summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-15 20:45:56 -0400
committerGravatar bunnei2018-04-17 16:36:42 -0400
commit5a28dce9eb8db4571cc47352174c78f2c3cfd606 (patch)
treef879ecc81cb6737df1e2e0adea45acf53cba1e1e
parentgl_shader_decompiler: Allow vertex position to be used in fragment shader. (diff)
downloadyuzu-5a28dce9eb8db4571cc47352174c78f2c3cfd606.tar.gz
yuzu-5a28dce9eb8db4571cc47352174c78f2c3cfd606.tar.xz
yuzu-5a28dce9eb8db4571cc47352174c78f2c3cfd606.zip
gl_shader_decompiler: Implement FMUL/FADD/FFMA immediate instructions.
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/shader_bytecode.h14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp51
2 files changed, 53 insertions, 12 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 51cf4af9f..c368fa7fd 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstring>
7#include <map> 8#include <map>
8#include <string> 9#include <string>
9#include "common/bit_field.h" 10#include "common/bit_field.h"
@@ -289,6 +290,7 @@ enum class SubOp : u64 {
289 Lg2 = 0x3, 290 Lg2 = 0x3,
290 Rcp = 0x4, 291 Rcp = 0x4,
291 Rsq = 0x5, 292 Rsq = 0x5,
293 Min = 0x8,
292}; 294};
293 295
294union Instruction { 296union Instruction {
@@ -307,11 +309,22 @@ union Instruction {
307 BitField<39, 8, Register> gpr39; 309 BitField<39, 8, Register> gpr39;
308 310
309 union { 311 union {
312 BitField<20, 19, u64> imm20;
310 BitField<45, 1, u64> negate_b; 313 BitField<45, 1, u64> negate_b;
311 BitField<46, 1, u64> abs_a; 314 BitField<46, 1, u64> abs_a;
312 BitField<48, 1, u64> negate_a; 315 BitField<48, 1, u64> negate_a;
313 BitField<49, 1, u64> abs_b; 316 BitField<49, 1, u64> abs_b;
314 BitField<50, 1, u64> abs_d; 317 BitField<50, 1, u64> abs_d;
318 BitField<56, 1, u64> negate_imm;
319
320 float GetImm20() const {
321 float result{};
322 u32 imm{static_cast<u32>(imm20)};
323 imm <<= 12;
324 imm |= negate_imm ? 0x80000000 : 0;
325 std::memcpy(&result, &imm, sizeof(imm));
326 return result;
327 }
315 } alu; 328 } alu;
316 329
317 union { 330 union {
@@ -319,6 +332,7 @@ union Instruction {
319 BitField<49, 1, u64> negate_c; 332 BitField<49, 1, u64> negate_c;
320 } ffma; 333 } ffma;
321 334
335 BitField<61, 1, u64> is_b_imm;
322 BitField<60, 1, u64> is_b_gpr; 336 BitField<60, 1, u64> is_b_gpr;
323 BitField<59, 1, u64> is_c_gpr; 337 BitField<59, 1, u64> is_c_gpr;
324 338
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 1d8057927..aa435e5cc 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -190,6 +190,11 @@ private:
190 } 190 }
191 } 191 }
192 192
193 /// Generates code representing an immediate value
194 static std::string GetImmediate(const Instruction& instr) {
195 return std::to_string(instr.alu.GetImm20());
196 }
197
193 /// Generates code representing a temporary (GPR) register. 198 /// Generates code representing a temporary (GPR) register.
194 std::string GetRegister(const Register& reg, unsigned elem = 0) { 199 std::string GetRegister(const Register& reg, unsigned elem = 0) {
195 if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) { 200 if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
@@ -269,24 +274,32 @@ private:
269 } 274 }
270 275
271 std::string op_b = instr.alu.negate_b ? "-" : ""; 276 std::string op_b = instr.alu.negate_b ? "-" : "";
272 if (instr.is_b_gpr) { 277
273 op_b += GetRegister(instr.gpr20); 278 if (instr.is_b_imm) {
279 op_b += GetImmediate(instr);
274 } else { 280 } else {
275 op_b += GetUniform(instr.uniform); 281 if (instr.is_b_gpr) {
282 op_b += GetRegister(instr.gpr20);
283 } else {
284 op_b += GetUniform(instr.uniform);
285 }
276 } 286 }
287
277 if (instr.alu.abs_b) { 288 if (instr.alu.abs_b) {
278 op_b = "abs(" + op_b + ")"; 289 op_b = "abs(" + op_b + ")";
279 } 290 }
280 291
281 switch (instr.opcode.EffectiveOpCode()) { 292 switch (instr.opcode.EffectiveOpCode()) {
282 case OpCode::Id::FMUL_C: 293 case OpCode::Id::FMUL_C:
283 case OpCode::Id::FMUL_R: { 294 case OpCode::Id::FMUL_R:
284 SetDest(0, dest, op_a + " * " + op_b, 1, 1); 295 case OpCode::Id::FMUL_IMM: {
296 SetDest(0, dest, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
285 break; 297 break;
286 } 298 }
287 case OpCode::Id::FADD_C: 299 case OpCode::Id::FADD_C:
288 case OpCode::Id::FADD_R: { 300 case OpCode::Id::FADD_R:
289 SetDest(0, dest, op_a + " + " + op_b, 1, 1); 301 case OpCode::Id::FADD_IMM: {
302 SetDest(0, dest, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
290 break; 303 break;
291 } 304 }
292 case OpCode::Id::MUFU: { 305 case OpCode::Id::MUFU: {
@@ -316,16 +329,28 @@ private:
316 329
317 std::string dest = GetRegister(instr.gpr0); 330 std::string dest = GetRegister(instr.gpr0);
318 std::string op_a = GetRegister(instr.gpr8); 331 std::string op_a = GetRegister(instr.gpr8);
319
320 std::string op_b = instr.ffma.negate_b ? "-" : ""; 332 std::string op_b = instr.ffma.negate_b ? "-" : "";
321 op_b += GetUniform(instr.uniform);
322
323 std::string op_c = instr.ffma.negate_c ? "-" : ""; 333 std::string op_c = instr.ffma.negate_c ? "-" : "";
324 op_c += GetRegister(instr.gpr39);
325 334
326 switch (instr.opcode.EffectiveOpCode()) { 335 switch (instr.opcode.EffectiveOpCode()) {
327 case OpCode::Id::FFMA_CR: { 336 case OpCode::Id::FFMA_CR: {
328 SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1); 337 op_b += GetUniform(instr.uniform);
338 op_c += GetRegister(instr.gpr39);
339 break;
340 }
341 case OpCode::Id::FFMA_RR: {
342 op_b += GetRegister(instr.gpr20);
343 op_c += GetRegister(instr.gpr39);
344 break;
345 }
346 case OpCode::Id::FFMA_RC: {
347 op_b += GetRegister(instr.gpr39);
348 op_c += GetUniform(instr.uniform);
349 break;
350 }
351 case OpCode::Id::FFMA_IMM: {
352 op_b += GetImmediate(instr);
353 op_c += GetRegister(instr.gpr39);
329 break; 354 break;
330 } 355 }
331 default: { 356 default: {
@@ -336,6 +361,8 @@ private:
336 break; 361 break;
337 } 362 }
338 } 363 }
364
365 SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
339 break; 366 break;
340 } 367 }
341 case OpCode::Type::Memory: { 368 case OpCode::Type::Memory: {