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 int 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(); } }
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; } } } } }
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, (int)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(); } WriteLine("{0} {1};", writeMaskName, string.Join(", ", group)); } }