public static DebugInputOutputSignatureChunk Parse(DebugBytecodeReader reader, ChunkType chunkType,
                                                           ProgramType programType)
        {
            DebugInputOutputSignatureChunk result;

            switch (chunkType)
            {
            case ChunkType.Isgn:
            case ChunkType.Isg1:
                result = new DebugInputSignatureChunk();
                break;

            case ChunkType.Osgn:
            case ChunkType.Osg1:
            case ChunkType.Osg5:
                result = new DebugOutputSignatureChunk();
                break;

            case ChunkType.Pcsg:
                result = new DebugPatchConstantSignatureChunk();
                break;

            default:
                throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType);
            }

            var chunkReader  = reader.CopyAtCurrentPosition("ChunkReader", reader);
            var elementCount = chunkReader.ReadUInt32("ElementCount");
            var uniqueKey    = chunkReader.ReadUInt32("UniqueKey");

            SignatureElementSize elementSize;

            switch (chunkType)
            {
            case ChunkType.Isgn:
            case ChunkType.Osgn:
            case ChunkType.Pcsg:
                elementSize = SignatureElementSize._6;
                break;

            case ChunkType.Osg5:
                elementSize = SignatureElementSize._7;
                break;

            case ChunkType.Osg1:
            case ChunkType.Isg1:
                elementSize = SignatureElementSize._8;
                break;

            default:
                throw new ArgumentOutOfRangeException("chunkType", "Unrecognised chunk type: " + chunkType);
            }

            for (int i = 0; i < elementCount; i++)
            {
                result.Parameters.Add(DebugSignatureParameterDescription.Parse(reader, chunkReader, chunkType, elementSize,
                                                                               programType));
            }

            return(result);
        }
        public static DebugSignatureParameterDescription Parse(DebugBytecodeReader reader, DebugBytecodeReader parameterReader,
                                                               ChunkType chunkType, SignatureElementSize size, ProgramType programType)
        {
            uint stream = 0;

            if (size == SignatureElementSize._7 || size == SignatureElementSize._8)
            {
                stream = parameterReader.ReadUInt32("Stream");
            }
            uint nameOffset = parameterReader.ReadUInt32("NameOffset");
            var  nameReader = reader.CopyAtOffset("NameReader", parameterReader, (int)nameOffset);

            var result = new DebugSignatureParameterDescription
            {
                SemanticName    = nameReader.ReadString("SemanticName"),
                SemanticIndex   = parameterReader.ReadUInt32("SemanticIndex"),
                SystemValueType = (Name)parameterReader.ReadUInt32("SystemValueType"),
                ComponentType   = (RegisterComponentType)parameterReader.ReadUInt32("ComponentType"),
                Register        = parameterReader.ReadUInt32("Register"),
                Stream          = stream,
            };

            result.Mask          = parameterReader.ReadEnum8 <ComponentMask>("Mask");
            result.ReadWriteMask = parameterReader.ReadEnum8 <ComponentMask>("ReadWriteMask");
            parameterReader.ReadUInt16("MaskPadding");

            if (size == SignatureElementSize._8)
            {
                MinPrecision minPrecision = parameterReader.ReadEnum32 <MinPrecision>("MinPrecision");
                result.MinPrecision = minPrecision;
            }

            // This is my guesswork, but it works so far...
            if (chunkType == ChunkType.Osg5 ||
                chunkType == ChunkType.Osgn ||
                chunkType == ChunkType.Osg1 ||
                (chunkType == ChunkType.Pcsg && programType == ProgramType.HullShader))
            {
                result.ReadWriteMask = (ComponentMask)(ComponentMask.All - result.ReadWriteMask);
            }

            // Vertex and pixel shaders need special handling for SystemValueType in the output signature.
            if ((programType == ProgramType.PixelShader || programType == ProgramType.VertexShader) &&
                (chunkType == ChunkType.Osg5 || chunkType == ChunkType.Osgn || chunkType == ChunkType.Osg1))
            {
                if (result.Register == 0xffffffff)
                {
                    switch (result.SemanticName.ToUpper())
                    {
                    case "SV_DEPTH":
                        result.SystemValueType = Name.Depth;
                        break;

                    case "SV_COVERAGE":
                        result.SystemValueType = Name.Coverage;
                        break;

                    case "SV_DEPTHGREATEREQUAL":
                        result.SystemValueType = Name.DepthGreaterEqual;
                        break;

                    case "SV_DEPTHLESSEQUAL":
                        result.SystemValueType = Name.DepthLessEqual;
                        break;

                    case "SV_STENCILREF":
                        result.SystemValueType = Name.StencilRef;
                        break;
                    }
                }
                else if (programType == ProgramType.PixelShader)
                {
                    result.SystemValueType = Name.Target;
                }
            }

            return(result);
        }