summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend/spirv/spirv_emit_context.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp51
1 files changed, 51 insertions, 0 deletions
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;