/// <summary> /// Split instructions into seperate phases. /// </summary> /// <param name="programChunk"></param> static void ParseShaderChunk(IrShader shader, ShaderProgramChunk programChunk) { Func <OpcodeToken, int, bool> NotSplitToken = (OpcodeToken token, int index) => index == 0 || token.Header.OpcodeType != OpcodeType.HsForkPhase && token.Header.OpcodeType != OpcodeType.HsJoinPhase && token.Header.OpcodeType != OpcodeType.Label; int i = 0; while (i < programChunk.Tokens.Count) { var tokens = programChunk.Tokens.Skip(i).TakeWhile(NotSplitToken).ToList(); if (i == 0) { var type = programChunk.Version.ProgramType.GetPassType(); var pass = new IrPass(tokens, programChunk.Version.ProgramType.ToString(), type); InstructionParser.ParseTokens(pass, tokens); pass.InputSignature = shader.Signatures.First(s => s.SignatureType == IrSignatureType.Input); pass.OutputSignature = shader.Signatures.First(s => s.SignatureType == IrSignatureType.Output); shader.Passes.Add(pass); } else if (tokens[0].Header.OpcodeType == OpcodeType.Label) { var index = (tokens[0] as InstructionToken).Operands[0].Indices[0].Value; var pass = new IrPass($"Label{index}", IrPass.PassType.FunctionBody); InstructionParser.ParseTokens(pass, tokens); shader.Passes.Add(pass); } else if (tokens[0].Header.OpcodeType == OpcodeType.HsForkPhase) { var index = shader.Passes.Select(p => p.Type == IrPass.PassType.HullShaderForkPhase).Count(); var pass = new IrPass($"HullForkPhase{index}", IrPass.PassType.HullShaderForkPhase); InstructionParser.ParseTokens(pass, tokens); shader.Passes.Add(pass); } else { var index = shader.Passes.Select(p => p.Type == IrPass.PassType.HullShaderJoinPhase).Count(); var pass = new IrPass(tokens, $"HullJoinPhase{index}", IrPass.PassType.HullShaderJoinPhase); InstructionParser.ParseTokens(pass, tokens); shader.Passes.Add(pass); } i += tokens.Count; } shader.InterfaceManger?.Parse(shader, programChunk.Container); if (programChunk.Version.ProgramType == ProgramType.HullShader) { string patchConstantPassName = "HullPatchConstant"; shader.Passes.Add(new IrPass("HullPatchConstant", IrPass.PassType.HullShaderPatchConstantPhase)); var ctrlPointPass = shader.Passes.First(p => p.Type == IrPass.PassType.HullShaderControlPointPhase); ctrlPointPass.Attributes.Add(IrAttribute.Create("patchconstantfunc", patchConstantPassName)); } }
public static BytecodeChunk ParseChunk(BytecodeReader chunkReader, BytecodeContainer container) { // Type of chunk this is. uint fourCc = chunkReader.ReadUInt32(); // Total length of the chunk in bytes. uint chunkSize = chunkReader.ReadUInt32(); ChunkType chunkType; if (KnownChunkTypes.ContainsKey(fourCc)) { chunkType = KnownChunkTypes[fourCc]; } else { System.Diagnostics.Debug.Assert(false, "Chunk type '" + fourCc.ToFourCcString() + "' is not yet supported."); System.Diagnostics.Debug.WriteLine("Chunk type '" + fourCc.ToFourCcString() + "' is not yet supported."); return(null); } var chunkContentReader = chunkReader.CopyAtCurrentPosition((int)chunkSize); BytecodeChunk chunk; switch (chunkType) { case ChunkType.Ifce: chunk = InterfacesChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Isgn: case ChunkType.Osgn: case ChunkType.Osg5: case ChunkType.Pcsg: case ChunkType.Isg1: case ChunkType.Osg1: chunk = InputOutputSignatureChunk.Parse(chunkContentReader, chunkType, container.Version.ProgramType); break; case ChunkType.Rdef: chunk = ResourceDefinitionChunk.Parse(chunkContentReader); break; case ChunkType.Sdbg: case ChunkType.Spdb: chunk = DebuggingChunk.Parse(chunkContentReader, chunkType, chunkSize); break; case ChunkType.Sfi0: chunk = Sfi0Chunk.Parse(chunkContentReader, container.Version, chunkSize); break; case ChunkType.Shdr: case ChunkType.Shex: chunk = ShaderProgramChunk.Parse(chunkContentReader); break; case ChunkType.Stat: chunk = StatisticsChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Xnas: case ChunkType.Xnap: case ChunkType.Aon9: chunk = Level9ShaderChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Priv: chunk = PrivateChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Rts0: chunk = RootSignatureChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Libf: chunk = LibfChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Libh: chunk = LibHeaderChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Lfs0: chunk = LibraryParameterSignatureChunk.Parse(chunkContentReader, chunkSize); break; default: throw new ParseException("Invalid chunk type: " + chunkType); } chunk.Container = container; chunk.FourCc = fourCc; chunk.ChunkSize = chunkSize; chunk.ChunkType = chunkType; return(chunk); }
public static RequiredRegisters FromShader(ShaderProgramChunk shader) { var result = new RequiredRegisters(); foreach (var declarationToken in shader.DeclarationTokens) { OperandIndex[] indices = (declarationToken.Operand != null) ? declarationToken.Operand.Indices : new OperandIndex[0]; var indexDimension = (declarationToken.Operand != null) ? declarationToken.Operand.IndexDimension : OperandIndexDimension._0D; switch (declarationToken.Header.OpcodeType) { case OpcodeType.DclInput: case OpcodeType.DclInputPs: case OpcodeType.DclInputPsSgv: case OpcodeType.DclInputPsSiv: case OpcodeType.DclInputSgv: case OpcodeType.DclInputSiv: switch (indexDimension) { case OperandIndexDimension._2D: result.NumPrimitives = (int)indices[0].Value; result.Inputs = Math.Max(result.Inputs, (int)indices[1].Value + 1); break; case OperandIndexDimension._1D: result.NumPrimitives = 1; result.Inputs = (int)indices[0].Value + 1; break; default: throw new ArgumentOutOfRangeException(); } break; case OpcodeType.DclOutput: case OpcodeType.DclOutputSgv: case OpcodeType.DclOutputSiv: result.Outputs = (int)indices[0].Value + 1; break; case OpcodeType.DclResource: result.Resources.Add(((ResourceDeclarationToken)declarationToken).ResourceDimension); break; case OpcodeType.DclSampler: result.Samplers = (int)indices[0].Value + 1; break; case OpcodeType.DclConstantBuffer: while (result.ConstantBuffers.Count < (int)indices[0].Value + 1) { result.ConstantBuffers.Add(0); } result.ConstantBuffers[(int)indices[0].Value] = (int)indices[1].Value; break; case OpcodeType.DclIndexableTemp: while (result.IndexableTemps.Count < (int)indices[0].Value + 1) { result.IndexableTemps.Add(0); } result.IndexableTemps[(int)indices[0].Value] = (int)indices[1].Value + 1; break; case OpcodeType.DclTemps: result.Temps = (int)((TempRegisterDeclarationToken)declarationToken).TempCount; break; } } return(result); }