/// <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)); }
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)); }