summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h10
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp119
2 files changed, 120 insertions, 9 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index f4d11fa5d..f3ca30cfa 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -19,7 +19,10 @@ namespace Tegra {
19namespace Shader { 19namespace Shader {
20 20
21struct Register { 21struct Register {
22 // Register 255 is special cased to always be 0 22 /// Number of registers
23 static constexpr size_t NumRegisters = 256;
24
25 /// Register 255 is special cased to always be 0
23 static constexpr size_t ZeroIndex = 255; 26 static constexpr size_t ZeroIndex = 255;
24 27
25 constexpr Register() = default; 28 constexpr Register() = default;
@@ -48,6 +51,11 @@ struct Register {
48 return ~value; 51 return ~value;
49 } 52 }
50 53
54 u64 GetSwizzledIndex(u64 elem) const {
55 elem = (value + elem) & 3;
56 return (value & ~3) + elem;
57 }
58
51private: 59private:
52 u64 value{}; 60 u64 value{};
53}; 61};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 3dffb205d..3716bb782 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -146,6 +146,90 @@ private:
146 std::string shader_source; 146 std::string shader_source;
147}; 147};
148 148
149/**
150 * Represents an emulated shader register, used to track the state of that register for emulation
151 * with GLSL. At this time, a register can be used as a float or an integer. This class is used for
152 * bookkeeping within the GLSL program.
153 */
154class GLSLRegister {
155public:
156 GLSLRegister(size_t index, ShaderWriter& shader)
157 : index{index}, shader{shader}, float_str{"freg_" + std::to_string(index)},
158 integer_str{"ireg_" + std::to_string(index)} {}
159
160 /// Returns a GLSL string representing the current state of the register
161 const std::string& GetActiveString() {
162 declr_type.insert(active_type);
163
164 switch (active_type) {
165 case Type::Float:
166 return float_str;
167 case Type::Integer:
168 return integer_str;
169 }
170
171 UNREACHABLE();
172 return float_str;
173 }
174
175 /// Returns a GLSL string representing the register as a float
176 const std::string& GetFloatString() const {
177 ASSERT(IsFloatUsed());
178 return float_str;
179 }
180
181 /// Returns a GLSL string representing the register as an integer
182 const std::string& GetIntegerString() const {
183 ASSERT(IsIntegerUsed());
184 return integer_str;
185 }
186
187 /// Convert the current register state from float to integer
188 void FloatToInteger() {
189 ASSERT(active_type == Type::Float);
190
191 const std::string src = GetActiveString();
192 active_type = Type::Integer;
193 const std::string dest = GetActiveString();
194
195 shader.AddLine(dest + " = floatBitsToInt(" + src + ");");
196 }
197
198 /// Convert the current register state from integer to float
199 void IntegerToFloat() {
200 ASSERT(active_type == Type::Integer);
201
202 const std::string src = GetActiveString();
203 active_type = Type::Float;
204 const std::string dest = GetActiveString();
205
206 shader.AddLine(dest + " = intBitsToFloat(" + src + ");");
207 }
208
209 /// Returns true if the register was ever used as a float, used for register declarations
210 bool IsFloatUsed() const {
211 return declr_type.find(Type::Float) != declr_type.end();
212 }
213
214 /// Returns true if the register was ever used as an integer, used for register declarations
215 bool IsIntegerUsed() const {
216 return declr_type.find(Type::Integer) != declr_type.end();
217 }
218
219private:
220 enum class Type {
221 Float,
222 Integer,
223 };
224
225 const size_t index;
226 const std::string float_str;
227 const std::string integer_str;
228 ShaderWriter& shader;
229 Type active_type{Type::Float};
230 std::set<Type> declr_type;
231};
232
149class GLSLGenerator { 233class GLSLGenerator {
150public: 234public:
151 GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code, 235 GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
@@ -153,6 +237,7 @@ public:
153 : subroutines(subroutines), program_code(program_code), main_offset(main_offset), 237 : subroutines(subroutines), program_code(program_code), main_offset(main_offset),
154 stage(stage) { 238 stage(stage) {
155 239
240 BuildRegisterList();
156 Generate(); 241 Generate();
157 } 242 }
158 243
@@ -166,6 +251,13 @@ public:
166 } 251 }
167 252
168private: 253private:
254 /// Build the GLSL register list
255 void BuildRegisterList() {
256 for (size_t index = 0; index < Register::NumRegisters; ++index) {
257 regs.emplace_back(index, shader);
258 }
259 }
260
169 /// Gets the Subroutine object corresponding to the specified address. 261 /// Gets the Subroutine object corresponding to the specified address.
170 const Subroutine& GetSubroutine(u32 begin, u32 end) const { 262 const Subroutine& GetSubroutine(u32 begin, u32 end) const {
171 auto iter = subroutines.find(Subroutine{begin, end}); 263 auto iter = subroutines.find(Subroutine{begin, end});
@@ -221,14 +313,11 @@ private:
221 313
222 /// Generates code representing a temporary (GPR) register. 314 /// Generates code representing a temporary (GPR) register.
223 std::string GetRegister(const Register& reg, unsigned elem = 0) { 315 std::string GetRegister(const Register& reg, unsigned elem = 0) {
224 if (reg == Register::ZeroIndex) 316 if (reg == Register::ZeroIndex) {
225 return "0"; 317 return "0";
226 if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
227 // GPRs 0-3 are output color for the fragment shader
228 return std::string{"color."} + "rgba"[(reg + elem) & 3];
229 } 318 }
230 319
231 return *declr_register.insert("register_" + std::to_string(reg + elem)).first; 320 return regs[reg.GetSwizzledIndex(elem)].GetActiveString();
232 } 321 }
233 322
234 /// Generates code representing a uniform (C buffer) register. 323 /// Generates code representing a uniform (C buffer) register.
@@ -628,6 +717,15 @@ private:
628 case OpCode::Id::EXIT: { 717 case OpCode::Id::EXIT: {
629 ASSERT_MSG(instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex), 718 ASSERT_MSG(instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex),
630 "Predicated exits not implemented"); 719 "Predicated exits not implemented");
720
721 // Final color output is currently hardcoded to GPR0-3 for fragment shaders
722 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
723 shader.AddLine("color.r = " + GetRegister(0) + ";");
724 shader.AddLine("color.g = " + GetRegister(1) + ";");
725 shader.AddLine("color.b = " + GetRegister(2) + ";");
726 shader.AddLine("color.a = " + GetRegister(3) + ";");
727 }
728
631 shader.AddLine("return true;"); 729 shader.AddLine("return true;");
632 offset = PROGRAM_END - 1; 730 offset = PROGRAM_END - 1;
633 break; 731 break;
@@ -755,8 +853,13 @@ private:
755 853
756 /// Add declarations for registers 854 /// Add declarations for registers
757 void GenerateDeclarations() { 855 void GenerateDeclarations() {
758 for (const auto& reg : declr_register) { 856 for (const auto& reg : regs) {
759 declarations.AddLine("float " + reg + " = 0.0;"); 857 if (reg.IsFloatUsed()) {
858 declarations.AddLine("float " + reg.GetFloatString() + " = 0.0;");
859 }
860 if (reg.IsIntegerUsed()) {
861 declarations.AddLine("int " + reg.GetIntegerString() + " = 0;");
862 }
760 } 863 }
761 declarations.AddNewLine(); 864 declarations.AddNewLine();
762 865
@@ -803,9 +906,9 @@ private:
803 906
804 ShaderWriter shader; 907 ShaderWriter shader;
805 ShaderWriter declarations; 908 ShaderWriter declarations;
909 std::vector<GLSLRegister> regs;
806 910
807 // Declarations 911 // Declarations
808 std::set<std::string> declr_register;
809 std::set<std::string> declr_predicates; 912 std::set<std::string> declr_predicates;
810 std::set<Attribute::Index> declr_input_attribute; 913 std::set<Attribute::Index> declr_input_attribute;
811 std::set<Attribute::Index> declr_output_attribute; 914 std::set<Attribute::Index> declr_output_attribute;