virtual public ShaderModel ReadShader() { // Version token byte minorVersion = ReadByte(); byte majorVersion = ReadByte(); ShaderType shaderType = (ShaderType)ReadUInt16(); if (shaderType == ShaderType.Fx) { throw new Exception("FX shaders currently not supported"); } Debug.Assert(shaderType == ShaderType.Pixel || shaderType == ShaderType.Vertex || shaderType == ShaderType.Fx, $"Shader does not contain a valid shader type {shaderType}"); var shader = new ShaderModel(majorVersion, minorVersion, shaderType); while (true) { Token instruction = ReadInstruction(shader); InstructionVerifier.Verify(instruction); shader.Tokens.Add(instruction); if (instruction.Opcode == Opcode.End) { break; } } shader.ParseConstantTable(); return(shader); }
public static string Decompile(ShaderModel shaderModel, string entryPoint = null) { if (shaderModel.Type == ShaderType.Effect) { return(EffectHLSLWriter.Decompile(shaderModel.EffectChunk)); } var hlslWriter = new HlslWriter(shaderModel, false, entryPoint); return(hlslWriter.Decompile()); }
private void LoadConstantOutputs(ShaderModel shader) { IList <ConstantDeclaration> constantTable = shader.ParseConstantTable().ConstantDeclarations; _activeOutputs = new Dictionary <RegisterComponentKey, HlslTreeNode>(); _samplers = new Dictionary <RegisterKey, HlslTreeNode>(); foreach (var constant in constantTable) { if (constant.RegisterSet == RegisterSet.Sampler) { var registerKey = new RegisterKey(RegisterType.Sampler, constant.RegisterIndex); var destinationKey = new RegisterComponentKey(registerKey, 0); int samplerTextureDimension; switch (constant.ParameterType) { case ParameterType.Sampler1D: samplerTextureDimension = 1; break; case ParameterType.Sampler2D: samplerTextureDimension = 2; break; case ParameterType.Sampler3D: case ParameterType.SamplerCube: samplerTextureDimension = 3; break; default: throw new InvalidOperationException(); } var shaderInput = new RegisterInputNode(destinationKey, samplerTextureDimension); _samplers.Add(registerKey, shaderInput); } else { for (int r = 0; r < constant.RegisterCount; r++) { if (constant.ParameterType != ParameterType.Float) { throw new NotImplementedException(); } var registerKey = new RegisterKey(RegisterType.Const, constant.RegisterIndex + r); for (int i = 0; i < 4; i++) { var destinationKey = new RegisterComponentKey(registerKey, i); var shaderInput = new RegisterInputNode(destinationKey); _activeOutputs.Add(destinationKey, shaderInput); } } } } }
public static string Disassemble(ShaderModel shaderModel) { if (shaderModel.Type == ShaderType.Effect) { var effectWriter = new EffectAsmWriter(shaderModel.EffectChunk); return(effectWriter.Decompile()); } var asmWriter = new AsmWriter(shaderModel); return(asmWriter.Decompile()); }
public HlslWriter(ShaderModel shader, bool doAstAnalysis = false, string entryPoint = null) { _shader = shader; _doAstAnalysis = doAstAnalysis; if (string.IsNullOrEmpty(entryPoint)) { _entryPoint = $"{_shader.Type}Main"; } else { _entryPoint = entryPoint; } }
public static string Decompile(ShaderModel shaderModel) { var hlslWriter = new HlslWriter(shaderModel); using (var stream = new MemoryStream()) { hlslWriter.Write(stream); stream.Position = 0; using (var reader = new StreamReader(stream, Encoding.UTF8)) { return(reader.ReadToEnd()); } } }
public static string Disassemble(ShaderModel shaderModel) { var asmWriter = new AsmWriter(shaderModel); using (var stream = new MemoryStream()) { asmWriter.Write(stream); stream.Position = 0; using (var reader = new StreamReader(stream, Encoding.UTF8)) { return(reader.ReadToEnd()); } } }
private void WriteExpression(ShaderModel shader) { WriteLine("void {0}Preshader(){{", _entryPoint); Indent++; WriteLine($"// {shader.Type}_{shader.MajorVersion}_{shader.MinorVersion}"); foreach (var token in shader.Fxlc.Tokens) { WriteLine($"// {token.ToString(shader.ConstantTable, shader.Cli)}"); } if (shader.Prsi != null) { WriteLine(shader.Prsi.Dump()); } Indent++; WriteLine("}"); }
static public ShaderModel ReadShader(byte[] data) { byte minorVersion = data[0]; byte majorVersion = data[1]; ShaderType shaderType = (ShaderType)BitConverter.ToUInt16(data, 2); if (shaderType == ShaderType.Effect) { var _shader = new ShaderModel(majorVersion, minorVersion, shaderType); var bytecodeReader = new BytecodeReader(data, 4, data.Length - 4); _shader.EffectChunk = FX9.EffectContainer.Parse(bytecodeReader, (uint)(data.Length - 4)); return(_shader); } var reader = new BytecodeReader(data, 0, data.Length); return(ShaderModel.Parse(reader)); }
public HlslAst Parse(ShaderModel shader) { LoadConstantOutputs(shader); int instructionPointer = 0; bool ifBlock = false; while (instructionPointer < shader.Tokens.Count) { var instruction = shader.Tokens[instructionPointer]; if (ifBlock) { if (instruction.Opcode == Opcode.Else) { ifBlock = false; } } else { if (instruction.Opcode == Opcode.IfC) { ifBlock = true; } ParseInstruction(instruction); } instructionPointer++; } Dictionary <RegisterComponentKey, HlslTreeNode> roots; if (shader.Type == ShaderType.Pixel) { roots = _activeOutputs .Where(o => o.Key.Type == RegisterType.ColorOut) .ToDictionary(o => o.Key, o => o.Value); } else { roots = _activeOutputs .Where(o => o.Key.Type == RegisterType.Output) .ToDictionary(o => o.Key, o => o.Value); } return(new HlslAst(roots)); }
public static ShaderModel Parse(BytecodeReader reader) { var result = new ShaderModel(); result.MinorVersion = reader.ReadByte(); result.MajorVersion = reader.ReadByte(); result.Type = (ShaderType)reader.ReadUInt16(); while (true) { var instruction = result.ReadInstruction(reader); if (instruction == null) { continue; } result.Tokens.Add(instruction); if (instruction.Opcode == Opcode.End) { break; } } return(result); }
public Token(Opcode opcode, int numParams, ShaderModel shaderModel) { Opcode = opcode; Data = new uint[numParams]; _shaderModel = shaderModel; }
public AsmWriter(ShaderModel shader) { this.shader = shader; constantTable = shader.ParseConstantTable(); }
public AsmWriter(ShaderModel shader) { this.shader = shader; }
public CommentToken(Opcode opcode, int length, ShaderModel shaderModel) : base(opcode, length, shaderModel) { }
private void Load(ShaderModel shader) { ConstantDeclarations = shader.ParseConstantTable().ConstantDeclarations; foreach (var constantDeclaration in ConstantDeclarations) { RegisterType registerType; switch (constantDeclaration.RegisterSet) { case RegisterSet.Bool: registerType = RegisterType.ConstBool; break; case RegisterSet.Float4: registerType = RegisterType.Const; break; case RegisterSet.Int4: registerType = RegisterType.ConstInt; break; case RegisterSet.Sampler: registerType = RegisterType.Sampler; break; default: throw new InvalidOperationException(); } if (registerType == RegisterType.Sampler) { // Use declaration from declaration instruction instead continue; } for (int r = 0; r < constantDeclaration.RegisterCount; r++) { var registerKey = new RegisterKey(registerType, constantDeclaration.RegisterIndex + r); var registerDeclaration = new RegisterDeclaration(registerKey); _registerDeclarations.Add(registerKey, registerDeclaration); } } foreach (var instruction in shader.Tokens.Where(i => i.HasDestination)) { if (instruction.Opcode == Opcode.Dcl) { var registerDeclaration = new RegisterDeclaration(instruction); RegisterKey registerKey = registerDeclaration.RegisterKey; _registerDeclarations.Add(registerKey, registerDeclaration); switch (registerKey.Type) { case RegisterType.Input: case RegisterType.MiscType: MethodInputRegisters.Add(registerKey, registerDeclaration); break; case RegisterType.Output: case RegisterType.ColorOut: MethodOutputRegisters.Add(registerKey, registerDeclaration); break; case RegisterType.Sampler: case RegisterType.Addr: break; default: throw new Exception($"Unexpected dcl {registerKey.Type}"); } } else if (instruction.Opcode == Opcode.Def) { var constant = new Constant( instruction.GetParamRegisterNumber(0), instruction.GetParamSingle(1), instruction.GetParamSingle(2), instruction.GetParamSingle(3), instruction.GetParamSingle(4)); _constantDefinitions.Add(constant); } else if (instruction.Opcode == Opcode.DefI) { var constantInt = new ConstantInt(instruction.GetParamRegisterNumber(0), instruction.Data[1], instruction.Data[2], instruction.Data[3], instruction.Data[4]); _constantIntDefinitions.Add(constantInt); } else { // Find all assignments to color outputs, because pixel shader outputs are not declared. int destIndex = instruction.GetDestinationParamIndex(); RegisterType registerType = instruction.GetParamRegisterType(destIndex); int registerNumber = instruction.GetParamRegisterNumber(destIndex); var registerKey = new RegisterKey(registerType, registerNumber); if (_registerDeclarations.ContainsKey(registerKey) == false) { var reg = new RegisterDeclaration(registerKey); _registerDeclarations[registerKey] = reg; if (registerType == RegisterType.ColorOut || registerType == RegisterType.RastOut || registerType == RegisterType.Output || registerType == RegisterType.AttrOut) { MethodOutputRegisters[registerKey] = reg; } } } } }
public RegisterState(ShaderModel shader) { Load(shader); }
public static BytecodeContainer ConvertToDXBC(ShaderModel shaderModel) { var container = new BytecodeContainer(); return(container); }
public InstructionToken(Opcode opcode, int length, ShaderModel shaderModel) : base(opcode, length, shaderModel) { Operands = new List <Operand>(); }
private Token ReadInstruction(ShaderModel shaderModel) { uint instructionToken = ReadUInt32(); Opcode opcode = (Opcode)(instructionToken & 0xffff); Debug.Assert(opcode <= Opcode.Breakp || (opcode >= Opcode.Phase && opcode <= Opcode.End), $"Invalid opcode {opcode}"); int size; if (opcode == Opcode.Comment) { size = (int)((instructionToken >> 16) & 0x7FFF); } else { size = (int)((instructionToken >> 24) & 0x0f); } Token token = null; if (opcode == Opcode.Comment) { token = new CommentToken(opcode, size, shaderModel); for (int i = 0; i < size; i++) { token.Data[i] = ReadUInt32(); } } else { token = new InstructionToken(opcode, size, shaderModel); var inst = token as InstructionToken; for (int i = 0; i < size; i++) { token.Data[i] = ReadUInt32(); if (opcode == Opcode.Def || opcode == Opcode.DefB || opcode == Opcode.DefI) { } else if (opcode == Opcode.Dcl) { if (i == 0) { inst.Operands.Add(new DeclarationOperand(token.Data[i])); } else { inst.Operands.Add(new DestinationOperand(token.Data[i])); } } else if (i == 0 && opcode != Opcode.BreakC && opcode != Opcode.IfC && opcode != Opcode.If) { inst.Operands.Add(new DestinationOperand(token.Data[i])); } else if ((token.Data[i] & (1 << 13)) != 0) { //Relative Address mode token.Data[i + 1] = ReadUInt32(); inst.Operands.Add(new SourceOperand(token.Data[i], token.Data[i + 1])); i++; } else { inst.Operands.Add(new SourceOperand(token.Data[i])); } } } if (opcode != Opcode.Comment) { token.Modifier = (int)((instructionToken >> 16) & 0xff); token.Predicated = (instructionToken & 0x10000000) != 0; token.CoIssue = (instructionToken & 0x40000000) != 0; Debug.Assert((instructionToken & 0xA0000000) == 0, $"Instruction has unexpected bits set {instructionToken & 0xE0000000}"); } return(token); }
public HlslWriter(ShaderModel shader, bool doAstAnalysis = false) { _shader = shader; _doAstAnalysis = doAstAnalysis; }