summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp8
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp9
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp4
3 files changed, 13 insertions, 8 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
index 787612def..9ad668b86 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
@@ -18,6 +18,14 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU
18 throw NotImplementedException("Indirect constant buffer loading"); 18 throw NotImplementedException("Indirect constant buffer loading");
19 } 19 }
20 const Register ret{ctx.reg_alloc.Define(inst)}; 20 const Register ret{ctx.reg_alloc.Define(inst)};
21 if (offset.type == Type::U32) {
22 // Avoid reading arrays out of bounds, matching hardware's behavior
23 const u32 imm_offset{offset.imm_u32};
24 if (offset.imm_u32 >= 0x10'000) {
25 ctx.Add("MOV.S {},0;", ret);
26 return;
27 }
28 }
21 ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset); 29 ctx.Add("LDC.{} {},c{}[{}];", size, ret, binding.U32(), offset);
22} 30}
23 31
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 c1b69c234..442a958a5 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
@@ -122,7 +122,7 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
122} 122}
123 123
124Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, 124Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size,
125 const IR::Value& binding, const IR::Value& offset, bool check_alignment = true) { 125 const IR::Value& binding, const IR::Value& offset) {
126 if (!binding.IsImmediate()) { 126 if (!binding.IsImmediate()) {
127 throw NotImplementedException("Constant buffer indexing"); 127 throw NotImplementedException("Constant buffer indexing");
128 } 128 }
@@ -138,17 +138,14 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr,
138 const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, index)}; 138 const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, index)};
139 return ctx.OpLoad(result_type, access_chain); 139 return ctx.OpLoad(result_type, access_chain);
140 } 140 }
141 if (check_alignment && offset.U32() % element_size != 0) { 141 // Hardware been proved to read the aligned offset (e.g. LDC.U32 at 6 will read offset 4)
142 throw NotImplementedException("Unaligned immediate constant buffer load");
143 }
144 const Id imm_offset{ctx.Const(offset.U32() / element_size)}; 142 const Id imm_offset{ctx.Const(offset.U32() / element_size)};
145 const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, imm_offset)}; 143 const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, imm_offset)};
146 return ctx.OpLoad(result_type, access_chain); 144 return ctx.OpLoad(result_type, access_chain);
147} 145}
148 146
149Id GetCbufU32x4(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 147Id GetCbufU32x4(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
150 return GetCbuf(ctx, ctx.U32[4], &UniformDefinitions::U32x4, sizeof(u32[4]), binding, offset, 148 return GetCbuf(ctx, ctx.U32[4], &UniformDefinitions::U32x4, sizeof(u32[4]), binding, offset);
151 false);
152} 149}
153 150
154Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 index_offset) { 151Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 index_offset) {
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
index 88bbac0a5..b446aae0e 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
@@ -122,14 +122,14 @@ IR::F64 TranslatorVisitor::GetDoubleReg39(u64 insn) {
122static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { 122static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) {
123 union { 123 union {
124 u64 raw; 124 u64 raw;
125 BitField<20, 14, s64> offset; 125 BitField<20, 14, u64> offset;
126 BitField<34, 5, u64> binding; 126 BitField<34, 5, u64> binding;
127 } const cbuf{insn}; 127 } const cbuf{insn};
128 128
129 if (cbuf.binding >= 18) { 129 if (cbuf.binding >= 18) {
130 throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding); 130 throw NotImplementedException("Out of bounds constant buffer binding {}", cbuf.binding);
131 } 131 }
132 if (cbuf.offset >= 0x10'000 || cbuf.offset < 0) { 132 if (cbuf.offset >= 0x10'000) {
133 throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset); 133 throw NotImplementedException("Out of bounds constant buffer offset {}", cbuf.offset);
134 } 134 }
135 const IR::Value binding{static_cast<u32>(cbuf.binding)}; 135 const IR::Value binding{static_cast<u32>(cbuf.binding)};