private string GetSrcReg(ShaderProgram Program, uint Reg, uint Idx = 0) { if (Reg >= 0x20 && Reg < 0x80) { ShaderUniformVec4 Uniform = Program.Vec4Uniforms[Reg - 0x20]; string Name = Vec4UniformNames[Reg - 0x20]; if (Uniform.IsConstant) { return(string.Format(CultureInfo.InvariantCulture, "vec4({0}, {1}, {2}, {3})", Uniform.Constant.X, Uniform.Constant.Y, Uniform.Constant.Z, Uniform.Constant.W)); } else if (Uniform.IsArray && Idx > 0) { //Min protects against illegal accesses (can cause glitches on some GPUs). Name = Vec4UniformNamesNoIdx[Reg - 0x20]; int Max = Uniform.ArrayLength - 1; switch (Idx) { case 1: return($"{Name}[min({Uniform.ArrayIndex} + {A0RegName}.x, {Max})]"); case 2: return($"{Name}[min({Uniform.ArrayIndex} + {A0RegName}.y, {Max})]"); case 3: return($"{Name}[min({Uniform.ArrayIndex} + {ALRegName}, {Max})]"); } } return(Name); } else if (Reg < 0x10) { return(InputNames[Reg]); } else if (Reg < 0x20) { return($"{TempRegName}[{Reg - 0x10}]"); } else { throw new InvalidOperationException($"Invalid register Index {Reg} used!"); } }
private void GenVec4Uniforms(StringBuilder Output, ShaderUniformVec4[] Uniforms, string[] Names, string Type) { for (int i = 0; i < Uniforms.Length; i++) { ShaderUniformVec4 Uniform = Uniforms[i]; if (Uniform?.IsConstant ?? true) { continue; } string Name = $"{Type}_{i - Uniform.ArrayIndex}_{GetValidName(Uniform.Name)}"; /* * For registers used as arrays, the name is stored with the * indexer ([0], [1], [2]...), but a version without the indexer * is also stored in Vec4UniformNamesNoIdx for GetSrcReg func, since it * needs indexed array access with illegal memory access protection. */ string Indexer = Uniform.IsArray ? $"[{Uniform.ArrayIndex}]" : string.Empty; Names[i] = Name + Indexer; if (Names == Vec4UniformNames) { Vec4UniformNamesNoIdx[i] = Name; } if (Uniform.ArrayIndex == 0) { if (Uniform.IsArray) { Output.AppendLine($"uniform {Type} {Name}[{Uniform.ArrayLength}];"); } else { Output.AppendLine($"uniform {Type} {Name};"); } } } }
private void GenLoop(ShaderProgram Program, ShaderInst3 Inst) { ShaderUniformVec4 Uniform = Program.IVec4Uniforms[Inst.RegId & 3]; string IUName = IVec4UniformNames[Inst.RegId & 3]; string ALStart; string ALCond; string ALInc; if (Uniform.IsConstant) { ALStart = $"{ALRegName} = {(byte)Uniform.Constant.Y}"; ALCond = $"{ALRegName} <= {(byte)Uniform.Constant.X}"; ALInc = $"{ALRegName} += {(byte)Uniform.Constant.Z}"; } else { ALStart = $"{ALRegName} = {IUName}.y"; ALCond = $"{ALRegName} <= {IUName}.x"; ALInc = $"{ALRegName} += {IUName}.z"; } Append($"for ({ALStart}; {ALCond}; {ALInc}) {{"); string OldIdent = Ident; Ident += "\t"; while (IP + 1 <= Inst.Dest) { GenInst(Program, SHBin.Executable[++IP]); } Ident = OldIdent; Append("}"); }