diff options
Diffstat (limited to 'src/shader_recompiler/backend')
| -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, | |||
| 111 | } else if (element_size > 1) { | 111 | } else if (element_size > 1) { |
| 112 | const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; | 112 | const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; |
| 113 | const Id shift{ctx.Const(log2_element_size)}; | 113 | const Id shift{ctx.Const(log2_element_size)}; |
| 114 | buffer_offset = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift); | 114 | buffer_offset = ctx.OpShiftRightLogical(ctx.U32[1], ctx.Def(offset), shift); |
| 115 | } else { | 115 | } else { |
| 116 | buffer_offset = ctx.Def(offset); | 116 | buffer_offset = ctx.Def(offset); |
| 117 | } | 117 | } |
| 118 | if (!binding.IsImmediate()) { | 118 | if (!binding.IsImmediate()) { |
| 119 | return ctx.OpFunctionCall(result_type, indirect_func, ctx.Def(binding), buffer_offset); | 119 | return ctx.OpFunctionCall(result_type, indirect_func, ctx.Def(binding), buffer_offset); |
| 120 | } | 120 | } |
| 121 | |||
| 121 | const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; | 122 | const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; |
| 122 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; | 123 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; |
| 123 | return ctx.OpLoad(result_type, access_chain); | 124 | const Id val = ctx.OpLoad(result_type, access_chain); |
| 125 | |||
| 126 | if (offset.IsImmediate() || !ctx.profile.has_broken_robust) { | ||
| 127 | return val; | ||
| 128 | } | ||
| 129 | |||
| 130 | const auto is_float = UniformDefinitions::IsFloat(member_ptr); | ||
| 131 | const auto num_elements = UniformDefinitions::NumElements(member_ptr); | ||
| 132 | const std::array zero_vec{ | ||
| 133 | is_float ? ctx.Const(0.0f) : ctx.Const(0u), | ||
| 134 | is_float ? ctx.Const(0.0f) : ctx.Const(0u), | ||
| 135 | is_float ? ctx.Const(0.0f) : ctx.Const(0u), | ||
| 136 | is_float ? ctx.Const(0.0f) : ctx.Const(0u), | ||
| 137 | }; | ||
| 138 | const Id cond = ctx.OpULessThanEqual(ctx.TypeBool(), buffer_offset, ctx.Const(0xFFFFu)); | ||
| 139 | const Id zero = ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements)); | ||
| 140 | return ctx.OpSelect(result_type, cond, val, zero); | ||
| 124 | } | 141 | } |
| 125 | 142 | ||
| 126 | Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { | 143 | 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 | |||
| 138 | const u32 element{(offset.U32() / 4) % 4 + index_offset}; | 155 | const u32 element{(offset.U32() / 4) % 4 + index_offset}; |
| 139 | return ctx.OpCompositeExtract(ctx.U32[1], vector, element); | 156 | return ctx.OpCompositeExtract(ctx.U32[1], vector, element); |
| 140 | } | 157 | } |
| 141 | const Id shift{ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), ctx.Const(2u))}; | 158 | const Id shift{ctx.OpShiftRightLogical(ctx.U32[1], ctx.Def(offset), ctx.Const(2u))}; |
| 142 | Id element{ctx.OpBitwiseAnd(ctx.U32[1], shift, ctx.Const(3u))}; | 159 | Id element{ctx.OpBitwiseAnd(ctx.U32[1], shift, ctx.Const(3u))}; |
| 143 | if (index_offset > 0) { | 160 | if (index_offset > 0) { |
| 144 | element = ctx.OpIAdd(ctx.U32[1], element, ctx.Const(index_offset)); | 161 | 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 { | |||
| 64 | Id F32{}; | 64 | Id F32{}; |
| 65 | Id U32x2{}; | 65 | Id U32x2{}; |
| 66 | Id U32x4{}; | 66 | Id U32x4{}; |
| 67 | |||
| 68 | constexpr static size_t NumElements(Id UniformDefinitions::*member_ptr) { | ||
| 69 | if (member_ptr == &UniformDefinitions::U8) { | ||
| 70 | return 1; | ||
| 71 | } | ||
| 72 | if (member_ptr == &UniformDefinitions::S8) { | ||
| 73 | return 1; | ||
| 74 | } | ||
| 75 | if (member_ptr == &UniformDefinitions::U16) { | ||
| 76 | return 1; | ||
| 77 | } | ||
| 78 | if (member_ptr == &UniformDefinitions::S16) { | ||
| 79 | return 1; | ||
| 80 | } | ||
| 81 | if (member_ptr == &UniformDefinitions::U32) { | ||
| 82 | return 1; | ||
| 83 | } | ||
| 84 | if (member_ptr == &UniformDefinitions::F32) { | ||
| 85 | return 1; | ||
| 86 | } | ||
| 87 | if (member_ptr == &UniformDefinitions::U32x2) { | ||
| 88 | return 2; | ||
| 89 | } | ||
| 90 | if (member_ptr == &UniformDefinitions::U32x4) { | ||
| 91 | return 4; | ||
| 92 | } | ||
| 93 | ASSERT(false); | ||
| 94 | return 1; | ||
| 95 | } | ||
| 96 | |||
| 97 | constexpr static bool IsFloat(Id UniformDefinitions::*member_ptr) { | ||
| 98 | if (member_ptr == &UniformDefinitions::F32) { | ||
| 99 | return true; | ||
| 100 | } | ||
| 101 | return false; | ||
| 102 | } | ||
| 67 | }; | 103 | }; |
| 68 | 104 | ||
| 69 | struct StorageTypeDefinition { | 105 | struct StorageTypeDefinition { |