private void WriteAst(HlslAst ast) { var compiler = new NodeCompiler(_registers); var rootGroups = ast.Roots.GroupBy(r => r.Key.RegisterKey); if (_registers.MethodOutputRegisters.Count == 1) { var rootGroup = rootGroups.Single(); var registerKey = rootGroup.Key; var roots = rootGroup.OrderBy(r => r.Key.ComponentIndex).Select(r => r.Value).ToList(); string statement = compiler.Compile(roots, 4); WriteLine($"return {statement};"); } else { foreach (var rootGroup in rootGroups) { var registerKey = rootGroup.Key; var roots = rootGroup.OrderBy(r => r.Key.ComponentIndex).Select(r => r.Value).ToList(); RegisterDeclaration outputRegister = _registers.MethodOutputRegisters[registerKey]; string statement = compiler.Compile(roots, roots.Count); WriteLine($"o.{outputRegister.Name} = {statement};"); } WriteLine(); WriteLine($"return o;"); } }
public uint GetRegisterFullLength(RegisterKey registerKey) { if (registerKey.Type == RegisterType.Const) { var constant = FindConstant(ParameterType.Float, registerKey.Number); return(constant.Columns); } RegisterDeclaration decl = _registerDeclarations[registerKey]; switch (decl.TypeName) { case "float": return(1); case "float2": return(2); case "float3": return(3); case "float4": return(4); default: throw new InvalidOperationException(); } }
public uint GetRegisterFullLength(RegisterKey registerKey) { if (registerKey.Type == RegisterType.Const) { var constant = FindConstant(registerKey.Number); var data = constant.GetRegisterTypeByOffset(registerKey.Number - constant.RegisterIndex); if (data.Type.ParameterType != ParameterType.Float) { throw new NotImplementedException(); } if (data.Type.ParameterClass == ParameterClass.MatrixColumns) { return(data.Type.Rows); } return(data.Type.Columns); } RegisterDeclaration decl = _registerDeclarations[registerKey]; switch (decl.TypeName) { case "float": return(1); case "float2": return(2); case "float3": return(3); case "float4": return(4); default: throw new InvalidOperationException(); } }
void WriteTemps() { Dictionary <RegisterKey, int> tempRegisters = new Dictionary <RegisterKey, int>(); foreach (var inst in _shader.Instructions) { foreach (var operand in inst.Operands) { if (operand is DestinationOperand dest) { if (dest.RegisterType == RegisterType.Temp) { var registerKey = new RegisterKey(dest.RegisterType, dest.RegisterNumber); if (!tempRegisters.ContainsKey(registerKey)) { var reg = new RegisterDeclaration(registerKey); _registers._registerDeclarations[registerKey] = reg; tempRegisters[registerKey] = (int)inst.GetDestinationWriteMask(); } else { tempRegisters[registerKey] |= (int)inst.GetDestinationWriteMask(); } } } } } if (tempRegisters.Count == 0) { return; } foreach (IGrouping <int, RegisterKey> group in tempRegisters.GroupBy( kv => kv.Value, kv => kv.Key)) { int writeMask = group.Key; string writeMaskName; switch (writeMask) { case 0x1: writeMaskName = "float"; break; case 0x3: writeMaskName = "float2"; break; case 0x7: writeMaskName = "float3"; break; case 0xF: writeMaskName = "float4"; break; default: // TODO writeMaskName = "float4"; break; //throw new NotImplementedException(); } WriteIndent(); WriteLine("{0} {1};", writeMaskName, string.Join(", ", group)); } }
private void Load(ShaderModel shader) { ConstantDeclarations = shader.ConstantTable.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 (uint 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.OfType <InstructionToken>().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: case RegisterType.Texture when shader.Type == ShaderType.Pixel: MethodInputRegisters.Add(registerKey, registerDeclaration); break; case RegisterType.Output: case RegisterType.ColorOut: case RegisterType.AttrOut when shader.MajorVersion == 3 && shader.Type == ShaderType.Vertex: 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); var registerNumber = instruction.GetParamRegisterNumber(destIndex); var registerKey = new RegisterKey(registerType, registerNumber); if (_registerDeclarations.ContainsKey(registerKey) == false) { var reg = new RegisterDeclaration(registerKey); _registerDeclarations[registerKey] = reg; switch (registerType) { case RegisterType.AttrOut: case RegisterType.ColorOut: case RegisterType.DepthOut: case RegisterType.Output: case RegisterType.RastOut: MethodOutputRegisters[registerKey] = reg; break; } } } } }