diff options
| author | 2021-06-03 22:25:06 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:37 -0400 | |
| commit | 0a0b0a73d82057a309b6b0427c29c7e15e2b356f (patch) | |
| tree | 0982ab6ae4b27b69a97cad77beb551e9508d537e /src/shader_recompiler/backend/glsl | |
| parent | glsl: Cleanup and address feedback (diff) | |
| download | yuzu-0a0b0a73d82057a309b6b0427c29c7e15e2b356f.tar.gz yuzu-0a0b0a73d82057a309b6b0427c29c7e15e2b356f.tar.xz yuzu-0a0b0a73d82057a309b6b0427c29c7e15e2b356f.zip | |
glsl: Fix <32-bit SSBO writes
and more cleanup
Diffstat (limited to 'src/shader_recompiler/backend/glsl')
4 files changed, 43 insertions, 50 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/emit_context.cpp index ae5ac752d..ecc7335ba 100644 --- a/src/shader_recompiler/backend/glsl/emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/emit_context.cpp | |||
| @@ -433,8 +433,7 @@ void EmitContext::DefineHelperFunctions() { | |||
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | std::string EmitContext::DefineGlobalMemoryFunctions() { | 435 | std::string EmitContext::DefineGlobalMemoryFunctions() { |
| 436 | const auto define_body{[&](std::string& func, size_t index, u32 num_components, | 436 | const auto define_body{[&](std::string& func, size_t index, std::string_view return_statement) { |
| 437 | std::string_view return_statement) { | ||
| 438 | const auto& ssbo{info.storage_buffers_descriptors[index]}; | 437 | const auto& ssbo{info.storage_buffers_descriptors[index]}; |
| 439 | const u32 size_cbuf_offset{ssbo.cbuf_offset + 8}; | 438 | const u32 size_cbuf_offset{ssbo.cbuf_offset + 8}; |
| 440 | const auto ssbo_addr{fmt::format("ssbo_addr{}", index)}; | 439 | const auto ssbo_addr{fmt::format("ssbo_addr{}", index)}; |
| @@ -458,42 +457,31 @@ std::string EmitContext::DefineGlobalMemoryFunctions() { | |||
| 458 | func += comparison; | 457 | func += comparison; |
| 459 | 458 | ||
| 460 | const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; | 459 | const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; |
| 461 | switch (num_components) { | 460 | func += fmt::format(return_statement, ssbo_name, ssbo_addr); |
| 462 | case 1: | ||
| 463 | func += fmt::format(return_statement, ssbo_name, ssbo_addr); | ||
| 464 | break; | ||
| 465 | case 2: | ||
| 466 | func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); | ||
| 467 | break; | ||
| 468 | case 4: | ||
| 469 | func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, | ||
| 470 | ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | }}; | 461 | }}; |
| 474 | std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){\n"}; | 462 | std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){"}; |
| 475 | std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){\n"}; | 463 | std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){"}; |
| 476 | std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){\n"}; | 464 | std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){"}; |
| 477 | std::string load_func{"uint LoadGlobal32(uint64_t addr){\n"}; | 465 | std::string load_func{"uint LoadGlobal32(uint64_t addr){"}; |
| 478 | std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){\n"}; | 466 | std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){"}; |
| 479 | std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){\n"}; | 467 | std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){"}; |
| 480 | const size_t num_buffers{info.storage_buffers_descriptors.size()}; | 468 | const size_t num_buffers{info.storage_buffers_descriptors.size()}; |
| 481 | for (size_t index = 0; index < num_buffers; ++index) { | 469 | for (size_t index = 0; index < num_buffers; ++index) { |
| 482 | if (!info.nvn_buffer_used[index]) { | 470 | if (!info.nvn_buffer_used[index]) { |
| 483 | continue; | 471 | continue; |
| 484 | } | 472 | } |
| 485 | define_body(write_func, index, 1, "{}[uint(addr-{})>>2]=data;return;}}"); | 473 | define_body(write_func, index, "{0}[uint(addr-{1})>>2]=data;return;}}"); |
| 486 | define_body(write_func_64, index, 2, | 474 | define_body(write_func_64, index, |
| 487 | "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;return;}}"); | 475 | "{0}[uint(addr-{1})>>2]=data.x;{0}[uint(addr-{1}+4)>>2]=data.y;return;}}"); |
| 488 | define_body(write_func_128, index, 4, | 476 | define_body(write_func_128, index, |
| 489 | "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;{}[uint(" | 477 | "{0}[uint(addr-{1})>>2]=data.x;{0}[uint(addr-{1}+4)>>2]=data.y;{0}[uint(" |
| 490 | "addr-{}+8)>>2]=data.z;{}[uint(addr-{}+12)>>2]=data.w;return;}}"); | 478 | "addr-{1}+8)>>2]=data.z;{0}[uint(addr-{1}+12)>>2]=data.w;return;}}"); |
| 491 | define_body(load_func, index, 1, "return {}[uint(addr-{})>>2];}}"); | 479 | define_body(load_func, index, "return {0}[uint(addr-{1})>>2];}}"); |
| 492 | define_body(load_func_64, index, 2, | 480 | define_body(load_func_64, index, |
| 493 | "return uvec2({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2]);}}"); | 481 | "return uvec2({0}[uint(addr-{1})>>2],{0}[uint(addr-{1}+4)>>2]);}}"); |
| 494 | define_body(load_func_128, index, 4, | 482 | define_body(load_func_128, index, |
| 495 | "return uvec4({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2],{}[" | 483 | "return uvec4({0}[uint(addr-{1})>>2],{0}[uint(addr-{1}+4)>>2],{0}[" |
| 496 | "uint(addr-{}+8)>>2],{}[uint(addr-{}+12)>>2]);}}"); | 484 | "uint(addr-{1}+8)>>2],{0}[uint(addr-{1}+12)>>2]);}}"); |
| 497 | } | 485 | } |
| 498 | write_func += "}"; | 486 | write_func += "}"; |
| 499 | write_func_64 += "}"; | 487 | write_func_64 += "}"; |
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp index 5ba39261b..1568bb7cf 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp | |||
| @@ -11,11 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | namespace Shader::Backend::GLSL { | 12 | namespace Shader::Backend::GLSL { |
| 13 | namespace { | 13 | namespace { |
| 14 | constexpr const char cas_loop[]{R"(for (;;){{ | 14 | constexpr char cas_loop[]{ |
| 15 | uint old_value={}; | 15 | "for (;;){{uint old={};{}=atomicCompSwap({},old,{}({},{}));if({}==old){{break;}}}}"}; |
| 16 | {}=atomicCompSwap({},old_value,{}({},{})); | ||
| 17 | if ({}==old_value){{break;}} | ||
| 18 | }})"}; | ||
| 19 | 16 | ||
| 20 | void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset, | 17 | void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset, |
| 21 | std::string_view value, std::string_view function) { | 18 | std::string_view value, std::string_view function) { |
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp index d986e1b1a..b2caa222a 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | namespace Shader::Backend::GLSL { | 12 | namespace Shader::Backend::GLSL { |
| 13 | namespace { | 13 | namespace { |
| 14 | static constexpr std::string_view SWIZZLE{"xyzw"}; | 14 | constexpr char SWIZZLE[]{"xyzw"}; |
| 15 | 15 | ||
| 16 | u32 CbufIndex(u32 offset) { | 16 | u32 CbufIndex(u32 offset) { |
| 17 | return (offset / 4) % 4; | 17 | return (offset / 4) % 4; |
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp index bc4363824..500e5c290 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp | |||
| @@ -9,6 +9,18 @@ | |||
| 9 | #include "shader_recompiler/frontend/ir/value.h" | 9 | #include "shader_recompiler/frontend/ir/value.h" |
| 10 | 10 | ||
| 11 | namespace Shader::Backend::GLSL { | 11 | namespace Shader::Backend::GLSL { |
| 12 | namespace { | ||
| 13 | constexpr char cas_loop[]{"for(;;){{uint old_value={};uint " | ||
| 14 | "cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));" | ||
| 15 | "if(cas_result==old_value){{break;}}}}"}; | ||
| 16 | |||
| 17 | void SsboWriteCas(EmitContext& ctx, const IR::Value& binding, std::string_view offset_var, | ||
| 18 | std::string_view value, std::string_view bit_offset, u32 num_bits) { | ||
| 19 | const auto ssbo{fmt::format("{}_ssbo{}[{}>>2]", ctx.stage_name, binding.U32(), offset_var)}; | ||
| 20 | ctx.Add(cas_loop, ssbo, ssbo, ssbo, value, bit_offset, num_bits); | ||
| 21 | } | ||
| 22 | } // Anonymous namespace | ||
| 23 | |||
| 12 | void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) { | 24 | void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) { |
| 13 | NotImplemented(); | 25 | NotImplemented(); |
| 14 | } | 26 | } |
| @@ -125,9 +137,8 @@ void EmitWriteStorageU8([[maybe_unused]] EmitContext& ctx, | |||
| 125 | [[maybe_unused]] const IR::Value& offset, | 137 | [[maybe_unused]] const IR::Value& offset, |
| 126 | [[maybe_unused]] std::string_view value) { | 138 | [[maybe_unused]] std::string_view value) { |
| 127 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 139 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 128 | ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int({}%4)*8,8);", ctx.stage_name, | 140 | const auto bit_offset{fmt::format("int({}%4)*8", offset_var)}; |
| 129 | binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, value, | 141 | SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 8); |
| 130 | offset_var); | ||
| 131 | } | 142 | } |
| 132 | 143 | ||
| 133 | void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx, | 144 | void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx, |
| @@ -135,9 +146,8 @@ void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx, | |||
| 135 | [[maybe_unused]] const IR::Value& offset, | 146 | [[maybe_unused]] const IR::Value& offset, |
| 136 | [[maybe_unused]] std::string_view value) { | 147 | [[maybe_unused]] std::string_view value) { |
| 137 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 148 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 138 | ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int({}%4)*8,8);", ctx.stage_name, | 149 | const auto bit_offset{fmt::format("int({}%4)*8", offset_var)}; |
| 139 | binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, value, | 150 | SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 8); |
| 140 | offset_var); | ||
| 141 | } | 151 | } |
| 142 | 152 | ||
| 143 | void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx, | 153 | void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx, |
| @@ -145,9 +155,8 @@ void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx, | |||
| 145 | [[maybe_unused]] const IR::Value& offset, | 155 | [[maybe_unused]] const IR::Value& offset, |
| 146 | [[maybe_unused]] std::string_view value) { | 156 | [[maybe_unused]] std::string_view value) { |
| 147 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 157 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 148 | ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int(({}>>1)%2)*16,16);", | 158 | const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset_var)}; |
| 149 | ctx.stage_name, binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, | 159 | SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 16); |
| 150 | value, offset_var); | ||
| 151 | } | 160 | } |
| 152 | 161 | ||
| 153 | void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx, | 162 | void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx, |
| @@ -155,9 +164,8 @@ void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx, | |||
| 155 | [[maybe_unused]] const IR::Value& offset, | 164 | [[maybe_unused]] const IR::Value& offset, |
| 156 | [[maybe_unused]] std::string_view value) { | 165 | [[maybe_unused]] std::string_view value) { |
| 157 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 166 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 158 | ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int(({}>>1)%2)*16,16);", | 167 | const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset_var)}; |
| 159 | ctx.stage_name, binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, | 168 | SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 16); |
| 160 | value, offset_var); | ||
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, | 171 | void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, |