diff options
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | 31 |
1 files changed, 15 insertions, 16 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 1cfe1d49f..264646115 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 | |||
| @@ -124,31 +124,28 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { | |||
| 124 | 124 | ||
| 125 | Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, | 125 | Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, |
| 126 | const IR::Value& binding, const IR::Value& offset) { | 126 | const IR::Value& binding, const IR::Value& offset) { |
| 127 | std::array<Id, 2> indexes; | 127 | Id buffer_offset; |
| 128 | 128 | ||
| 129 | const Id uniform_type{ctx.uniform_types.*member_ptr}; | 129 | const Id uniform_type{ctx.uniform_types.*member_ptr}; |
| 130 | if (offset.IsImmediate()) { | 130 | if (offset.IsImmediate()) { |
| 131 | // Hardware been proved to read the aligned offset (e.g. LDC.U32 at 6 will read offset 4) | 131 | // Hardware been proved to read the aligned offset (e.g. LDC.U32 at 6 will read offset 4) |
| 132 | const Id imm_offset{ctx.Const(offset.U32() / element_size)}; | 132 | const Id imm_offset{ctx.Const(offset.U32() / element_size)}; |
| 133 | indexes = {ctx.u32_zero_value, imm_offset}; | 133 | buffer_offset = imm_offset; |
| 134 | } else if (element_size > 1) { | ||
| 135 | const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; | ||
| 136 | const Id shift{ctx.Const(log2_element_size)}; | ||
| 137 | buffer_offset = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift); | ||
| 134 | } else { | 138 | } else { |
| 135 | Id index{ctx.Def(offset)}; | 139 | buffer_offset = ctx.Def(offset); |
| 136 | if (element_size > 1) { | ||
| 137 | const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; | ||
| 138 | const Id shift{ctx.Const(log2_element_size)}; | ||
| 139 | index = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift); | ||
| 140 | } | ||
| 141 | indexes = {ctx.u32_zero_value, index}; | ||
| 142 | } | 140 | } |
| 143 | 141 | ||
| 144 | if (binding.IsImmediate()) { | 142 | if (binding.IsImmediate()) { |
| 145 | const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; | 143 | const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; |
| 146 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, indexes)}; | 144 | const Id access_chain{ |
| 145 | ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; | ||
| 147 | return ctx.OpLoad(result_type, access_chain); | 146 | return ctx.OpLoad(result_type, access_chain); |
| 148 | } else { | 147 | } else { |
| 149 | const Id index{ctx.Def(binding)}; | 148 | const Id index{ctx.Def(binding)}; |
| 150 | const Id ptr{ctx.TypePointer(spv::StorageClass::Function, result_type)}; | ||
| 151 | const Id value{ctx.AddLocalVariable(ptr, spv::StorageClass::Function)}; | ||
| 152 | const Id merge_label = ctx.OpLabel(); | 149 | const Id merge_label = ctx.OpLabel(); |
| 153 | 150 | ||
| 154 | std::array<Id, Info::MAX_CBUFS> buf_labels; | 151 | std::array<Id, Info::MAX_CBUFS> buf_labels; |
| @@ -161,18 +158,20 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, | |||
| 161 | ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); | 158 | ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); |
| 162 | ctx.OpSwitch(index, buf_labels[0], buf_literals, buf_labels); | 159 | ctx.OpSwitch(index, buf_labels[0], buf_literals, buf_labels); |
| 163 | 160 | ||
| 161 | std::array<Id, Info::MAX_CBUFS * 2> phi_targets; | ||
| 164 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | 162 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { |
| 165 | ctx.AddLabel(buf_labels[i]); | 163 | ctx.AddLabel(buf_labels[i]); |
| 166 | const Id cbuf{ctx.cbufs[i].*member_ptr}; | 164 | const Id cbuf{ctx.cbufs[i].*member_ptr}; |
| 167 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, indexes)}; | 165 | const Id access_chain{ |
| 168 | const Id result = ctx.OpLoad(result_type, access_chain); | 166 | ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; |
| 169 | ctx.OpStore(value, result); | 167 | phi_targets[2 * i + 0] = ctx.OpLoad(result_type, access_chain); |
| 168 | phi_targets[2 * i + 1] = buf_labels[i]; | ||
| 170 | ctx.OpBranch(merge_label); | 169 | ctx.OpBranch(merge_label); |
| 171 | } | 170 | } |
| 172 | 171 | ||
| 173 | ctx.AddLabel(merge_label); | 172 | ctx.AddLabel(merge_label); |
| 174 | 173 | ||
| 175 | return ctx.OpLoad(result_type, value); | 174 | return ctx.OpPhi(result_type, phi_targets); |
| 176 | } | 175 | } |
| 177 | } | 176 | } |
| 178 | 177 | ||