/// <summary> /// Registers are effectively shared between outputs of the previous stage /// and inputs of the next stage, so we don't need to do any mapping. We only /// need to keep track of the interpolation mode, and system value semantic, /// of the inputs. /// <seealso cref="http://msdn.microsoft.com/en-us/library/windows/desktop/bb509650(v=vs.85).aspx"/> /// /// TODO: Add some sort of runtime validation that signatures match. Direct3D /// does this, but only when debugging. /// </summary> public static ShaderOutputInputBindings FromShaderSignatures( OutputSignatureChunk outputSignature, BytecodeContainer inputShader) { var inputRegisterDeclarations = inputShader.Shader.DeclarationTokens .OfType<PixelShaderInputRegisterDeclarationToken>() .ToList(); // Only create a binding if the value is actually used in the next shader. // We can gather this information from the declaration tokens. If there is // no declaration token for an item, then it isn't used. var bindings = new List<ShaderOutputInputBinding>(); foreach (var inputParameter in inputShader.InputSignature.Parameters) { // Get register declaration for this parameter. If there is no register // declaration, then it isn't used, and we can move on. var inputRegisterDeclaration = FindInputRegisterDeclaration( inputRegisterDeclarations, inputParameter); if (inputRegisterDeclaration == null) continue; bindings.Add(new ShaderOutputInputBinding { Register = (int) inputParameter.Register, ComponentMask = inputParameter.Mask, InterpolationMode = inputRegisterDeclaration.InterpolationMode, SystemValueType = inputParameter.SystemValueType }); } return new ShaderOutputInputBindings { Bindings = bindings.ToArray() }; }
public static InputOutputSignatureChunk Parse(BytecodeReader reader, ChunkType chunkType, ProgramType programType) { InputOutputSignatureChunk result; switch (chunkType) { case ChunkType.Isgn: result = new InputSignatureChunk(); break; case ChunkType.Osgn: case ChunkType.Osg5: result = new OutputSignatureChunk(); break; case ChunkType.Pcsg: result = new PatchConstantSignatureChunk(); break; default: throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType); } var chunkReader = reader.CopyAtCurrentPosition(); var elementCount = chunkReader.ReadUInt32(); var uniqueKey = chunkReader.ReadUInt32(); SignatureElementSize elementSize; switch (chunkType) { case ChunkType.Osg5: elementSize = SignatureElementSize._7; break; case ChunkType.Isgn: case ChunkType.Osgn: case ChunkType.Pcsg: elementSize = SignatureElementSize._6; break; default: throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType); } for (int i = 0; i < elementCount; i++) { result.Parameters.Add(SignatureParameterDescription.Parse(reader, chunkReader, chunkType, elementSize, programType)); } return(result); }
public static InputOutputSignatureChunk Parse(BytecodeReader reader, ChunkType chunkType, ProgramType programType) { InputOutputSignatureChunk result; switch (chunkType) { case ChunkType.Isgn : result = new InputSignatureChunk(); break; case ChunkType.Osgn : case ChunkType.Osg5 : result = new OutputSignatureChunk(); break; case ChunkType.Pcsg : result = new PatchConstantSignatureChunk(); break; default : throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType); } var chunkReader = reader.CopyAtCurrentPosition(); var elementCount = chunkReader.ReadUInt32(); var uniqueKey = chunkReader.ReadUInt32(); SignatureElementSize elementSize; switch (chunkType) { case ChunkType.Osg5 : elementSize = SignatureElementSize._7; break; case ChunkType.Isgn: case ChunkType.Osgn: case ChunkType.Pcsg: elementSize = SignatureElementSize._6; break; default: throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType); } for (int i = 0; i < elementCount; i++) result.Parameters.Add(SignatureParameterDescription.Parse(reader, chunkReader, chunkType, elementSize, programType)); return result; }
internal IEnumerable<FragmentQuad> Execute( IEnumerable<InputAssemblerPrimitiveOutput> inputs, PrimitiveTopology primitiveTopology, OutputSignatureChunk previousStageOutputSignature, BytecodeContainer pixelShader, int multiSampleCount) { // TODO: Allow selection of different viewport. var viewport = _viewports[0]; var outputInputBindings = ShaderOutputInputBindings.FromShaderSignatures( previousStageOutputSignature, pixelShader); var rasterizer = PrimitiveRasterizerFactory.CreateRasterizer( primitiveTopology, State.Description, multiSampleCount, outputInputBindings, ref viewport, FragmentFilter); foreach (var primitive in inputs) { // Frustum culling. if (ViewportCuller.ShouldCullTriangle(primitive.Vertices)) continue; // TODO: Clipping. // http://simonstechblog.blogspot.tw/2012/04/software-rasterizer-part-2.html#softwareRasterizerDemo // Perspective divide. for (int i = 0; i < primitive.Vertices.Length; i++) PerspectiveDivide(ref primitive.Vertices[i].Position); // Backface culling. if (State.Description.CullMode != CullMode.None && rasterizer.ShouldCull(primitive.Vertices)) continue; // Transform from clip space to screen space. for (int i = 0; i < primitive.Vertices.Length; i++) viewport.MapClipSpaceToScreenSpace(ref primitive.Vertices[i].Position); // Rasterize. foreach (var fragmentQuad in rasterizer.Rasterize(primitive)) yield return fragmentQuad; } }