summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp136
1 files changed, 99 insertions, 37 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
index 8849258e3..a6a3f3351 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
@@ -8,44 +8,62 @@
8 8
9namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
10namespace { 10namespace {
11Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size) { 11Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size,
12 u32 index_offset = 0) {
12 if (offset.IsImmediate()) { 13 if (offset.IsImmediate()) {
13 const u32 imm_offset{static_cast<u32>(offset.U32() / element_size)}; 14 const u32 imm_offset{static_cast<u32>(offset.U32() / element_size) + index_offset};
14 return ctx.Const(imm_offset); 15 return ctx.Const(imm_offset);
15 } 16 }
16 const u32 shift{static_cast<u32>(std::countr_zero(element_size))}; 17 const u32 shift{static_cast<u32>(std::countr_zero(element_size))};
17 const Id index{ctx.Def(offset)}; 18 Id index{ctx.Def(offset)};
18 if (shift == 0) { 19 if (shift != 0) {
19 return index; 20 const Id shift_id{ctx.Const(shift)};
21 index = ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id);
20 } 22 }
21 const Id shift_id{ctx.Const(shift)}; 23 if (index_offset != 0) {
22 return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); 24 index = ctx.OpIAdd(ctx.U32[1], index, ctx.Const(index_offset));
25 }
26 return index;
23} 27}
24 28
25Id StoragePointer(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 29Id StoragePointer(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
26 const StorageTypeDefinition& type_def, size_t element_size, 30 const StorageTypeDefinition& type_def, size_t element_size,
27 Id StorageDefinitions::*member_ptr) { 31 Id StorageDefinitions::*member_ptr, u32 index_offset = 0) {
28 if (!binding.IsImmediate()) { 32 if (!binding.IsImmediate()) {
29 throw NotImplementedException("Dynamic storage buffer indexing"); 33 throw NotImplementedException("Dynamic storage buffer indexing");
30 } 34 }
31 const Id ssbo{ctx.ssbos[binding.U32()].*member_ptr}; 35 const Id ssbo{ctx.ssbos[binding.U32()].*member_ptr};
32 const Id index{StorageIndex(ctx, offset, element_size)}; 36 const Id index{StorageIndex(ctx, offset, element_size, index_offset)};
33 return ctx.OpAccessChain(type_def.element, ssbo, ctx.u32_zero_value, index); 37 return ctx.OpAccessChain(type_def.element, ssbo, ctx.u32_zero_value, index);
34} 38}
35 39
36Id LoadStorage(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id result_type, 40Id LoadStorage(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id result_type,
37 const StorageTypeDefinition& type_def, size_t element_size, 41 const StorageTypeDefinition& type_def, size_t element_size,
38 Id StorageDefinitions::*member_ptr) { 42 Id StorageDefinitions::*member_ptr, u32 index_offset = 0) {
39 const Id pointer{StoragePointer(ctx, binding, offset, type_def, element_size, member_ptr)}; 43 const Id pointer{
44 StoragePointer(ctx, binding, offset, type_def, element_size, member_ptr, index_offset)};
40 return ctx.OpLoad(result_type, pointer); 45 return ctx.OpLoad(result_type, pointer);
41} 46}
42 47
48Id LoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
49 u32 index_offset = 0) {
50 return LoadStorage(ctx, binding, offset, ctx.U32[1], ctx.storage_types.U32, sizeof(u32),
51 &StorageDefinitions::U32, index_offset);
52}
53
43void WriteStorage(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value, 54void WriteStorage(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value,
44 const StorageTypeDefinition& type_def, size_t element_size, 55 const StorageTypeDefinition& type_def, size_t element_size,
45 Id StorageDefinitions::*member_ptr) { 56 Id StorageDefinitions::*member_ptr, u32 index_offset = 0) {
46 const Id pointer{StoragePointer(ctx, binding, offset, type_def, element_size, member_ptr)}; 57 const Id pointer{
58 StoragePointer(ctx, binding, offset, type_def, element_size, member_ptr, index_offset)};
47 ctx.OpStore(pointer, value); 59 ctx.OpStore(pointer, value);
48} 60}
61
62void WriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value,
63 u32 index_offset = 0) {
64 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32),
65 &StorageDefinitions::U32, index_offset);
66}
49} // Anonymous namespace 67} // Anonymous namespace
50 68
51void EmitLoadGlobalU8(EmitContext&) { 69void EmitLoadGlobalU8(EmitContext&) {
@@ -105,42 +123,73 @@ void EmitWriteGlobal128(EmitContext& ctx, Id address, Id value) {
105} 123}
106 124
107Id EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 125Id EmitLoadStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
108 return ctx.OpUConvert(ctx.U32[1], 126 if (ctx.profile.support_descriptor_aliasing) {
109 LoadStorage(ctx, binding, offset, ctx.U8, ctx.storage_types.U8, 127 return ctx.OpUConvert(ctx.U32[1],
110 sizeof(u8), &StorageDefinitions::U8)); 128 LoadStorage(ctx, binding, offset, ctx.U8, ctx.storage_types.U8,
129 sizeof(u8), &StorageDefinitions::U8));
130 } else {
131 return ctx.OpBitFieldUExtract(ctx.U32[1], LoadStorage32(ctx, binding, offset),
132 ctx.BitOffset8(offset), ctx.Const(8u));
133 }
111} 134}
112 135
113Id EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 136Id EmitLoadStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
114 return ctx.OpSConvert(ctx.U32[1], 137 if (ctx.profile.support_descriptor_aliasing) {
115 LoadStorage(ctx, binding, offset, ctx.S8, ctx.storage_types.S8, 138 return ctx.OpSConvert(ctx.U32[1],
116 sizeof(s8), &StorageDefinitions::S8)); 139 LoadStorage(ctx, binding, offset, ctx.S8, ctx.storage_types.S8,
140 sizeof(s8), &StorageDefinitions::S8));
141 } else {
142 return ctx.OpBitFieldSExtract(ctx.U32[1], LoadStorage32(ctx, binding, offset),
143 ctx.BitOffset8(offset), ctx.Const(8u));
144 }
117} 145}
118 146
119Id EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 147Id EmitLoadStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
120 return ctx.OpUConvert(ctx.U32[1], 148 if (ctx.profile.support_descriptor_aliasing) {
121 LoadStorage(ctx, binding, offset, ctx.U16, ctx.storage_types.U16, 149 return ctx.OpUConvert(ctx.U32[1],
122 sizeof(u16), &StorageDefinitions::U16)); 150 LoadStorage(ctx, binding, offset, ctx.U16, ctx.storage_types.U16,
151 sizeof(u16), &StorageDefinitions::U16));
152 } else {
153 return ctx.OpBitFieldUExtract(ctx.U32[1], LoadStorage32(ctx, binding, offset),
154 ctx.BitOffset16(offset), ctx.Const(16u));
155 }
123} 156}
124 157
125Id EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 158Id EmitLoadStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
126 return ctx.OpSConvert(ctx.U32[1], 159 if (ctx.profile.support_descriptor_aliasing) {
127 LoadStorage(ctx, binding, offset, ctx.S16, ctx.storage_types.S16, 160 return ctx.OpSConvert(ctx.U32[1],
128 sizeof(s16), &StorageDefinitions::S16)); 161 LoadStorage(ctx, binding, offset, ctx.S16, ctx.storage_types.S16,
162 sizeof(s16), &StorageDefinitions::S16));
163 } else {
164 return ctx.OpBitFieldSExtract(ctx.U32[1], LoadStorage32(ctx, binding, offset),
165 ctx.BitOffset16(offset), ctx.Const(16u));
166 }
129} 167}
130 168
131Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 169Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
132 return LoadStorage(ctx, binding, offset, ctx.U32[1], ctx.storage_types.U32, sizeof(u32), 170 return LoadStorage32(ctx, binding, offset);
133 &StorageDefinitions::U32);
134} 171}
135 172
136Id EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 173Id EmitLoadStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
137 return LoadStorage(ctx, binding, offset, ctx.U32[2], ctx.storage_types.U32x2, sizeof(u32[2]), 174 if (ctx.profile.support_descriptor_aliasing) {
138 &StorageDefinitions::U32x2); 175 return LoadStorage(ctx, binding, offset, ctx.U32[2], ctx.storage_types.U32x2,
176 sizeof(u32[2]), &StorageDefinitions::U32x2);
177 } else {
178 return ctx.OpCompositeConstruct(ctx.U32[2], LoadStorage32(ctx, binding, offset, 0),
179 LoadStorage32(ctx, binding, offset, 1));
180 }
139} 181}
140 182
141Id EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 183Id EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
142 return LoadStorage(ctx, binding, offset, ctx.U32[4], ctx.storage_types.U32x4, sizeof(u32[4]), 184 if (ctx.profile.support_descriptor_aliasing) {
143 &StorageDefinitions::U32x4); 185 return LoadStorage(ctx, binding, offset, ctx.U32[4], ctx.storage_types.U32x4,
186 sizeof(u32[4]), &StorageDefinitions::U32x4);
187 } else {
188 return ctx.OpCompositeConstruct(ctx.U32[4], LoadStorage32(ctx, binding, offset, 0),
189 LoadStorage32(ctx, binding, offset, 1),
190 LoadStorage32(ctx, binding, offset, 2),
191 LoadStorage32(ctx, binding, offset, 3));
192 }
144} 193}
145 194
146void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 195void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
@@ -169,20 +218,33 @@ void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::V
169 218
170void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 219void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
171 Id value) { 220 Id value) {
172 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32), 221 WriteStorage32(ctx, binding, offset, value);
173 &StorageDefinitions::U32);
174} 222}
175 223
176void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 224void EmitWriteStorage64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
177 Id value) { 225 Id value) {
178 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32x2, sizeof(u32[2]), 226 if (ctx.profile.support_descriptor_aliasing) {
179 &StorageDefinitions::U32x2); 227 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32x2, sizeof(u32[2]),
228 &StorageDefinitions::U32x2);
229 } else {
230 for (u32 index = 0; index < 2; ++index) {
231 const Id element{ctx.OpCompositeExtract(ctx.U32[1], value, index)};
232 WriteStorage32(ctx, binding, offset, element, index);
233 }
234 }
180} 235}
181 236
182void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 237void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
183 Id value) { 238 Id value) {
184 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32x4, sizeof(u32[4]), 239 if (ctx.profile.support_descriptor_aliasing) {
185 &StorageDefinitions::U32x4); 240 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32x4, sizeof(u32[4]),
241 &StorageDefinitions::U32x4);
242 } else {
243 for (u32 index = 0; index < 4; ++index) {
244 const Id element{ctx.OpCompositeExtract(ctx.U32[1], value, index)};
245 WriteStorage32(ctx, binding, offset, element, index);
246 }
247 }
186} 248}
187 249
188} // namespace Shader::Backend::SPIRV 250} // namespace Shader::Backend::SPIRV