static void ParseInstructions(IrPass pass, IEnumerable <InstructionToken> instructions) { foreach (var token in instructions) { pass.Instructions.Add(ParseInstruction(token)); } }
/// <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)); } }
static void ParseLibrary(IrShader shader, BytecodeContainer container) { var libraryHeader = container.Chunks.OfType <LibHeaderChunk>().Single(); var libraryFunctions = container.Chunks.OfType <LibfChunk>().ToArray(); for (int i = 0; i < libraryFunctions.Length; i++) { var pass = new IrPass(libraryHeader.FunctionDescs[i].Name, IrPass.PassType.FunctionBody); InstructionParser.ParseTokens(pass, libraryFunctions[i].LibraryContainer.Shader.Tokens); shader.Passes.Add(pass); } }
public void WritePass(IrPass pass) { foreach (var attribute in pass.Attributes) { WriteAttribute(attribute); } WriteIndent(); WriteLineFormat("void {0}()", pass.Name); WriteIndent(); WriteLine("{"); IncreaseIndent(); foreach (var declaration in pass.Declarations) { WriteDeclrations(declaration); } foreach (var instruction in pass.Instructions) { Context.InstructionWriter.WriteInstruction(instruction); } DecreaseIndent(); WriteLine("}"); }
static void ParseDeclarations(IrPass pass, IEnumerable <DeclarationToken> declarations) { pass.Declarations = new List <DeclarationToken>(declarations); foreach (var token in declarations) { switch (token.Header.OpcodeType) { case OpcodeType.DclTessDomain: { var decl = token as TessellatorDomainDeclarationToken; pass.Attributes.Add(IrAttribute.Create("domain", decl.Domain.GetAttributeName())); } break; case OpcodeType.DclMaxOutputVertexCount: { var decl = token as GeometryShaderMaxOutputVertexCountDeclarationToken; pass.Attributes.Add(IrAttribute.Create("maxvertexcount", decl.MaxPrimitives)); } break; case OpcodeType.DclOutputControlPointCount: { var decl = token as ControlPointCountDeclarationToken; pass.Attributes.Add(IrAttribute.Create("outputcontrolpoints", decl.ControlPointCount)); } break; case OpcodeType.DclTessPartitioning: { var decl = token as TessellatorPartitioningDeclarationToken; pass.Attributes.Add(IrAttribute.Create("partitioning", decl.Partitioning.ToString().ToLower())); } break; case OpcodeType.DclHsMaxTessFactor: { var decl = token as HullShaderMaxTessFactorDeclarationToken; pass.Attributes.Add(IrAttribute.Create("maxtessfactor", decl.MaxTessFactor)); } break; case OpcodeType.DclTessOutputPrimitive: { var decl = token as TessellatorOutputPrimitiveDeclarationToken; pass.Attributes.Add(IrAttribute.Create("outputtopology", decl.OutputPrimitive.ToString().ToLower())); } break; case OpcodeType.DclThreadGroup: { var decl = token as ThreadGroupDeclarationToken; pass.Attributes.Add(IrAttribute.Create("numthreads", decl.Dimensions[0], decl.Dimensions[1], decl.Dimensions[2])); } break; } } }
public static void ParseTokens(IrPass pass, List <OpcodeToken> opcodes) { ParseDeclarations(pass, opcodes.OfType <DeclarationToken>()); ParseInstructions(pass, opcodes.OfType <InstructionToken>()); }