public void WriteShader(IrShader shader) { foreach (var comment in shader.PreComments) { WriteIndent(); WriteLine(comment); } if (shader.ResourceDefinition != null) { Context.ResourceDefinitionWriter.WriteResourceDefinition(shader.ResourceDefinition); } if (shader.InterfaceManger != null) { Context.InterfaceWriter.WriteInterface(shader.InterfaceManger); } foreach (var signature in shader.Signatures) { Context.SignatureWriter.WriteSignature(signature); } foreach (var pass in shader.Passes) { Context.PassWriter.WritePass(pass); } if (shader.Effect != null) { Context.EffectWriter.WriteEffect(shader.Effect); } foreach (var comment in shader.PostComments) { WriteIndent(); WriteLine(comment); } }
/// <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 DecompileContext(StringWriter writer, IrShader shader) { Writer = writer; Shader = shader; ShaderWriter = new ShaderWriter(this); PassWriter = new PassWriter(this); EffectWriter = new EffectWriter(this); InstructionWriter = new InstructionWriter(this); OperandWriter = new OperandWriter(this); ResourceDefinitionWriter = new ResourceDefinitionWriter(this); InterfaceWriter = new InterfaceWriter(this); SignatureWriter = new SignatureWriter(this); }
public static void Parse(IrShader shader, ResourceDefinitionChunk chunk) { var rdef = new IrResourceDefinition(chunk); shader.ResourceDefinition = rdef; rdef.ResourceBindingsDebug = DisassembleBindings(chunk.ResourceBindings, chunk.Target.IsSM51); rdef.ResourceBindings = new List <IrResourceBinding>(); foreach (var binding in chunk.ResourceBindings) { rdef.ResourceBindings.Add(ParseBinding(binding)); } rdef.ConstantBuffersDebug = DisassembleBuffers(chunk.ConstantBuffers); rdef.ConstantBuffers = new List <IrConstantBuffer>(); foreach (var cbuffer in chunk.ConstantBuffers) { rdef.ConstantBuffers.Add(ParseBuffer(cbuffer)); } }
static void ParseEffect(IrShader shader, BytecodeContainer container) { var effect = container.Chunks.OfType <EffectChunk>().Single(); shader.Effect = new IrEffect(effect); foreach (var variable in effect.LocalVariables) { foreach (var effectShader in variable.ShaderData) { var chunk = effectShader.Shader?.Shader; if (chunk == null) { continue; } //shader.Passes.Add(new IrPass(chunk)); } foreach (var effectShader in variable.ShaderData5) { var chunk = effectShader.Shader.Shader; //shader.Passes.Add(new IrPass(chunk)); } } }
public static IrShader Parse(BytecodeContainer container) { var shader = new IrShader(); if (container.Version.ProgramType == ProgramType.LibraryShader) { ParseLibrary(shader, container); return(shader); } if (container.Version.ProgramType == ProgramType.EffectsShader) { ParseEffect(shader, container); return(shader); } ResourceDefinitionParser.Parse(shader, container.ResourceDefinition); if (container.Interfaces != null) { shader.InterfaceManger = new IrInterfaceManger(container.Interfaces); } if (container.InputSignature != null) { shader.Signatures.Add(new IrSignature( container.InputSignature, $"{container.Version.ProgramType}Input", IrSignatureType.Input)); } if (container.OutputSignature != null) { shader.Signatures.Add(new IrSignature( container.OutputSignature, $"{container.Version.ProgramType}Output", IrSignatureType.Output)); } ParseShaderChunk(shader, container.Shader); return(shader); }