diff options
author | Kelebek1 <eeeedddccc@hotmail.co.uk> | 2023-10-14 23:20:28 +0200 |
---|---|---|
committer | Kelebek1 <eeeedddccc@hotmail.co.uk> | 2023-10-19 20:54:31 +0200 |
commit | e02ee8e59d099692678bed09332b7d8aad1ce271 (patch) | |
tree | 8ea0de01f31cee80075441fab4c746e0615a7ff7 /src/shader_recompiler/backend/spirv | |
parent | Merge pull request #11810 from liamwhite/clang-17 (diff) | |
download | yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.tar yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.tar.gz yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.tar.bz2 yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.tar.lz yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.tar.xz yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.tar.zst yuzu-e02ee8e59d099692678bed09332b7d8aad1ce271.zip |
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
-rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | 23 | ||||
-rw-r--r-- | src/shader_recompiler/backend/spirv/spirv_emit_context.h | 36 |
2 files changed, 56 insertions, 3 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 2868fc57d..1d77426e0 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -111,16 +111,33 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, } else if (element_size > 1) { const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; const Id shift{ctx.Const(log2_element_size)}; - buffer_offset = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift); + buffer_offset = ctx.OpShiftRightLogical(ctx.U32[1], ctx.Def(offset), shift); } else { buffer_offset = ctx.Def(offset); } if (!binding.IsImmediate()) { return ctx.OpFunctionCall(result_type, indirect_func, ctx.Def(binding), buffer_offset); } + const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; - return ctx.OpLoad(result_type, access_chain); + const Id val = ctx.OpLoad(result_type, access_chain); + + if (offset.IsImmediate() || !ctx.profile.has_broken_robust) { + return val; + } + + const auto is_float = UniformDefinitions::IsFloat(member_ptr); + const auto num_elements = UniformDefinitions::NumElements(member_ptr); + const std::array zero_vec{ + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + is_float ? ctx.Const(0.0f) : ctx.Const(0u), + }; + const Id cond = ctx.OpULessThanEqual(ctx.TypeBool(), buffer_offset, ctx.Const(0xFFFFu)); + const Id zero = ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements)); + return ctx.OpSelect(result_type, cond, val, zero); } Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { @@ -138,7 +155,7 @@ Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 inde const u32 element{(offset.U32() / 4) % 4 + index_offset}; return ctx.OpCompositeExtract(ctx.U32[1], vector, element); } - const Id shift{ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), ctx.Const(2u))}; + const Id shift{ctx.OpShiftRightLogical(ctx.U32[1], ctx.Def(offset), ctx.Const(2u))}; Id element{ctx.OpBitwiseAnd(ctx.U32[1], shift, ctx.Const(3u))}; if (index_offset > 0) { element = ctx.OpIAdd(ctx.U32[1], element, ctx.Const(index_offset)); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 7c49fd504..1aa79863d 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -64,6 +64,42 @@ struct UniformDefinitions { Id F32{}; Id U32x2{}; Id U32x4{}; + + constexpr static size_t NumElements(Id UniformDefinitions::*member_ptr) { + if (member_ptr == &UniformDefinitions::U8) { + return 1; + } + if (member_ptr == &UniformDefinitions::S8) { + return 1; + } + if (member_ptr == &UniformDefinitions::U16) { + return 1; + } + if (member_ptr == &UniformDefinitions::S16) { + return 1; + } + if (member_ptr == &UniformDefinitions::U32) { + return 1; + } + if (member_ptr == &UniformDefinitions::F32) { + return 1; + } + if (member_ptr == &UniformDefinitions::U32x2) { + return 2; + } + if (member_ptr == &UniformDefinitions::U32x4) { + return 4; + } + ASSERT(false); + return 1; + } + + constexpr static bool IsFloat(Id UniformDefinitions::*member_ptr) { + if (member_ptr == &UniformDefinitions::F32) { + return true; + } + return false; + } }; struct StorageTypeDefinition { |