glsl: Fix <32-bit SSBO writes
and more cleanup
This commit is contained in:
		| @@ -433,8 +433,7 @@ void EmitContext::DefineHelperFunctions() { | |||||||
| } | } | ||||||
|  |  | ||||||
| std::string EmitContext::DefineGlobalMemoryFunctions() { | std::string EmitContext::DefineGlobalMemoryFunctions() { | ||||||
|     const auto define_body{[&](std::string& func, size_t index, u32 num_components, |     const auto define_body{[&](std::string& func, size_t index, std::string_view return_statement) { | ||||||
|                                std::string_view return_statement) { |  | ||||||
|         const auto& ssbo{info.storage_buffers_descriptors[index]}; |         const auto& ssbo{info.storage_buffers_descriptors[index]}; | ||||||
|         const u32 size_cbuf_offset{ssbo.cbuf_offset + 8}; |         const u32 size_cbuf_offset{ssbo.cbuf_offset + 8}; | ||||||
|         const auto ssbo_addr{fmt::format("ssbo_addr{}", index)}; |         const auto ssbo_addr{fmt::format("ssbo_addr{}", index)}; | ||||||
| @@ -458,42 +457,31 @@ std::string EmitContext::DefineGlobalMemoryFunctions() { | |||||||
|         func += comparison; |         func += comparison; | ||||||
|  |  | ||||||
|         const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; |         const auto ssbo_name{fmt::format("{}_ssbo{}", stage_name, index)}; | ||||||
|         switch (num_components) { |         func += fmt::format(return_statement, ssbo_name, ssbo_addr); | ||||||
|         case 1: |  | ||||||
|             func += fmt::format(return_statement, ssbo_name, ssbo_addr); |  | ||||||
|             break; |  | ||||||
|         case 2: |  | ||||||
|             func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); |  | ||||||
|             break; |  | ||||||
|         case 4: |  | ||||||
|             func += fmt::format(return_statement, ssbo_name, ssbo_addr, ssbo_name, ssbo_addr, |  | ||||||
|                                 ssbo_name, ssbo_addr, ssbo_name, ssbo_addr); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     }}; |     }}; | ||||||
|     std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){\n"}; |     std::string write_func{"void WriteGlobal32(uint64_t addr,uint data){"}; | ||||||
|     std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){\n"}; |     std::string write_func_64{"void WriteGlobal64(uint64_t addr,uvec2 data){"}; | ||||||
|     std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){\n"}; |     std::string write_func_128{"void WriteGlobal128(uint64_t addr,uvec4 data){"}; | ||||||
|     std::string load_func{"uint LoadGlobal32(uint64_t addr){\n"}; |     std::string load_func{"uint LoadGlobal32(uint64_t addr){"}; | ||||||
|     std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){\n"}; |     std::string load_func_64{"uvec2 LoadGlobal64(uint64_t addr){"}; | ||||||
|     std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){\n"}; |     std::string load_func_128{"uvec4 LoadGlobal128(uint64_t addr){"}; | ||||||
|     const size_t num_buffers{info.storage_buffers_descriptors.size()}; |     const size_t num_buffers{info.storage_buffers_descriptors.size()}; | ||||||
|     for (size_t index = 0; index < num_buffers; ++index) { |     for (size_t index = 0; index < num_buffers; ++index) { | ||||||
|         if (!info.nvn_buffer_used[index]) { |         if (!info.nvn_buffer_used[index]) { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         define_body(write_func, index, 1, "{}[uint(addr-{})>>2]=data;return;}}"); |         define_body(write_func, index, "{0}[uint(addr-{1})>>2]=data;return;}}"); | ||||||
|         define_body(write_func_64, index, 2, |         define_body(write_func_64, index, | ||||||
|                     "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;return;}}"); |                     "{0}[uint(addr-{1})>>2]=data.x;{0}[uint(addr-{1}+4)>>2]=data.y;return;}}"); | ||||||
|         define_body(write_func_128, index, 4, |         define_body(write_func_128, index, | ||||||
|                     "{}[uint(addr-{})>>2]=data.x;{}[uint(addr-{}+4)>>2]=data.y;{}[uint(" |                     "{0}[uint(addr-{1})>>2]=data.x;{0}[uint(addr-{1}+4)>>2]=data.y;{0}[uint(" | ||||||
|                     "addr-{}+8)>>2]=data.z;{}[uint(addr-{}+12)>>2]=data.w;return;}}"); |                     "addr-{1}+8)>>2]=data.z;{0}[uint(addr-{1}+12)>>2]=data.w;return;}}"); | ||||||
|         define_body(load_func, index, 1, "return {}[uint(addr-{})>>2];}}"); |         define_body(load_func, index, "return {0}[uint(addr-{1})>>2];}}"); | ||||||
|         define_body(load_func_64, index, 2, |         define_body(load_func_64, index, | ||||||
|                     "return uvec2({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2]);}}"); |                     "return uvec2({0}[uint(addr-{1})>>2],{0}[uint(addr-{1}+4)>>2]);}}"); | ||||||
|         define_body(load_func_128, index, 4, |         define_body(load_func_128, index, | ||||||
|                     "return uvec4({}[uint(addr-{})>>2],{}[uint(addr-{}+4)>>2],{}[" |                     "return uvec4({0}[uint(addr-{1})>>2],{0}[uint(addr-{1}+4)>>2],{0}[" | ||||||
|                     "uint(addr-{}+8)>>2],{}[uint(addr-{}+12)>>2]);}}"); |                     "uint(addr-{1}+8)>>2],{0}[uint(addr-{1}+12)>>2]);}}"); | ||||||
|     } |     } | ||||||
|     write_func += "}"; |     write_func += "}"; | ||||||
|     write_func_64 += "}"; |     write_func_64 += "}"; | ||||||
|   | |||||||
| @@ -11,11 +11,8 @@ | |||||||
|  |  | ||||||
| namespace Shader::Backend::GLSL { | namespace Shader::Backend::GLSL { | ||||||
| namespace { | namespace { | ||||||
| constexpr const char cas_loop[]{R"(for (;;){{ | constexpr char cas_loop[]{ | ||||||
|     uint old_value={}; |     "for (;;){{uint old={};{}=atomicCompSwap({},old,{}({},{}));if({}==old){{break;}}}}"}; | ||||||
|     {}=atomicCompSwap({},old_value,{}({},{})); |  | ||||||
|     if ({}==old_value){{break;}} |  | ||||||
| }})"}; |  | ||||||
|  |  | ||||||
| void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset, | void SharedCasFunction(EmitContext& ctx, IR::Inst& inst, std::string_view offset, | ||||||
|                        std::string_view value, std::string_view function) { |                        std::string_view value, std::string_view function) { | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| namespace Shader::Backend::GLSL { | namespace Shader::Backend::GLSL { | ||||||
| namespace { | namespace { | ||||||
| static constexpr std::string_view SWIZZLE{"xyzw"}; | constexpr char SWIZZLE[]{"xyzw"}; | ||||||
|  |  | ||||||
| u32 CbufIndex(u32 offset) { | u32 CbufIndex(u32 offset) { | ||||||
|     return (offset / 4) % 4; |     return (offset / 4) % 4; | ||||||
|   | |||||||
| @@ -9,6 +9,18 @@ | |||||||
| #include "shader_recompiler/frontend/ir/value.h" | #include "shader_recompiler/frontend/ir/value.h" | ||||||
|  |  | ||||||
| namespace Shader::Backend::GLSL { | namespace Shader::Backend::GLSL { | ||||||
|  | namespace { | ||||||
|  | constexpr char cas_loop[]{"for(;;){{uint old_value={};uint " | ||||||
|  |                           "cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));" | ||||||
|  |                           "if(cas_result==old_value){{break;}}}}"}; | ||||||
|  |  | ||||||
|  | void SsboWriteCas(EmitContext& ctx, const IR::Value& binding, std::string_view offset_var, | ||||||
|  |                   std::string_view value, std::string_view bit_offset, u32 num_bits) { | ||||||
|  |     const auto ssbo{fmt::format("{}_ssbo{}[{}>>2]", ctx.stage_name, binding.U32(), offset_var)}; | ||||||
|  |     ctx.Add(cas_loop, ssbo, ssbo, ssbo, value, bit_offset, num_bits); | ||||||
|  | } | ||||||
|  | } // Anonymous namespace | ||||||
|  |  | ||||||
| void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) { | void EmitLoadGlobalU8([[maybe_unused]] EmitContext& ctx) { | ||||||
|     NotImplemented(); |     NotImplemented(); | ||||||
| } | } | ||||||
| @@ -125,9 +137,8 @@ void EmitWriteStorageU8([[maybe_unused]] EmitContext& ctx, | |||||||
|                         [[maybe_unused]] const IR::Value& offset, |                         [[maybe_unused]] const IR::Value& offset, | ||||||
|                         [[maybe_unused]] std::string_view value) { |                         [[maybe_unused]] std::string_view value) { | ||||||
|     const auto offset_var{ctx.var_alloc.Consume(offset)}; |     const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||||||
|     ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int({}%4)*8,8);", ctx.stage_name, |     const auto bit_offset{fmt::format("int({}%4)*8", offset_var)}; | ||||||
|             binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, value, |     SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 8); | ||||||
|             offset_var); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx, | void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx, | ||||||
| @@ -135,9 +146,8 @@ void EmitWriteStorageS8([[maybe_unused]] EmitContext& ctx, | |||||||
|                         [[maybe_unused]] const IR::Value& offset, |                         [[maybe_unused]] const IR::Value& offset, | ||||||
|                         [[maybe_unused]] std::string_view value) { |                         [[maybe_unused]] std::string_view value) { | ||||||
|     const auto offset_var{ctx.var_alloc.Consume(offset)}; |     const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||||||
|     ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int({}%4)*8,8);", ctx.stage_name, |     const auto bit_offset{fmt::format("int({}%4)*8", offset_var)}; | ||||||
|             binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, value, |     SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 8); | ||||||
|             offset_var); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx, | void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx, | ||||||
| @@ -145,9 +155,8 @@ void EmitWriteStorageU16([[maybe_unused]] EmitContext& ctx, | |||||||
|                          [[maybe_unused]] const IR::Value& offset, |                          [[maybe_unused]] const IR::Value& offset, | ||||||
|                          [[maybe_unused]] std::string_view value) { |                          [[maybe_unused]] std::string_view value) { | ||||||
|     const auto offset_var{ctx.var_alloc.Consume(offset)}; |     const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||||||
|     ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int(({}>>1)%2)*16,16);", |     const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset_var)}; | ||||||
|             ctx.stage_name, binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, |     SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 16); | ||||||
|             value, offset_var); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx, | void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx, | ||||||
| @@ -155,9 +164,8 @@ void EmitWriteStorageS16([[maybe_unused]] EmitContext& ctx, | |||||||
|                          [[maybe_unused]] const IR::Value& offset, |                          [[maybe_unused]] const IR::Value& offset, | ||||||
|                          [[maybe_unused]] std::string_view value) { |                          [[maybe_unused]] std::string_view value) { | ||||||
|     const auto offset_var{ctx.var_alloc.Consume(offset)}; |     const auto offset_var{ctx.var_alloc.Consume(offset)}; | ||||||
|     ctx.Add("{}_ssbo{}[{}>>2]=bitfieldInsert({}_ssbo{}[{}>>2],{},int(({}>>1)%2)*16,16);", |     const auto bit_offset{fmt::format("int(({}>>1)%2)*16", offset_var)}; | ||||||
|             ctx.stage_name, binding.U32(), offset_var, ctx.stage_name, binding.U32(), offset_var, |     SsboWriteCas(ctx, binding, offset_var, value, bit_offset, 16); | ||||||
|             value, offset_var); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, | void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user