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_memory.cpp40
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp51
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h3
3 files changed, 86 insertions, 8 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
index 8693801c7..bdcbccfde 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
@@ -65,6 +65,14 @@ void WriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value&
65 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32), 65 WriteStorage(ctx, binding, offset, value, ctx.storage_types.U32, sizeof(u32),
66 &StorageDefinitions::U32, index_offset); 66 &StorageDefinitions::U32, index_offset);
67} 67}
68
69void WriteStorageByCasLoop(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
70 Id value, Id bit_offset, Id bit_count) {
71 const Id pointer{StoragePointer(ctx, binding, offset, ctx.storage_types.U32, sizeof(u32),
72 &StorageDefinitions::U32)};
73 ctx.OpFunctionCall(ctx.TypeVoid(), ctx.write_storage_cas_loop_func, pointer, value, bit_offset,
74 bit_count);
75}
68} // Anonymous namespace 76} // Anonymous namespace
69 77
70void EmitLoadGlobalU8(EmitContext&) { 78void EmitLoadGlobalU8(EmitContext&) {
@@ -219,26 +227,42 @@ Id EmitLoadStorage128(EmitContext& ctx, const IR::Value& binding, const IR::Valu
219 227
220void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 228void EmitWriteStorageU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
221 Id value) { 229 Id value) {
222 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8, 230 if (ctx.profile.support_int8) {
223 sizeof(u8), &StorageDefinitions::U8); 231 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U8, value), ctx.storage_types.U8,
232 sizeof(u8), &StorageDefinitions::U8);
233 } else {
234 WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset8(offset), ctx.Const(8u));
235 }
224} 236}
225 237
226void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 238void EmitWriteStorageS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
227 Id value) { 239 Id value) {
228 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8, 240 if (ctx.profile.support_int8) {
229 sizeof(s8), &StorageDefinitions::S8); 241 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S8, value), ctx.storage_types.S8,
242 sizeof(s8), &StorageDefinitions::S8);
243 } else {
244 WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset8(offset), ctx.Const(8u));
245 }
230} 246}
231 247
232void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 248void EmitWriteStorageU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
233 Id value) { 249 Id value) {
234 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16, 250 if (ctx.profile.support_int16) {
235 sizeof(u16), &StorageDefinitions::U16); 251 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.U16, value), ctx.storage_types.U16,
252 sizeof(u16), &StorageDefinitions::U16);
253 } else {
254 WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset16(offset), ctx.Const(16u));
255 }
236} 256}
237 257
238void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 258void EmitWriteStorageS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
239 Id value) { 259 Id value) {
240 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16, 260 if (ctx.profile.support_int16) {
241 sizeof(s16), &StorageDefinitions::S16); 261 WriteStorage(ctx, binding, offset, ctx.OpSConvert(ctx.S16, value), ctx.storage_types.S16,
262 sizeof(s16), &StorageDefinitions::S16);
263 } else {
264 WriteStorageByCasLoop(ctx, binding, offset, value, ctx.BitOffset16(offset), ctx.Const(16u));
265 }
242} 266}
243 267
244void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, 268void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset,
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index 0442adc83..a27f2f73a 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -480,6 +480,7 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
480 DefineTextures(program.info, texture_binding, bindings.texture_scaling_index); 480 DefineTextures(program.info, texture_binding, bindings.texture_scaling_index);
481 DefineImages(program.info, image_binding, bindings.image_scaling_index); 481 DefineImages(program.info, image_binding, bindings.image_scaling_index);
482 DefineAttributeMemAccess(program.info); 482 DefineAttributeMemAccess(program.info);
483 DefineWriteStorageCasLoopFunction(program.info);
483 DefineGlobalMemoryFunctions(program.info); 484 DefineGlobalMemoryFunctions(program.info);
484 DefineRescalingInput(program.info); 485 DefineRescalingInput(program.info);
485 DefineRenderArea(program.info); 486 DefineRenderArea(program.info);
@@ -877,6 +878,56 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
877 } 878 }
878} 879}
879 880
881void EmitContext::DefineWriteStorageCasLoopFunction(const Info& info) {
882 if (profile.support_int8 && profile.support_int16) {
883 return;
884 }
885 if (!info.uses_int8 && !info.uses_int16) {
886 return;
887 }
888
889 AddCapability(spv::Capability::VariablePointersStorageBuffer);
890
891 const Id ptr_type{TypePointer(spv::StorageClass::StorageBuffer, U32[1])};
892 const Id func_type{TypeFunction(void_id, ptr_type, U32[1], U32[1], U32[1])};
893 const Id func{OpFunction(void_id, spv::FunctionControlMask::MaskNone, func_type)};
894 const Id pointer{OpFunctionParameter(ptr_type)};
895 const Id value{OpFunctionParameter(U32[1])};
896 const Id bit_offset{OpFunctionParameter(U32[1])};
897 const Id bit_count{OpFunctionParameter(U32[1])};
898
899 AddLabel();
900 const Id scope_device{Const(1u)};
901 const Id ordering_relaxed{u32_zero_value};
902 const Id body_label{OpLabel()};
903 const Id continue_label{OpLabel()};
904 const Id endloop_label{OpLabel()};
905 const Id beginloop_label{OpLabel()};
906 OpBranch(beginloop_label);
907
908 AddLabel(beginloop_label);
909 OpLoopMerge(endloop_label, continue_label, spv::LoopControlMask::MaskNone);
910 OpBranch(body_label);
911
912 AddLabel(body_label);
913 const Id expected_value{OpLoad(U32[1], pointer)};
914 const Id desired_value{OpBitFieldInsert(U32[1], expected_value, value, bit_offset, bit_count)};
915 const Id actual_value{OpAtomicCompareExchange(U32[1], pointer, scope_device, ordering_relaxed,
916 ordering_relaxed, desired_value, expected_value)};
917 const Id store_successful{OpIEqual(U1, expected_value, actual_value)};
918 OpBranchConditional(store_successful, endloop_label, continue_label);
919
920 AddLabel(endloop_label);
921 OpReturn();
922
923 AddLabel(continue_label);
924 OpBranch(beginloop_label);
925
926 OpFunctionEnd();
927
928 write_storage_cas_loop_func = func;
929}
930
880void EmitContext::DefineGlobalMemoryFunctions(const Info& info) { 931void EmitContext::DefineGlobalMemoryFunctions(const Info& info) {
881 if (!info.uses_global_memory || !profile.support_int64) { 932 if (!info.uses_global_memory || !profile.support_int64) {
882 return; 933 return;
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index 56019ad89..40adcb6b6 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -325,6 +325,8 @@ public:
325 Id f32x2_min_cas{}; 325 Id f32x2_min_cas{};
326 Id f32x2_max_cas{}; 326 Id f32x2_max_cas{};
327 327
328 Id write_storage_cas_loop_func{};
329
328 Id load_global_func_u32{}; 330 Id load_global_func_u32{};
329 Id load_global_func_u32x2{}; 331 Id load_global_func_u32x2{};
330 Id load_global_func_u32x4{}; 332 Id load_global_func_u32x4{};
@@ -372,6 +374,7 @@ private:
372 void DefineTextures(const Info& info, u32& binding, u32& scaling_index); 374 void DefineTextures(const Info& info, u32& binding, u32& scaling_index);
373 void DefineImages(const Info& info, u32& binding, u32& scaling_index); 375 void DefineImages(const Info& info, u32& binding, u32& scaling_index);
374 void DefineAttributeMemAccess(const Info& info); 376 void DefineAttributeMemAccess(const Info& info);
377 void DefineWriteStorageCasLoopFunction(const Info& info);
375 void DefineGlobalMemoryFunctions(const Info& info); 378 void DefineGlobalMemoryFunctions(const Info& info);
376 void DefineRescalingInput(const Info& info); 379 void DefineRescalingInput(const Info& info);
377 void DefineRescalingInputPushConstant(); 380 void DefineRescalingInputPushConstant();