/// <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()
            };
        }
Beispiel #2
0
        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;
			}
		}