summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp23
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h36
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
126Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 143Id 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
69struct StorageTypeDefinition { 105struct StorageTypeDefinition {