diff options
Diffstat (limited to 'src/shader_recompiler/backend/glsl/emit_context.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/glsl/emit_context.cpp | 143 |
1 files changed, 72 insertions, 71 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index f68f33212..fbc4b9c0f 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp | |||
| @@ -9,11 +9,11 @@ | |||
| 9 | 9 | ||
| 10 | namespace Shader::Backend::GLSL { | 10 | namespace Shader::Backend::GLSL { |
| 11 | namespace { | 11 | namespace { |
| 12 | u32 CbufIndex(u32 offset) { | 12 | u32 CbufIndex(size_t offset) { |
| 13 | return (offset / 4) % 4; | 13 | return (offset / 4) % 4; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | char OffsetSwizzle(u32 offset) { | 16 | char CbufSwizzle(size_t offset) { |
| 17 | return "xyzw"[CbufIndex(offset)]; | 17 | return "xyzw"[CbufIndex(offset)]; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| @@ -434,79 +434,80 @@ void EmitContext::DefineHelperFunctions() { | |||
| 434 | header += "uint CasMaxS32(uint op_a,uint op_b){return uint(max(int(op_a),int(op_b)));}"; | 434 | header += "uint CasMaxS32(uint op_a,uint op_b){return uint(max(int(op_a),int(op_b)));}"; |
| 435 | } | 435 | } |
| 436 | if (info.uses_global_memory) { | 436 | if (info.uses_global_memory) { |
| 437 | std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){\n"}; | 437 | header += DefineGlobalMemoryFunctions(); |
| 438 | std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){\n"}; | 438 | } |
| 439 | std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){\n"}; | 439 | } |
| 440 | 440 | ||
| 441 | std::string load_func{"uint LoadGlobal32(uint64_t addr){\n"}; | 441 | std::string EmitContext::DefineGlobalMemoryFunctions() { |
| 442 | std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){\n"}; | 442 | const auto define_body{[&](std::string& func, size_t index, u32 num_components, |
| 443 | std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){\n"}; | 443 | std::string_view return_statement) { |
| 444 | const size_t num_buffers{info.storage_buffers_descriptors.size()}; | 444 | const auto& ssbo{info.storage_buffers_descriptors[index]}; |
| 445 | for (size_t index = 0; index < num_buffers; ++index) { | 445 | const u32 size_cbuf_offset{ssbo.cbuf_offset + 8}; |
| 446 | if (!info.nvn_buffer_used[index]) { | 446 | const auto ssbo_addr{fmt::format("ssbo_addr{}", index)}; |
| 447 | continue; | 447 | const auto cbuf{fmt::format("{}_cbuf{}", stage_name, ssbo.cbuf_index)}; |
| 448 | } | 448 | std::array<std::string, 2> addr_xy; |
| 449 | const auto& ssbo{info.storage_buffers_descriptors[index]}; | 449 | std::array<std::string, 2> size_xy; |
| 450 | const u32 size_cbuf_offset{ssbo.cbuf_offset + 8}; | 450 | for (size_t i = 0; i < addr_xy.size(); ++i) { |
| 451 | const auto ssbo_addr{fmt::format("ssbo_addr{}", index)}; | 451 | const auto addr_loc{ssbo.cbuf_offset + 4 * i}; |
| 452 | const auto cbuf{fmt::format("{}_cbuf{}", stage_name, ssbo.cbuf_index)}; | 452 | const auto size_loc{size_cbuf_offset + 4 * i}; |
| 453 | const auto cbuf_value{fmt::format( | 453 | addr_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, addr_loc / 16, CbufSwizzle(addr_loc)); |
| 454 | "uint64_t {}=packUint2x32(uvec2(ftou({}[{}].{}),ftou({}[{}].{})));", ssbo_addr, | 454 | size_xy[i] = fmt::format("ftou({}[{}].{})", cbuf, size_loc / 16, CbufSwizzle(size_loc)); |
| 455 | cbuf, ssbo.cbuf_offset / 16, OffsetSwizzle(ssbo.cbuf_offset), cbuf, | 455 | } |
| 456 | (ssbo.cbuf_offset + 4) / 16, OffsetSwizzle(ssbo.cbuf_offset + 4))}; | 456 | const auto addr_pack{fmt::format("packUint2x32(uvec2({},{}))", addr_xy[0], addr_xy[1])}; |
| 457 | const auto addr_statment{fmt::format("uint64_t {}={};", ssbo_addr, addr_pack)}; | ||
| 458 | func += addr_statment; | ||
| 457 | 459 | ||
| 458 | write_func += cbuf_value; | 460 | const auto size_vec{fmt::format("uvec2({},{})", size_xy[0], size_xy[1])}; |
| 459 | write_func_64 += cbuf_value; | 461 | const auto comp_lhs{fmt::format("(addr>={})", ssbo_addr)}; |
| 460 | write_func_128 += cbuf_value; | 462 | const auto comp_rhs{fmt::format("(addr<({}+uint64_t({})))", ssbo_addr, size_vec)}; |
| 461 | load_func += cbuf_value; | 463 | const auto comparison{fmt::format("if({}&&{}){{", comp_lhs, comp_rhs)}; |
| 462 | load_func_64 += cbuf_value; | 464 | func += comparison; |
| 463 | load_func_128 += cbuf_value; | ||
| 464 | const auto ssbo_size{fmt::format("ftou({}[{}].{}),ftou({}[{}].{})", cbuf, | ||
| 465 | size_cbuf_offset / 16, OffsetSwizzle(size_cbuf_offset), | ||
| 466 | cbuf, (size_cbuf_offset + 4) / 16, | ||
| 467 | OffsetSwizzle(size_cbuf_offset + 4))}; | ||
| 468 | const auto comparison{fmt::format("if((addr>={})&&(addr<({}+\nuint64_t(uvec2({}))))){{", | ||
| 469 | ssbo_addr, ssbo_addr, ssbo_size)}; | ||
| 470 | write_func += comparison; | ||
| 471 | write_func_64 += comparison; | ||
| 472 | write_func_128 += comparison; | ||
| 473 | load_func += comparison; | ||
| 474 | load_func_64 += comparison; | ||
| 475 | load_func_128 += comparison; | ||
| 476 | 465 | ||
| 477 | const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; | 466 | const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; |
| 478 | write_func += fmt::format("{}[uint(addr-{})>>2]=data;return;}}", ssbo_name, ssbo_addr); | 467 | switch (num_components) { |
| 479 | write_func_64 += | 468 | case 1: |
| 480 | fmt::format("{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;return;}}", | 469 | func += fmt::format(return_statement, ssbo_name, ssbo_addr); |
| 481 | ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); | 470 | break; |
| 482 | write_func_128 += | 471 | case 2: |
| 483 | fmt::format("{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;{}[uint(" | 472 | func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); |
| 484 | "addr-{}+8)>>2]=data.z;{}[uint(addr-{}+12)>>2]=data.w;return;}}", | 473 | break; |
| 485 | ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, | 474 | case 4: |
| 486 | ssbo_name, ssbo_addr); | 475 | func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, |
| 487 | load_func += fmt::format("return {}[uint(addr-{})>>2];}}", ssbo_name, ssbo_addr); | 476 | ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); |
| 488 | load_func_64 += | 477 | break; |
| 489 | fmt::format("return uvec2({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2]);}}", | ||
| 490 | ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); | ||
| 491 | load_func_128 += fmt::format("return " | ||
| 492 | "uvec4({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2],{}[" | ||
| 493 | "uint(addr-{}+8)>>2],{}[uint(addr-{}+12)>>2]);}}", | ||
| 494 | ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, ssbo_name, | ||
| 495 | ssbo_addr, ssbo_name, ssbo_addr); | ||
| 496 | } | 478 | } |
| 497 | write_func += "}\n"; | 479 | }}; |
| 498 | write_func_64 += "}\n"; | 480 | std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){\n"}; |
| 499 | write_func_128 += "}\n"; | 481 | std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){\n"}; |
| 500 | load_func += "return 0u;}\n"; | 482 | std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){\n"}; |
| 501 | load_func_64 += "return uvec2(0);}\n"; | 483 | std::string load_func{"uint LoadGlobal32(uint64_t addr){\n"}; |
| 502 | load_func_128 += "return uvec4(0);}\n"; | 484 | std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){\n"}; |
| 503 | header += write_func; | 485 | std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){\n"}; |
| 504 | header += write_func_64; | 486 | const size_t num_buffers{info.storage_buffers_descriptors.size()}; |
| 505 | header += write_func_128; | 487 | for (size_t index = 0; index < num_buffers; ++index) { |
| 506 | header += load_func; | 488 | if (!info.nvn_buffer_used[index]) { |
| 507 | header += load_func_64; | 489 | continue; |
| 508 | header += load_func_128; | 490 | } |
| 509 | } | 491 | define_body(write_func, index, 1, "{}[uint(addr-{})>>2]=data;return;}}"); |
| 492 | define_body(write_func_64, index, 2, | ||
| 493 | "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;return;}}"); | ||
| 494 | define_body(write_func_128, index, 4, | ||
| 495 | "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;{}[uint(" | ||
| 496 | "addr-{}+8)>>2]=data.z;{}[uint(addr-{}+12)>>2]=data.w;return;}}"); | ||
| 497 | define_body(load_func, index, 1, "return {}[uint(addr-{})>>2];}}"); | ||
| 498 | define_body(load_func_64, index, 2, | ||
| 499 | "return uvec2({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2]);}}"); | ||
| 500 | define_body(load_func_128, index, 4, | ||
| 501 | "return uvec4({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2],{}[" | ||
| 502 | "uint(addr-{}+8)>>2],{}[uint(addr-{}+12)>>2]);}}"); | ||
| 503 | } | ||
| 504 | write_func += "}"; | ||
| 505 | write_func_64 += "}"; | ||
| 506 | write_func_128 += "}"; | ||
| 507 | load_func += "return 0u;}"; | ||
| 508 | load_func_64 += "return uvec2(0);}"; | ||
| 509 | load_func_128 += "return uvec4(0);}"; | ||
| 510 | return write_func + write_func_64 + write_func_128 + load_func + load_func_64 + load_func_128; | ||
| 510 | } | 511 | } |
| 511 | 512 | ||
| 512 | void EmitContext::SetupImages(Bindings& bindings) { | 513 | void EmitContext::SetupImages(Bindings& bindings) { |