예제 #1
0
        /// <summary>
        /// Executes the shader. First, the input value is set into the input registers.
        /// Then the shader is executed. Finally, the output value is extracted from
        /// the output registers.
        /// </summary>
        /// <typeparam name="TInput">Input type. This must be a struct whose byte count
        /// exactly matches the shader input.</typeparam>
        /// <typeparam name="TOutput">Output type. This must be a struct whose byte count
        /// exactly matches the shader output.</typeparam>
        /// <param name="input">Input to the shader.</param>
        /// <returns>Shader output.</returns>
        public TOutput Execute <TInput, TOutput>(TInput input)
            where TInput : struct
            where TOutput : struct
        {
            // Validate.
            if (StructUtility.SizeOf <TInput>() != _inputSignatureSize)
            {
                throw new ArgumentException(string.Format("Expected input struct to be {0} bytes, but was {1}'",
                                                          _inputSignatureSize, StructUtility.SizeOf <TInput>()));
            }

            // Set input parameters into virtual machine registers. Use knowledge of byte size of each
            // parameter to extract the right values from the input.
            var inputBytes     = StructUtility.ToBytes(input);
            var inputByteIndex = 0;

            for (int i = 0; i < _inputSignature.Parameters.Count; i++)
            {
                var inputParameter = _inputSignature.Parameters[i];
                var registerBytes  = new byte[Number4.SizeInBytes];
                Array.Copy(inputBytes, inputByteIndex, registerBytes, 0, inputParameter.ByteCount);
                _virtualMachine.SetInputRegisterValue(ContextIndex, 0, i, Number4.FromByteArray(registerBytes, 0));
                inputByteIndex += inputParameter.ByteCount;
            }

            // Execute shader.
            _virtualMachine.Execute();

            // Get output parameters from virtual machine registers.
            var outputBytes     = new byte[_outputSignatureSize];
            var outputByteIndex = 0;

            for (var i = 0; i < _outputSignature.Parameters.Count; i++)
            {
                var outputParameter = _outputSignature.Parameters[i];
                var registerBytes   = _virtualMachine.GetOutputRegisterValue(ContextIndex, i).RawBytes;
                Array.Copy(registerBytes, 0, outputBytes, outputByteIndex, outputParameter.ByteCount);
                outputByteIndex += outputParameter.ByteCount;
            }
            return(StructUtility.FromBytes <TOutput>(outputBytes));
        }
예제 #2
0
        public static BasicHlsl.VertexShaderOutput ExecuteVertexShader(string compiledShaderFile,
                                                                       BasicHlsl.ConstantBufferGlobals globals, VertexPositionNormalTexture vertex)
        {
            var device = new Device(DriverType.Warp);

            var vertexShaderBytes    = File.ReadAllBytes(compiledShaderFile);
            var vertexShaderBytecode = new ShaderBytecode(vertexShaderBytes);
            var vertexShader         = new VertexShader(device, vertexShaderBytecode);

            var layout = new InputLayout(device,
                                         ShaderSignature.GetInputSignature(vertexShaderBytecode),
                                         new[]
            {
                new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                new InputElement("NORMAL", 0, Format.R32G32B32_Float, 16, 0),
                new InputElement("TEXCOORD", 0, Format.R32G32_Float, 28, 0)
            });

            var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[] { vertex });

            var constantBuffer = Buffer.Create(device, ref globals, new BufferDescription
            {
                BindFlags      = BindFlags.ConstantBuffer,
                CpuAccessFlags = CpuAccessFlags.None,
                Usage          = ResourceUsage.Default
            });

            var geometryShader = new GeometryShader(device, vertexShaderBytecode,
                                                    new[]
            {
                new StreamOutputElement {
                    SemanticName = "SV_POSITION", ComponentCount = 4
                },
                new StreamOutputElement {
                    SemanticName = "COLOR", ComponentCount = 4
                },
                new StreamOutputElement {
                    SemanticName = "TEXCOORD", ComponentCount = 2
                }
            },
                                                    BasicHlsl.VertexShaderOutput.SizeInBytes);

            var outputBuffer = Buffer.Create(device, new BasicHlsl.VertexShaderOutput[1],
                                             new BufferDescription
            {
                CpuAccessFlags = CpuAccessFlags.None,
                BindFlags      = BindFlags.StreamOutput,
                Usage          = ResourceUsage.Default
            });

            var stagingBuffer = Buffer.Create(device, new BasicHlsl.VertexShaderOutput[1],
                                              new BufferDescription
            {
                CpuAccessFlags = CpuAccessFlags.Read,
                BindFlags      = BindFlags.None,
                Usage          = ResourceUsage.Staging
            });

            device.InputAssembler.InputLayout       = layout;
            device.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList;
            device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, VertexPositionNormalTexture.SizeInBytes, 0));
            device.VertexShader.SetConstantBuffer(0, constantBuffer);
            device.VertexShader.Set(vertexShader);
            device.GeometryShader.Set(geometryShader);
            device.StreamOutput.SetTargets(new StreamOutputBufferBinding(outputBuffer, 0));

            device.Draw(1, 0);

            device.CopyResource(outputBuffer, stagingBuffer);
            device.Flush();

            var stream = stagingBuffer.Map(MapMode.Read, SharpDX.Direct3D10.MapFlags.None);
            var bytes  = new byte[BasicHlsl.VertexShaderOutput.SizeInBytes];

            stream.Read(bytes, 0, bytes.Length);
            stream.Dispose();

            outputBuffer.Dispose();
            vertices.Dispose();
            layout.Dispose();
            geometryShader.Dispose();
            vertexShader.Dispose();
            vertexShaderBytecode.Dispose();
            device.Dispose();

            return(StructUtility.FromBytes <BasicHlsl.VertexShaderOutput>(bytes));
        }