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