diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv/spirv_emit_context.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | 64 |
1 files changed, 64 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 cd90c084a..f85541a2e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -464,6 +464,7 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf | |||
| 464 | DefineSharedMemory(program); | 464 | DefineSharedMemory(program); |
| 465 | DefineSharedMemoryFunctions(program); | 465 | DefineSharedMemoryFunctions(program); |
| 466 | DefineConstantBuffers(program.info, uniform_binding); | 466 | DefineConstantBuffers(program.info, uniform_binding); |
| 467 | DefineConstantBufferIndirectFunctions(program.info); | ||
| 467 | DefineStorageBuffers(program.info, storage_binding); | 468 | DefineStorageBuffers(program.info, storage_binding); |
| 468 | DefineTextureBuffers(program.info, texture_binding); | 469 | DefineTextureBuffers(program.info, texture_binding); |
| 469 | DefineImageBuffers(program.info, image_binding); | 470 | DefineImageBuffers(program.info, image_binding); |
| @@ -1027,6 +1028,69 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { | |||
| 1027 | binding += static_cast<u32>(info.constant_buffer_descriptors.size()); | 1028 | binding += static_cast<u32>(info.constant_buffer_descriptors.size()); |
| 1028 | } | 1029 | } |
| 1029 | 1030 | ||
| 1031 | void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | ||
| 1032 | if (!info.uses_cbuf_indirect) { | ||
| 1033 | return; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | const auto make_accessor{[&](Id buffer_type, Id UniformDefinitions::*member_ptr) { | ||
| 1037 | const Id func_type{TypeFunction(buffer_type, U32[1], U32[1])}; | ||
| 1038 | const Id func{OpFunction(buffer_type, spv::FunctionControlMask::MaskNone, func_type)}; | ||
| 1039 | const Id binding{OpFunctionParameter(U32[1])}; | ||
| 1040 | const Id offset{OpFunctionParameter(U32[1])}; | ||
| 1041 | |||
| 1042 | AddLabel(); | ||
| 1043 | |||
| 1044 | const Id merge_label{OpLabel()}; | ||
| 1045 | const Id uniform_type{uniform_types.*member_ptr}; | ||
| 1046 | |||
| 1047 | std::array<Id, Info::MAX_CBUFS> buf_labels; | ||
| 1048 | std::array<Sirit::Literal, Info::MAX_CBUFS> buf_literals; | ||
| 1049 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | ||
| 1050 | buf_labels[i] = OpLabel(); | ||
| 1051 | buf_literals[i] = Sirit::Literal{i}; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); | ||
| 1055 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); | ||
| 1056 | |||
| 1057 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | ||
| 1058 | AddLabel(buf_labels[i]); | ||
| 1059 | const Id cbuf{cbufs[i].*member_ptr}; | ||
| 1060 | const Id access_chain{OpAccessChain(uniform_type, cbuf, u32_zero_value, offset)}; | ||
| 1061 | const Id result{OpLoad(buffer_type, access_chain)}; | ||
| 1062 | OpReturnValue(result); | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | AddLabel(merge_label); | ||
| 1066 | OpUnreachable(); | ||
| 1067 | OpFunctionEnd(); | ||
| 1068 | |||
| 1069 | return func; | ||
| 1070 | }}; | ||
| 1071 | |||
| 1072 | IR::Type types{info.used_constant_buffer_types}; | ||
| 1073 | |||
| 1074 | if (True(types & IR::Type::U8)) { | ||
| 1075 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); | ||
| 1076 | } | ||
| 1077 | if (True(types & IR::Type::U16)) { | ||
| 1078 | load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); | ||
| 1079 | } | ||
| 1080 | if (True(types & IR::Type::F32)) { | ||
| 1081 | load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32); | ||
| 1082 | } | ||
| 1083 | if (True(types & IR::Type::U32)) { | ||
| 1084 | load_const_func_u32 = make_accessor(U32[1], &UniformDefinitions::U32); | ||
| 1085 | } | ||
| 1086 | if (True(types & IR::Type::U32x2)) { | ||
| 1087 | load_const_func_u32x2 = make_accessor(U32[2], &UniformDefinitions::U32x2); | ||
| 1088 | } | ||
| 1089 | if (True(types & IR::Type::U32x4)) { | ||
| 1090 | load_const_func_u32x4 = make_accessor(U32[4], &UniformDefinitions::U32x4); | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | |||
| 1030 | void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { | 1094 | void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { |
| 1031 | if (info.storage_buffers_descriptors.empty()) { | 1095 | if (info.storage_buffers_descriptors.empty()) { |
| 1032 | return; | 1096 | return; |