diff options
Diffstat (limited to 'src')
12 files changed, 101 insertions, 112 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index b9e6d5655..214ef9c25 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -131,13 +131,13 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, | |||
| 131 | case Stage::TessellationControl: | 131 | case Stage::TessellationControl: |
| 132 | case Stage::TessellationEval: | 132 | case Stage::TessellationEval: |
| 133 | if (per_invocation) { | 133 | if (per_invocation) { |
| 134 | type = ctx.TypeArray(type, ctx.Constant(ctx.U32[1], 32u)); | 134 | type = ctx.TypeArray(type, ctx.Const(32u)); |
| 135 | } | 135 | } |
| 136 | break; | 136 | break; |
| 137 | case Stage::Geometry: | 137 | case Stage::Geometry: |
| 138 | if (per_invocation) { | 138 | if (per_invocation) { |
| 139 | const u32 num_vertices{NumVertices(ctx.profile.input_topology)}; | 139 | const u32 num_vertices{NumVertices(ctx.profile.input_topology)}; |
| 140 | type = ctx.TypeArray(type, ctx.Constant(ctx.U32[1], num_vertices)); | 140 | type = ctx.TypeArray(type, ctx.Const(num_vertices)); |
| 141 | } | 141 | } |
| 142 | break; | 142 | break; |
| 143 | default: | 143 | default: |
| @@ -149,7 +149,7 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, | |||
| 149 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, | 149 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, |
| 150 | std::optional<spv::BuiltIn> builtin = std::nullopt) { | 150 | std::optional<spv::BuiltIn> builtin = std::nullopt) { |
| 151 | if (invocations && ctx.stage == Stage::TessellationControl) { | 151 | if (invocations && ctx.stage == Stage::TessellationControl) { |
| 152 | type = ctx.TypeArray(type, ctx.Constant(ctx.U32[1], *invocations)); | 152 | type = ctx.TypeArray(type, ctx.Const(*invocations)); |
| 153 | } | 153 | } |
| 154 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); | 154 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); |
| 155 | } | 155 | } |
| @@ -224,7 +224,7 @@ std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { | |||
| 224 | 224 | ||
| 225 | void DefineConstBuffers(EmitContext& ctx, const Info& info, Id UniformDefinitions::*member_type, | 225 | void DefineConstBuffers(EmitContext& ctx, const Info& info, Id UniformDefinitions::*member_type, |
| 226 | u32 binding, Id type, char type_char, u32 element_size) { | 226 | u32 binding, Id type, char type_char, u32 element_size) { |
| 227 | const Id array_type{ctx.TypeArray(type, ctx.Constant(ctx.U32[1], 65536U / element_size))}; | 227 | const Id array_type{ctx.TypeArray(type, ctx.Const(65536U / element_size))}; |
| 228 | ctx.Decorate(array_type, spv::Decoration::ArrayStride, element_size); | 228 | ctx.Decorate(array_type, spv::Decoration::ArrayStride, element_size); |
| 229 | 229 | ||
| 230 | const Id struct_type{ctx.TypeStruct(array_type)}; | 230 | const Id struct_type{ctx.TypeStruct(array_type)}; |
| @@ -328,7 +328,7 @@ Id CasLoop(EmitContext& ctx, Operation operation, Id array_pointer, Id element_p | |||
| 328 | const bool is_struct{!is_shared || ctx.profile.support_explicit_workgroup_layout}; | 328 | const bool is_struct{!is_shared || ctx.profile.support_explicit_workgroup_layout}; |
| 329 | const Id cas_func{CasFunction(ctx, operation, value_type)}; | 329 | const Id cas_func{CasFunction(ctx, operation, value_type)}; |
| 330 | const Id zero{ctx.u32_zero_value}; | 330 | const Id zero{ctx.u32_zero_value}; |
| 331 | const Id scope_id{ctx.Constant(ctx.U32[1], static_cast<u32>(scope))}; | 331 | const Id scope_id{ctx.Const(static_cast<u32>(scope))}; |
| 332 | 332 | ||
| 333 | const Id loop_header{ctx.OpLabel()}; | 333 | const Id loop_header{ctx.OpLabel()}; |
| 334 | const Id continue_block{ctx.OpLabel()}; | 334 | const Id continue_block{ctx.OpLabel()}; |
| @@ -428,11 +428,11 @@ Id EmitContext::Def(const IR::Value& value) { | |||
| 428 | case IR::Type::U1: | 428 | case IR::Type::U1: |
| 429 | return value.U1() ? true_value : false_value; | 429 | return value.U1() ? true_value : false_value; |
| 430 | case IR::Type::U32: | 430 | case IR::Type::U32: |
| 431 | return Constant(U32[1], value.U32()); | 431 | return Const(value.U32()); |
| 432 | case IR::Type::U64: | 432 | case IR::Type::U64: |
| 433 | return Constant(U64, value.U64()); | 433 | return Constant(U64, value.U64()); |
| 434 | case IR::Type::F32: | 434 | case IR::Type::F32: |
| 435 | return Constant(F32[1], value.F32()); | 435 | return Const(value.F32()); |
| 436 | case IR::Type::F64: | 436 | case IR::Type::F64: |
| 437 | return Constant(F64[1], value.F64()); | 437 | return Constant(F64[1], value.F64()); |
| 438 | case IR::Type::Label: | 438 | case IR::Type::Label: |
| @@ -486,8 +486,8 @@ void EmitContext::DefineCommonTypes(const Info& info) { | |||
| 486 | void EmitContext::DefineCommonConstants() { | 486 | void EmitContext::DefineCommonConstants() { |
| 487 | true_value = ConstantTrue(U1); | 487 | true_value = ConstantTrue(U1); |
| 488 | false_value = ConstantFalse(U1); | 488 | false_value = ConstantFalse(U1); |
| 489 | u32_zero_value = Constant(U32[1], 0U); | 489 | u32_zero_value = Const(0U); |
| 490 | f32_zero_value = Constant(F32[1], 0.0f); | 490 | f32_zero_value = Const(0.0f); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | void EmitContext::DefineInterfaces(const IR::Program& program) { | 493 | void EmitContext::DefineInterfaces(const IR::Program& program) { |
| @@ -500,7 +500,7 @@ void EmitContext::DefineLocalMemory(const IR::Program& program) { | |||
| 500 | return; | 500 | return; |
| 501 | } | 501 | } |
| 502 | const u32 num_elements{Common::DivCeil(program.local_memory_size, 4U)}; | 502 | const u32 num_elements{Common::DivCeil(program.local_memory_size, 4U)}; |
| 503 | const Id type{TypeArray(U32[1], Constant(U32[1], num_elements))}; | 503 | const Id type{TypeArray(U32[1], Const(num_elements))}; |
| 504 | const Id pointer{TypePointer(spv::StorageClass::Private, type)}; | 504 | const Id pointer{TypePointer(spv::StorageClass::Private, type)}; |
| 505 | local_memory = AddGlobalVariable(pointer, spv::StorageClass::Private); | 505 | local_memory = AddGlobalVariable(pointer, spv::StorageClass::Private); |
| 506 | if (profile.supported_spirv >= 0x00010400) { | 506 | if (profile.supported_spirv >= 0x00010400) { |
| @@ -514,7 +514,7 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { | |||
| 514 | } | 514 | } |
| 515 | const auto make{[&](Id element_type, u32 element_size) { | 515 | const auto make{[&](Id element_type, u32 element_size) { |
| 516 | const u32 num_elements{Common::DivCeil(program.shared_memory_size, element_size)}; | 516 | const u32 num_elements{Common::DivCeil(program.shared_memory_size, element_size)}; |
| 517 | const Id array_type{TypeArray(element_type, Constant(U32[1], num_elements))}; | 517 | const Id array_type{TypeArray(element_type, Const(num_elements))}; |
| 518 | Decorate(array_type, spv::Decoration::ArrayStride, element_size); | 518 | Decorate(array_type, spv::Decoration::ArrayStride, element_size); |
| 519 | 519 | ||
| 520 | const Id struct_type{TypeStruct(array_type)}; | 520 | const Id struct_type{TypeStruct(array_type)}; |
| @@ -549,7 +549,7 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { | |||
| 549 | return; | 549 | return; |
| 550 | } | 550 | } |
| 551 | const u32 num_elements{Common::DivCeil(program.shared_memory_size, 4U)}; | 551 | const u32 num_elements{Common::DivCeil(program.shared_memory_size, 4U)}; |
| 552 | const Id type{TypeArray(U32[1], Constant(U32[1], num_elements))}; | 552 | const Id type{TypeArray(U32[1], Const(num_elements))}; |
| 553 | shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); | 553 | shared_memory_u32_type = TypePointer(spv::StorageClass::Workgroup, type); |
| 554 | 554 | ||
| 555 | shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); | 555 | shared_u32 = TypePointer(spv::StorageClass::Workgroup, U32[1]); |
| @@ -569,10 +569,10 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { | |||
| 569 | OpBranch(loop_header); | 569 | OpBranch(loop_header); |
| 570 | 570 | ||
| 571 | AddLabel(loop_header); | 571 | AddLabel(loop_header); |
| 572 | const Id word_offset{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; | 572 | const Id word_offset{OpShiftRightArithmetic(U32[1], offset, Const(2U))}; |
| 573 | const Id shift_offset{OpShiftLeftLogical(U32[1], offset, Constant(U32[1], 3U))}; | 573 | const Id shift_offset{OpShiftLeftLogical(U32[1], offset, Const(3U))}; |
| 574 | const Id bit_offset{OpBitwiseAnd(U32[1], shift_offset, Constant(U32[1], mask))}; | 574 | const Id bit_offset{OpBitwiseAnd(U32[1], shift_offset, Const(mask))}; |
| 575 | const Id count{Constant(U32[1], size)}; | 575 | const Id count{Const(size)}; |
| 576 | OpLoopMerge(merge_block, continue_block, spv::LoopControlMask::MaskNone); | 576 | OpLoopMerge(merge_block, continue_block, spv::LoopControlMask::MaskNone); |
| 577 | OpBranch(continue_block); | 577 | OpBranch(continue_block); |
| 578 | 578 | ||
| @@ -580,9 +580,8 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { | |||
| 580 | const Id word_pointer{OpAccessChain(shared_u32, shared_memory_u32, word_offset)}; | 580 | const Id word_pointer{OpAccessChain(shared_u32, shared_memory_u32, word_offset)}; |
| 581 | const Id old_value{OpLoad(U32[1], word_pointer)}; | 581 | const Id old_value{OpLoad(U32[1], word_pointer)}; |
| 582 | const Id new_value{OpBitFieldInsert(U32[1], old_value, insert_value, bit_offset, count)}; | 582 | const Id new_value{OpBitFieldInsert(U32[1], old_value, insert_value, bit_offset, count)}; |
| 583 | const Id atomic_res{OpAtomicCompareExchange(U32[1], word_pointer, Constant(U32[1], 1U), | 583 | const Id atomic_res{OpAtomicCompareExchange(U32[1], word_pointer, Const(1U), u32_zero_value, |
| 584 | u32_zero_value, u32_zero_value, new_value, | 584 | u32_zero_value, new_value, old_value)}; |
| 585 | old_value)}; | ||
| 586 | const Id success{OpIEqual(U1, atomic_res, old_value)}; | 585 | const Id success{OpIEqual(U1, atomic_res, old_value)}; |
| 587 | OpBranchConditional(success, merge_block, loop_header); | 586 | OpBranchConditional(success, merge_block, loop_header); |
| 588 | 587 | ||
| @@ -623,9 +622,9 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 623 | const Id vertex{is_array ? OpFunctionParameter(U32[1]) : Id{}}; | 622 | const Id vertex{is_array ? OpFunctionParameter(U32[1]) : Id{}}; |
| 624 | 623 | ||
| 625 | AddLabel(); | 624 | AddLabel(); |
| 626 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; | 625 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Const(2U))}; |
| 627 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; | 626 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Const(3U))}; |
| 628 | const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Constant(U32[1], 2U))}; | 627 | const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))}; |
| 629 | std::vector<Sirit::Literal> literals; | 628 | std::vector<Sirit::Literal> literals; |
| 630 | std::vector<Id> labels; | 629 | std::vector<Id> labels; |
| 631 | if (info.loads_position) { | 630 | if (info.loads_position) { |
| @@ -643,7 +642,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 643 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); | 642 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); |
| 644 | OpSwitch(compare_index, default_label, literals, labels); | 643 | OpSwitch(compare_index, default_label, literals, labels); |
| 645 | AddLabel(default_label); | 644 | AddLabel(default_label); |
| 646 | OpReturnValue(Constant(F32[1], 0.0f)); | 645 | OpReturnValue(Const(0.0f)); |
| 647 | size_t label_index{0}; | 646 | size_t label_index{0}; |
| 648 | if (info.loads_position) { | 647 | if (info.loads_position) { |
| 649 | AddLabel(labels[label_index]); | 648 | AddLabel(labels[label_index]); |
| @@ -661,7 +660,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 661 | AddLabel(labels[label_index]); | 660 | AddLabel(labels[label_index]); |
| 662 | const auto type{AttrTypes(*this, static_cast<u32>(i))}; | 661 | const auto type{AttrTypes(*this, static_cast<u32>(i))}; |
| 663 | if (!type) { | 662 | if (!type) { |
| 664 | OpReturnValue(Constant(F32[1], 0.0f)); | 663 | OpReturnValue(Const(0.0f)); |
| 665 | ++label_index; | 664 | ++label_index; |
| 666 | continue; | 665 | continue; |
| 667 | } | 666 | } |
| @@ -688,9 +687,9 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 688 | const Id offset{OpFunctionParameter(U32[1])}; | 687 | const Id offset{OpFunctionParameter(U32[1])}; |
| 689 | const Id store_value{OpFunctionParameter(F32[1])}; | 688 | const Id store_value{OpFunctionParameter(F32[1])}; |
| 690 | AddLabel(); | 689 | AddLabel(); |
| 691 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; | 690 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Const(2U))}; |
| 692 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; | 691 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Const(3U))}; |
| 693 | const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Constant(U32[1], 2U))}; | 692 | const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))}; |
| 694 | std::vector<Sirit::Literal> literals; | 693 | std::vector<Sirit::Literal> literals; |
| 695 | std::vector<Id> labels; | 694 | std::vector<Id> labels; |
| 696 | if (info.stores_position) { | 695 | if (info.stores_position) { |
| @@ -744,7 +743,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 744 | OpReturn(); | 743 | OpReturn(); |
| 745 | ++label_index; | 744 | ++label_index; |
| 746 | AddLabel(labels[label_index]); | 745 | AddLabel(labels[label_index]); |
| 747 | const Id fixed_index{OpIAdd(U32[1], masked_index, Constant(U32[1], 4))}; | 746 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; |
| 748 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; | 747 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; |
| 749 | OpStore(pointer2, store_value); | 748 | OpStore(pointer2, store_value); |
| 750 | OpReturn(); | 749 | OpReturn(); |
| @@ -1018,9 +1017,9 @@ void EmitContext::DefineInputs(const Info& info) { | |||
| 1018 | DefineInput(*this, U32[1], false, spv::BuiltIn::SubgroupLocalInvocationId); | 1017 | DefineInput(*this, U32[1], false, spv::BuiltIn::SubgroupLocalInvocationId); |
| 1019 | } | 1018 | } |
| 1020 | if (info.uses_fswzadd) { | 1019 | if (info.uses_fswzadd) { |
| 1021 | const Id f32_one{Constant(F32[1], 1.0f)}; | 1020 | const Id f32_one{Const(1.0f)}; |
| 1022 | const Id f32_minus_one{Constant(F32[1], -1.0f)}; | 1021 | const Id f32_minus_one{Const(-1.0f)}; |
| 1023 | const Id f32_zero{Constant(F32[1], 0.0f)}; | 1022 | const Id f32_zero{Const(0.0f)}; |
| 1024 | fswzadd_lut_a = ConstantComposite(F32[4], f32_minus_one, f32_one, f32_minus_one, f32_zero); | 1023 | fswzadd_lut_a = ConstantComposite(F32[4], f32_minus_one, f32_one, f32_minus_one, f32_zero); |
| 1025 | fswzadd_lut_b = | 1024 | fswzadd_lut_b = |
| 1026 | ConstantComposite(F32[4], f32_minus_one, f32_minus_one, f32_one, f32_minus_one); | 1025 | ConstantComposite(F32[4], f32_minus_one, f32_minus_one, f32_one, f32_minus_one); |
| @@ -1118,7 +1117,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1118 | if (stage == Stage::Fragment) { | 1117 | if (stage == Stage::Fragment) { |
| 1119 | throw NotImplementedException("Storing ClipDistance in fragment stage"); | 1118 | throw NotImplementedException("Storing ClipDistance in fragment stage"); |
| 1120 | } | 1119 | } |
| 1121 | const Id type{TypeArray(F32[1], Constant(U32[1], 8U))}; | 1120 | const Id type{TypeArray(F32[1], Const(8U))}; |
| 1122 | clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); | 1121 | clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); |
| 1123 | } | 1122 | } |
| 1124 | if (info.stores_layer && | 1123 | if (info.stores_layer && |
| @@ -1136,7 +1135,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1136 | viewport_index = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::ViewportIndex); | 1135 | viewport_index = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::ViewportIndex); |
| 1137 | } | 1136 | } |
| 1138 | if (info.stores_viewport_mask && profile.support_viewport_mask) { | 1137 | if (info.stores_viewport_mask && profile.support_viewport_mask) { |
| 1139 | viewport_mask = DefineOutput(*this, TypeArray(U32[1], Constant(U32[1], 1u)), std::nullopt); | 1138 | viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt); |
| 1140 | } | 1139 | } |
| 1141 | for (size_t index = 0; index < info.stores_generics.size(); ++index) { | 1140 | for (size_t index = 0; index < info.stores_generics.size(); ++index) { |
| 1142 | if (info.stores_generics[index]) { | 1141 | if (info.stores_generics[index]) { |
| @@ -1146,13 +1145,13 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1146 | switch (stage) { | 1145 | switch (stage) { |
| 1147 | case Stage::TessellationControl: | 1146 | case Stage::TessellationControl: |
| 1148 | if (info.stores_tess_level_outer) { | 1147 | if (info.stores_tess_level_outer) { |
| 1149 | const Id type{TypeArray(F32[1], Constant(U32[1], 4))}; | 1148 | const Id type{TypeArray(F32[1], Const(4U))}; |
| 1150 | output_tess_level_outer = | 1149 | output_tess_level_outer = |
| 1151 | DefineOutput(*this, type, std::nullopt, spv::BuiltIn::TessLevelOuter); | 1150 | DefineOutput(*this, type, std::nullopt, spv::BuiltIn::TessLevelOuter); |
| 1152 | Decorate(output_tess_level_outer, spv::Decoration::Patch); | 1151 | Decorate(output_tess_level_outer, spv::Decoration::Patch); |
| 1153 | } | 1152 | } |
| 1154 | if (info.stores_tess_level_inner) { | 1153 | if (info.stores_tess_level_inner) { |
| 1155 | const Id type{TypeArray(F32[1], Constant(U32[1], 2))}; | 1154 | const Id type{TypeArray(F32[1], Const(2U))}; |
| 1156 | output_tess_level_inner = | 1155 | output_tess_level_inner = |
| 1157 | DefineOutput(*this, type, std::nullopt, spv::BuiltIn::TessLevelInner); | 1156 | DefineOutput(*this, type, std::nullopt, spv::BuiltIn::TessLevelInner); |
| 1158 | Decorate(output_tess_level_inner, spv::Decoration::Patch); | 1157 | Decorate(output_tess_level_inner, spv::Decoration::Patch); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 7567fdcac..ef8507367 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -114,7 +114,7 @@ public: | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | Id Const(u32 element_1, u32 element_2, u32 element_3, u32 element_4) { | 116 | Id Const(u32 element_1, u32 element_2, u32 element_3, u32 element_4) { |
| 117 | return ConstantComposite(U32[2], Const(element_1), Const(element_2), Const(element_3), | 117 | return ConstantComposite(U32[4], Const(element_1), Const(element_2), Const(element_3), |
| 118 | Const(element_4)); | 118 | Const(element_4)); |
| 119 | } | 119 | } |
| 120 | 120 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index c2c879a6c..6e17d1c7e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp | |||
| @@ -7,10 +7,10 @@ | |||
| 7 | namespace Shader::Backend::SPIRV { | 7 | namespace Shader::Backend::SPIRV { |
| 8 | namespace { | 8 | namespace { |
| 9 | Id SharedPointer(EmitContext& ctx, Id offset, u32 index_offset = 0) { | 9 | Id SharedPointer(EmitContext& ctx, Id offset, u32 index_offset = 0) { |
| 10 | const Id shift_id{ctx.Constant(ctx.U32[1], 2U)}; | 10 | const Id shift_id{ctx.Const(2U)}; |
| 11 | Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 11 | Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 12 | if (index_offset > 0) { | 12 | if (index_offset > 0) { |
| 13 | index = ctx.OpIAdd(ctx.U32[1], index, ctx.Constant(ctx.U32[1], index_offset)); | 13 | index = ctx.OpIAdd(ctx.U32[1], index, ctx.Const(index_offset)); |
| 14 | } | 14 | } |
| 15 | return ctx.profile.support_explicit_workgroup_layout | 15 | return ctx.profile.support_explicit_workgroup_layout |
| 16 | ? ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, ctx.u32_zero_value, index) | 16 | ? ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, ctx.u32_zero_value, index) |
| @@ -20,14 +20,14 @@ Id SharedPointer(EmitContext& ctx, Id offset, u32 index_offset = 0) { | |||
| 20 | Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size) { | 20 | Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size) { |
| 21 | if (offset.IsImmediate()) { | 21 | if (offset.IsImmediate()) { |
| 22 | const u32 imm_offset{static_cast<u32>(offset.U32() / element_size)}; | 22 | const u32 imm_offset{static_cast<u32>(offset.U32() / element_size)}; |
| 23 | return ctx.Constant(ctx.U32[1], imm_offset); | 23 | return ctx.Const(imm_offset); |
| 24 | } | 24 | } |
| 25 | const u32 shift{static_cast<u32>(std::countr_zero(element_size))}; | 25 | const u32 shift{static_cast<u32>(std::countr_zero(element_size))}; |
| 26 | const Id index{ctx.Def(offset)}; | 26 | const Id index{ctx.Def(offset)}; |
| 27 | if (shift == 0) { | 27 | if (shift == 0) { |
| 28 | return index; | 28 | return index; |
| 29 | } | 29 | } |
| 30 | const Id shift_id{ctx.Constant(ctx.U32[1], shift)}; | 30 | const Id shift_id{ctx.Const(shift)}; |
| 31 | return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); | 31 | return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| @@ -43,7 +43,7 @@ Id StoragePointer(EmitContext& ctx, const StorageTypeDefinition& type_def, | |||
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | std::pair<Id, Id> AtomicArgs(EmitContext& ctx) { | 45 | std::pair<Id, Id> AtomicArgs(EmitContext& ctx) { |
| 46 | const Id scope{ctx.Constant(ctx.U32[1], static_cast<u32>(spv::Scope::Device))}; | 46 | const Id scope{ctx.Const(static_cast<u32>(spv::Scope::Device))}; |
| 47 | const Id semantics{ctx.u32_zero_value}; | 47 | const Id semantics{ctx.u32_zero_value}; |
| 48 | return {scope, semantics}; | 48 | return {scope, semantics}; |
| 49 | } | 49 | } |
| @@ -103,13 +103,13 @@ Id EmitSharedAtomicUMax32(EmitContext& ctx, Id offset, Id value) { | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | Id EmitSharedAtomicInc32(EmitContext& ctx, Id offset, Id value) { | 105 | Id EmitSharedAtomicInc32(EmitContext& ctx, Id offset, Id value) { |
| 106 | const Id shift_id{ctx.Constant(ctx.U32[1], 2U)}; | 106 | const Id shift_id{ctx.Const(2U)}; |
| 107 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 107 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 108 | return ctx.OpFunctionCall(ctx.U32[1], ctx.increment_cas_shared, index, value); | 108 | return ctx.OpFunctionCall(ctx.U32[1], ctx.increment_cas_shared, index, value); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | Id EmitSharedAtomicDec32(EmitContext& ctx, Id offset, Id value) { | 111 | Id EmitSharedAtomicDec32(EmitContext& ctx, Id offset, Id value) { |
| 112 | const Id shift_id{ctx.Constant(ctx.U32[1], 2U)}; | 112 | const Id shift_id{ctx.Const(2U)}; |
| 113 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 113 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 114 | return ctx.OpFunctionCall(ctx.U32[1], ctx.decrement_cas_shared, index, value); | 114 | return ctx.OpFunctionCall(ctx.U32[1], ctx.decrement_cas_shared, index, value); |
| 115 | } | 115 | } |
| @@ -132,7 +132,7 @@ Id EmitSharedAtomicExchange32(EmitContext& ctx, Id offset, Id value) { | |||
| 132 | 132 | ||
| 133 | Id EmitSharedAtomicExchange64(EmitContext& ctx, Id offset, Id value) { | 133 | Id EmitSharedAtomicExchange64(EmitContext& ctx, Id offset, Id value) { |
| 134 | if (ctx.profile.support_int64_atomics && ctx.profile.support_explicit_workgroup_layout) { | 134 | if (ctx.profile.support_int64_atomics && ctx.profile.support_explicit_workgroup_layout) { |
| 135 | const Id shift_id{ctx.Constant(ctx.U32[1], 3U)}; | 135 | const Id shift_id{ctx.Const(3U)}; |
| 136 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 136 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 137 | const Id pointer{ | 137 | const Id pointer{ |
| 138 | ctx.OpAccessChain(ctx.shared_u64, ctx.shared_memory_u64, ctx.u32_zero_value, index)}; | 138 | ctx.OpAccessChain(ctx.shared_u64, ctx.shared_memory_u64, ctx.u32_zero_value, index)}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp index 366dc6a0c..705aebd81 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp | |||
| @@ -12,8 +12,7 @@ void MemoryBarrier(EmitContext& ctx, spv::Scope scope) { | |||
| 12 | spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory | | 12 | spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory | |
| 13 | spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory | | 13 | spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory | |
| 14 | spv::MemorySemanticsMask::ImageMemory}; | 14 | spv::MemorySemanticsMask::ImageMemory}; |
| 15 | ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)), | 15 | ctx.OpMemoryBarrier(ctx.Const(static_cast<u32>(scope)), ctx.Const(static_cast<u32>(semantics))); |
| 16 | ctx.Constant(ctx.U32[1], static_cast<u32>(semantics))); | ||
| 17 | } | 16 | } |
| 18 | } // Anonymous namespace | 17 | } // Anonymous namespace |
| 19 | 18 | ||
| @@ -22,9 +21,9 @@ void EmitBarrier(EmitContext& ctx) { | |||
| 22 | const auto memory{spv::Scope::Workgroup}; | 21 | const auto memory{spv::Scope::Workgroup}; |
| 23 | const auto memory_semantics{spv::MemorySemanticsMask::AcquireRelease | | 22 | const auto memory_semantics{spv::MemorySemanticsMask::AcquireRelease | |
| 24 | spv::MemorySemanticsMask::WorkgroupMemory}; | 23 | spv::MemorySemanticsMask::WorkgroupMemory}; |
| 25 | ctx.OpControlBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(execution)), | 24 | ctx.OpControlBarrier(ctx.Const(static_cast<u32>(execution)), |
| 26 | ctx.Constant(ctx.U32[1], static_cast<u32>(memory)), | 25 | ctx.Const(static_cast<u32>(memory)), |
| 27 | ctx.Constant(ctx.U32[1], static_cast<u32>(memory_semantics))); | 26 | ctx.Const(static_cast<u32>(memory_semantics))); |
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | void EmitWorkgroupMemoryBarrier(EmitContext& ctx) { | 29 | void EmitWorkgroupMemoryBarrier(EmitContext& ctx) { |
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 ed57e44a2..5cc9d0d39 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 | |||
| @@ -69,7 +69,7 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { | |||
| 69 | return info.id; | 69 | return info.id; |
| 70 | } else { | 70 | } else { |
| 71 | const u32 index_element{element - info.first_element}; | 71 | const u32 index_element{element - info.first_element}; |
| 72 | const Id index_id{ctx.Constant(ctx.U32[1], index_element)}; | 72 | const Id index_id{ctx.Const(index_element)}; |
| 73 | return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id); | 73 | return OutputAccessChain(ctx, ctx.output_f32, info.id, index_id); |
| 74 | } | 74 | } |
| 75 | } | 75 | } |
| @@ -81,7 +81,7 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { | |||
| 81 | case IR::Attribute::PositionZ: | 81 | case IR::Attribute::PositionZ: |
| 82 | case IR::Attribute::PositionW: { | 82 | case IR::Attribute::PositionW: { |
| 83 | const u32 element{static_cast<u32>(attr) % 4}; | 83 | const u32 element{static_cast<u32>(attr) % 4}; |
| 84 | const Id element_id{ctx.Constant(ctx.U32[1], element)}; | 84 | const Id element_id{ctx.Const(element)}; |
| 85 | return OutputAccessChain(ctx, ctx.output_f32, ctx.output_position, element_id); | 85 | return OutputAccessChain(ctx, ctx.output_f32, ctx.output_position, element_id); |
| 86 | } | 86 | } |
| 87 | case IR::Attribute::ClipDistance0: | 87 | case IR::Attribute::ClipDistance0: |
| @@ -94,7 +94,7 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { | |||
| 94 | case IR::Attribute::ClipDistance7: { | 94 | case IR::Attribute::ClipDistance7: { |
| 95 | const u32 base{static_cast<u32>(IR::Attribute::ClipDistance0)}; | 95 | const u32 base{static_cast<u32>(IR::Attribute::ClipDistance0)}; |
| 96 | const u32 index{static_cast<u32>(attr) - base}; | 96 | const u32 index{static_cast<u32>(attr) - base}; |
| 97 | const Id clip_num{ctx.Constant(ctx.U32[1], index)}; | 97 | const Id clip_num{ctx.Const(index)}; |
| 98 | return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num); | 98 | return OutputAccessChain(ctx, ctx.output_f32, ctx.clip_distances, clip_num); |
| 99 | } | 99 | } |
| 100 | case IR::Attribute::Layer: | 100 | case IR::Attribute::Layer: |
| @@ -131,7 +131,7 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, | |||
| 131 | Id index{ctx.Def(offset)}; | 131 | Id index{ctx.Def(offset)}; |
| 132 | if (element_size > 1) { | 132 | if (element_size > 1) { |
| 133 | const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; | 133 | const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))}; |
| 134 | const Id shift{ctx.Constant(ctx.U32[1], log2_element_size)}; | 134 | const Id shift{ctx.Const(log2_element_size)}; |
| 135 | index = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift); | 135 | index = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift); |
| 136 | } | 136 | } |
| 137 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, index)}; | 137 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, index)}; |
| @@ -140,7 +140,7 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, | |||
| 140 | if (offset.U32() % element_size != 0) { | 140 | if (offset.U32() % element_size != 0) { |
| 141 | throw NotImplementedException("Unaligned immediate constant buffer load"); | 141 | throw NotImplementedException("Unaligned immediate constant buffer load"); |
| 142 | } | 142 | } |
| 143 | const Id imm_offset{ctx.Constant(ctx.U32[1], offset.U32() / element_size)}; | 143 | const Id imm_offset{ctx.Const(offset.U32() / element_size)}; |
| 144 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, imm_offset)}; | 144 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, imm_offset)}; |
| 145 | return ctx.OpLoad(result_type, access_chain); | 145 | return ctx.OpLoad(result_type, access_chain); |
| 146 | } | 146 | } |
| @@ -212,13 +212,13 @@ Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& | |||
| 212 | 212 | ||
| 213 | Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { | 213 | Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { |
| 214 | const u32 element{static_cast<u32>(attr) % 4}; | 214 | const u32 element{static_cast<u32>(attr) % 4}; |
| 215 | const auto element_id{[&] { return ctx.Constant(ctx.U32[1], element); }}; | 215 | const auto element_id{[&] { return ctx.Const(element); }}; |
| 216 | if (IR::IsGeneric(attr)) { | 216 | if (IR::IsGeneric(attr)) { |
| 217 | const u32 index{IR::GenericAttributeIndex(attr)}; | 217 | const u32 index{IR::GenericAttributeIndex(attr)}; |
| 218 | const std::optional<AttrInfo> type{AttrTypes(ctx, index)}; | 218 | const std::optional<AttrInfo> type{AttrTypes(ctx, index)}; |
| 219 | if (!type) { | 219 | if (!type) { |
| 220 | // Attribute is disabled | 220 | // Attribute is disabled |
| 221 | return ctx.Constant(ctx.F32[1], 0.0f); | 221 | return ctx.Const(0.0f); |
| 222 | } | 222 | } |
| 223 | const Id generic_id{ctx.input_generics.at(index)}; | 223 | const Id generic_id{ctx.input_generics.at(index)}; |
| 224 | const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, element_id())}; | 224 | const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, element_id())}; |
| @@ -252,20 +252,19 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { | |||
| 252 | } | 252 | } |
| 253 | case IR::Attribute::FrontFace: | 253 | case IR::Attribute::FrontFace: |
| 254 | return ctx.OpSelect(ctx.U32[1], ctx.OpLoad(ctx.U1, ctx.front_face), | 254 | return ctx.OpSelect(ctx.U32[1], ctx.OpLoad(ctx.U1, ctx.front_face), |
| 255 | ctx.Constant(ctx.U32[1], std::numeric_limits<u32>::max()), | 255 | ctx.Const(std::numeric_limits<u32>::max()), ctx.u32_zero_value); |
| 256 | ctx.u32_zero_value); | ||
| 257 | case IR::Attribute::PointSpriteS: | 256 | case IR::Attribute::PointSpriteS: |
| 258 | return ctx.OpLoad(ctx.F32[1], | 257 | return ctx.OpLoad(ctx.F32[1], |
| 259 | ctx.OpAccessChain(ctx.input_f32, ctx.point_coord, ctx.u32_zero_value)); | 258 | ctx.OpAccessChain(ctx.input_f32, ctx.point_coord, ctx.u32_zero_value)); |
| 260 | case IR::Attribute::PointSpriteT: | 259 | case IR::Attribute::PointSpriteT: |
| 261 | return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.point_coord, | 260 | return ctx.OpLoad(ctx.F32[1], |
| 262 | ctx.Constant(ctx.U32[1], 1U))); | 261 | ctx.OpAccessChain(ctx.input_f32, ctx.point_coord, ctx.Const(1U))); |
| 263 | case IR::Attribute::TessellationEvaluationPointU: | 262 | case IR::Attribute::TessellationEvaluationPointU: |
| 264 | return ctx.OpLoad(ctx.F32[1], | 263 | return ctx.OpLoad(ctx.F32[1], |
| 265 | ctx.OpAccessChain(ctx.input_f32, ctx.tess_coord, ctx.u32_zero_value)); | 264 | ctx.OpAccessChain(ctx.input_f32, ctx.tess_coord, ctx.u32_zero_value)); |
| 266 | case IR::Attribute::TessellationEvaluationPointV: | 265 | case IR::Attribute::TessellationEvaluationPointV: |
| 267 | return ctx.OpLoad(ctx.F32[1], ctx.OpAccessChain(ctx.input_f32, ctx.tess_coord, | 266 | return ctx.OpLoad(ctx.F32[1], |
| 268 | ctx.Constant(ctx.U32[1], 1U))); | 267 | ctx.OpAccessChain(ctx.input_f32, ctx.tess_coord, ctx.Const(1U))); |
| 269 | 268 | ||
| 270 | default: | 269 | default: |
| 271 | throw NotImplementedException("Read attribute {}", attr); | 270 | throw NotImplementedException("Read attribute {}", attr); |
| @@ -303,7 +302,7 @@ Id EmitGetPatch(EmitContext& ctx, IR::Patch patch) { | |||
| 303 | throw NotImplementedException("Non-generic patch load"); | 302 | throw NotImplementedException("Non-generic patch load"); |
| 304 | } | 303 | } |
| 305 | const u32 index{IR::GenericPatchIndex(patch)}; | 304 | const u32 index{IR::GenericPatchIndex(patch)}; |
| 306 | const Id element{ctx.Constant(ctx.U32[1], IR::GenericPatchElement(patch))}; | 305 | const Id element{ctx.Const(IR::GenericPatchElement(patch))}; |
| 307 | const Id pointer{ctx.OpAccessChain(ctx.input_f32, ctx.patches.at(index), element)}; | 306 | const Id pointer{ctx.OpAccessChain(ctx.input_f32, ctx.patches.at(index), element)}; |
| 308 | return ctx.OpLoad(ctx.F32[1], pointer); | 307 | return ctx.OpLoad(ctx.F32[1], pointer); |
| 309 | } | 308 | } |
| @@ -312,7 +311,7 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) { | |||
| 312 | const Id pointer{[&] { | 311 | const Id pointer{[&] { |
| 313 | if (IR::IsGeneric(patch)) { | 312 | if (IR::IsGeneric(patch)) { |
| 314 | const u32 index{IR::GenericPatchIndex(patch)}; | 313 | const u32 index{IR::GenericPatchIndex(patch)}; |
| 315 | const Id element{ctx.Constant(ctx.U32[1], IR::GenericPatchElement(patch))}; | 314 | const Id element{ctx.Const(IR::GenericPatchElement(patch))}; |
| 316 | return ctx.OpAccessChain(ctx.output_f32, ctx.patches.at(index), element); | 315 | return ctx.OpAccessChain(ctx.output_f32, ctx.patches.at(index), element); |
| 317 | } | 316 | } |
| 318 | switch (patch) { | 317 | switch (patch) { |
| @@ -321,15 +320,14 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) { | |||
| 321 | case IR::Patch::TessellationLodTop: | 320 | case IR::Patch::TessellationLodTop: |
| 322 | case IR::Patch::TessellationLodBottom: { | 321 | case IR::Patch::TessellationLodBottom: { |
| 323 | const u32 index{static_cast<u32>(patch) - u32(IR::Patch::TessellationLodLeft)}; | 322 | const u32 index{static_cast<u32>(patch) - u32(IR::Patch::TessellationLodLeft)}; |
| 324 | const Id index_id{ctx.Constant(ctx.U32[1], index)}; | 323 | const Id index_id{ctx.Const(index)}; |
| 325 | return ctx.OpAccessChain(ctx.output_f32, ctx.output_tess_level_outer, index_id); | 324 | return ctx.OpAccessChain(ctx.output_f32, ctx.output_tess_level_outer, index_id); |
| 326 | } | 325 | } |
| 327 | case IR::Patch::TessellationLodInteriorU: | 326 | case IR::Patch::TessellationLodInteriorU: |
| 328 | return ctx.OpAccessChain(ctx.output_f32, ctx.output_tess_level_inner, | 327 | return ctx.OpAccessChain(ctx.output_f32, ctx.output_tess_level_inner, |
| 329 | ctx.u32_zero_value); | 328 | ctx.u32_zero_value); |
| 330 | case IR::Patch::TessellationLodInteriorV: | 329 | case IR::Patch::TessellationLodInteriorV: |
| 331 | return ctx.OpAccessChain(ctx.output_f32, ctx.output_tess_level_inner, | 330 | return ctx.OpAccessChain(ctx.output_f32, ctx.output_tess_level_inner, ctx.Const(1u)); |
| 332 | ctx.Constant(ctx.U32[1], 1u)); | ||
| 333 | default: | 331 | default: |
| 334 | throw NotImplementedException("Patch {}", patch); | 332 | throw NotImplementedException("Patch {}", patch); |
| 335 | } | 333 | } |
| @@ -338,7 +336,7 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) { | |||
| 338 | } | 336 | } |
| 339 | 337 | ||
| 340 | void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value) { | 338 | void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value) { |
| 341 | const Id component_id{ctx.Constant(ctx.U32[1], component)}; | 339 | const Id component_id{ctx.Const(component)}; |
| 342 | const Id pointer{ctx.OpAccessChain(ctx.output_f32, ctx.frag_color.at(index), component_id)}; | 340 | const Id pointer{ctx.OpAccessChain(ctx.output_f32, ctx.frag_color.at(index), component_id)}; |
| 343 | ctx.OpStore(pointer, value); | 341 | ctx.OpStore(pointer, value); |
| 344 | } | 342 | } |
| @@ -404,7 +402,7 @@ Id EmitIsHelperInvocation(EmitContext& ctx) { | |||
| 404 | } | 402 | } |
| 405 | 403 | ||
| 406 | Id EmitYDirection(EmitContext& ctx) { | 404 | Id EmitYDirection(EmitContext& ctx) { |
| 407 | return ctx.Constant(ctx.F32[1], ctx.profile.y_negate ? -1.0f : 1.0f); | 405 | return ctx.Const(ctx.profile.y_negate ? -1.0f : 1.0f); |
| 408 | } | 406 | } |
| 409 | 407 | ||
| 410 | Id EmitLoadLocal(EmitContext& ctx, Id word_offset) { | 408 | Id EmitLoadLocal(EmitContext& ctx, Id word_offset) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp index 24300af39..97d11cc63 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp | |||
| @@ -117,7 +117,7 @@ Id EmitFPLog2(EmitContext& ctx, Id value) { | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | Id EmitFPRecip32(EmitContext& ctx, Id value) { | 119 | Id EmitFPRecip32(EmitContext& ctx, Id value) { |
| 120 | return ctx.OpFDiv(ctx.F32[1], ctx.Constant(ctx.F32[1], 1.0f), value); | 120 | return ctx.OpFDiv(ctx.F32[1], ctx.Const(1.0f), value); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | Id EmitFPRecip64(EmitContext& ctx, Id value) { | 123 | Id EmitFPRecip64(EmitContext& ctx, Id value) { |
| @@ -143,8 +143,8 @@ Id EmitFPSaturate16(EmitContext& ctx, Id value) { | |||
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | Id EmitFPSaturate32(EmitContext& ctx, Id value) { | 145 | Id EmitFPSaturate32(EmitContext& ctx, Id value) { |
| 146 | const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})}; | 146 | const Id zero{ctx.Const(f32{0.0})}; |
| 147 | const Id one{ctx.Constant(ctx.F32[1], f32{1.0})}; | 147 | const Id one{ctx.Const(f32{1.0})}; |
| 148 | return Clamp(ctx, ctx.F32[1], value, zero, one); | 148 | return Clamp(ctx, ctx.F32[1], value, zero, one); |
| 149 | } | 149 | } |
| 150 | 150 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 7a4388e7e..90817f161 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | |||
| @@ -45,16 +45,12 @@ public: | |||
| 45 | if (opcode != values[1]->GetOpcode() || opcode != IR::Opcode::CompositeConstructU32x4) { | 45 | if (opcode != values[1]->GetOpcode() || opcode != IR::Opcode::CompositeConstructU32x4) { |
| 46 | throw LogicError("Invalid PTP arguments"); | 46 | throw LogicError("Invalid PTP arguments"); |
| 47 | } | 47 | } |
| 48 | auto read{[&](unsigned int a, unsigned int b) { | 48 | auto read{[&](unsigned int a, unsigned int b) { return values[a]->Arg(b).U32(); }}; |
| 49 | return ctx.Constant(ctx.U32[1], values[a]->Arg(b).U32()); | 49 | |
| 50 | }}; | 50 | const Id offsets{ctx.ConstantComposite( |
| 51 | 51 | ctx.TypeArray(ctx.U32[2], ctx.Const(4U)), ctx.Const(read(0, 0), read(0, 1)), | |
| 52 | const Id offsets{ | 52 | ctx.Const(read(0, 2), read(0, 3)), ctx.Const(read(1, 0), read(1, 1)), |
| 53 | ctx.ConstantComposite(ctx.TypeArray(ctx.U32[2], ctx.Constant(ctx.U32[1], 4)), | 53 | ctx.Const(read(1, 2), read(1, 3)))}; |
| 54 | ctx.ConstantComposite(ctx.U32[2], read(0, 0), read(0, 1)), | ||
| 55 | ctx.ConstantComposite(ctx.U32[2], read(0, 2), read(0, 3)), | ||
| 56 | ctx.ConstantComposite(ctx.U32[2], read(1, 0), read(1, 1)), | ||
| 57 | ctx.ConstantComposite(ctx.U32[2], read(1, 2), read(1, 3)))}; | ||
| 58 | Add(spv::ImageOperandsMask::ConstOffsets, offsets); | 54 | Add(spv::ImageOperandsMask::ConstOffsets, offsets); |
| 59 | } | 55 | } |
| 60 | 56 | ||
| @@ -108,7 +104,7 @@ private: | |||
| 108 | return; | 104 | return; |
| 109 | } | 105 | } |
| 110 | if (offset.IsImmediate()) { | 106 | if (offset.IsImmediate()) { |
| 111 | Add(spv::ImageOperandsMask::ConstOffset, ctx.Constant(ctx.U32[1], offset.U32())); | 107 | Add(spv::ImageOperandsMask::ConstOffset, ctx.Const(offset.U32())); |
| 112 | return; | 108 | return; |
| 113 | } | 109 | } |
| 114 | IR::Inst* const inst{offset.InstRecursive()}; | 110 | IR::Inst* const inst{offset.InstRecursive()}; |
| @@ -361,9 +357,8 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id | |||
| 361 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 357 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 362 | const ImageOperands operands(ctx, offset, offset2); | 358 | const ImageOperands operands(ctx, offset, offset2); |
| 363 | return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, | 359 | return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, |
| 364 | ctx.F32[4], Texture(ctx, index), coords, | 360 | ctx.F32[4], Texture(ctx, index), coords, ctx.Const(info.gather_component), |
| 365 | ctx.Constant(ctx.U32[1], info.gather_component.Value()), operands.Mask(), | 361 | operands.Mask(), operands.Span()); |
| 366 | operands.Span()); | ||
| 367 | } | 362 | } |
| 368 | 363 | ||
| 369 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 364 | Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index 944f1e429..c12d0a513 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp | |||
| @@ -44,7 +44,7 @@ Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | |||
| 44 | // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c | 44 | // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c |
| 45 | constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())}; | 45 | constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())}; |
| 46 | const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)}; | 46 | const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)}; |
| 47 | const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Constant(ctx.U32[1], s32_max), a)}; | 47 | const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Const(s32_max), a)}; |
| 48 | 48 | ||
| 49 | const Id positive_test{ctx.OpSGreaterThan(ctx.U1, b, sub_a)}; | 49 | const Id positive_test{ctx.OpSGreaterThan(ctx.U1, b, sub_a)}; |
| 50 | const Id negative_test{ctx.OpSLessThan(ctx.U1, b, sub_a)}; | 50 | const Id negative_test{ctx.OpSLessThan(ctx.U1, b, sub_a)}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp index a8f2ea5a0..7bf828995 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp | |||
| @@ -11,14 +11,14 @@ namespace { | |||
| 11 | Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size) { | 11 | Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element_size) { |
| 12 | if (offset.IsImmediate()) { | 12 | if (offset.IsImmediate()) { |
| 13 | const u32 imm_offset{static_cast<u32>(offset.U32() / element_size)}; | 13 | const u32 imm_offset{static_cast<u32>(offset.U32() / element_size)}; |
| 14 | return ctx.Constant(ctx.U32[1], imm_offset); | 14 | return ctx.Const(imm_offset); |
| 15 | } | 15 | } |
| 16 | const u32 shift{static_cast<u32>(std::countr_zero(element_size))}; | 16 | const u32 shift{static_cast<u32>(std::countr_zero(element_size))}; |
| 17 | const Id index{ctx.Def(offset)}; | 17 | const Id index{ctx.Def(offset)}; |
| 18 | if (shift == 0) { | 18 | if (shift == 0) { |
| 19 | return index; | 19 | return index; |
| 20 | } | 20 | } |
| 21 | const Id shift_id{ctx.Constant(ctx.U32[1], shift)}; | 21 | const Id shift_id{ctx.Const(shift)}; |
| 22 | return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); | 22 | return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); |
| 23 | } | 23 | } |
| 24 | 24 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp index fa2fc9ab4..710d1cd25 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp | |||
| @@ -7,22 +7,22 @@ | |||
| 7 | namespace Shader::Backend::SPIRV { | 7 | namespace Shader::Backend::SPIRV { |
| 8 | namespace { | 8 | namespace { |
| 9 | Id Pointer(EmitContext& ctx, Id pointer_type, Id array, Id offset, u32 shift) { | 9 | Id Pointer(EmitContext& ctx, Id pointer_type, Id array, Id offset, u32 shift) { |
| 10 | const Id shift_id{ctx.Constant(ctx.U32[1], shift)}; | 10 | const Id shift_id{ctx.Const(shift)}; |
| 11 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 11 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 12 | return ctx.OpAccessChain(pointer_type, array, ctx.u32_zero_value, index); | 12 | return ctx.OpAccessChain(pointer_type, array, ctx.u32_zero_value, index); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | Id Word(EmitContext& ctx, Id offset) { | 15 | Id Word(EmitContext& ctx, Id offset) { |
| 16 | const Id shift_id{ctx.Constant(ctx.U32[1], 2U)}; | 16 | const Id shift_id{ctx.Const(2U)}; |
| 17 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 17 | const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 18 | const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; | 18 | const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; |
| 19 | return ctx.OpLoad(ctx.U32[1], pointer); | 19 | return ctx.OpLoad(ctx.U32[1], pointer); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | std::pair<Id, Id> ExtractArgs(EmitContext& ctx, Id offset, u32 mask, u32 count) { | 22 | std::pair<Id, Id> ExtractArgs(EmitContext& ctx, Id offset, u32 mask, u32 count) { |
| 23 | const Id shift{ctx.OpShiftLeftLogical(ctx.U32[1], offset, ctx.Constant(ctx.U32[1], 3U))}; | 23 | const Id shift{ctx.OpShiftLeftLogical(ctx.U32[1], offset, ctx.Const(3U))}; |
| 24 | const Id bit{ctx.OpBitwiseAnd(ctx.U32[1], shift, ctx.Constant(ctx.U32[1], mask))}; | 24 | const Id bit{ctx.OpBitwiseAnd(ctx.U32[1], shift, ctx.Const(mask))}; |
| 25 | const Id count_id{ctx.Constant(ctx.U32[1], count)}; | 25 | const Id count_id{ctx.Const(count)}; |
| 26 | return {bit, count_id}; | 26 | return {bit, count_id}; |
| 27 | } | 27 | } |
| 28 | } // Anonymous namespace | 28 | } // Anonymous namespace |
| @@ -83,9 +83,9 @@ Id EmitLoadSharedU64(EmitContext& ctx, Id offset) { | |||
| 83 | const Id pointer{Pointer(ctx, ctx.shared_u32x2, ctx.shared_memory_u32x2, offset, 3)}; | 83 | const Id pointer{Pointer(ctx, ctx.shared_u32x2, ctx.shared_memory_u32x2, offset, 3)}; |
| 84 | return ctx.OpLoad(ctx.U32[2], pointer); | 84 | return ctx.OpLoad(ctx.U32[2], pointer); |
| 85 | } else { | 85 | } else { |
| 86 | const Id shift_id{ctx.Constant(ctx.U32[1], 2U)}; | 86 | const Id shift_id{ctx.Const(2U)}; |
| 87 | const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 87 | const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 88 | const Id next_index{ctx.OpIAdd(ctx.U32[1], base_index, ctx.Constant(ctx.U32[1], 1U))}; | 88 | const Id next_index{ctx.OpIAdd(ctx.U32[1], base_index, ctx.Const(1U))}; |
| 89 | const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, base_index)}; | 89 | const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, base_index)}; |
| 90 | const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_index)}; | 90 | const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_index)}; |
| 91 | return ctx.OpCompositeConstruct(ctx.U32[2], ctx.OpLoad(ctx.U32[1], lhs_pointer), | 91 | return ctx.OpCompositeConstruct(ctx.U32[2], ctx.OpLoad(ctx.U32[1], lhs_pointer), |
| @@ -98,12 +98,11 @@ Id EmitLoadSharedU128(EmitContext& ctx, Id offset) { | |||
| 98 | const Id pointer{Pointer(ctx, ctx.shared_u32x4, ctx.shared_memory_u32x4, offset, 4)}; | 98 | const Id pointer{Pointer(ctx, ctx.shared_u32x4, ctx.shared_memory_u32x4, offset, 4)}; |
| 99 | return ctx.OpLoad(ctx.U32[4], pointer); | 99 | return ctx.OpLoad(ctx.U32[4], pointer); |
| 100 | } | 100 | } |
| 101 | const Id shift_id{ctx.Constant(ctx.U32[1], 2U)}; | 101 | const Id shift_id{ctx.Const(2U)}; |
| 102 | const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; | 102 | const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; |
| 103 | std::array<Id, 4> values{}; | 103 | std::array<Id, 4> values{}; |
| 104 | for (u32 i = 0; i < 4; ++i) { | 104 | for (u32 i = 0; i < 4; ++i) { |
| 105 | const Id index{i == 0 ? base_index | 105 | const Id index{i == 0 ? base_index : ctx.OpIAdd(ctx.U32[1], base_index, ctx.Const(i))}; |
| 106 | : ctx.OpIAdd(ctx.U32[1], base_index, ctx.Constant(ctx.U32[1], i))}; | ||
| 107 | const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; | 106 | const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; |
| 108 | values[i] = ctx.OpLoad(ctx.U32[1], pointer); | 107 | values[i] = ctx.OpLoad(ctx.U32[1], pointer); |
| 109 | } | 108 | } |
| @@ -134,7 +133,7 @@ void EmitWriteSharedU32(EmitContext& ctx, Id offset, Id value) { | |||
| 134 | if (ctx.profile.support_explicit_workgroup_layout) { | 133 | if (ctx.profile.support_explicit_workgroup_layout) { |
| 135 | pointer = Pointer(ctx, ctx.shared_u32, ctx.shared_memory_u32, offset, 2); | 134 | pointer = Pointer(ctx, ctx.shared_u32, ctx.shared_memory_u32, offset, 2); |
| 136 | } else { | 135 | } else { |
| 137 | const Id shift{ctx.Constant(ctx.U32[1], 2U)}; | 136 | const Id shift{ctx.Const(2U)}; |
| 138 | const Id word_offset{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; | 137 | const Id word_offset{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; |
| 139 | pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset); | 138 | pointer = ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset); |
| 140 | } | 139 | } |
| @@ -147,9 +146,9 @@ void EmitWriteSharedU64(EmitContext& ctx, Id offset, Id value) { | |||
| 147 | ctx.OpStore(pointer, value); | 146 | ctx.OpStore(pointer, value); |
| 148 | return; | 147 | return; |
| 149 | } | 148 | } |
| 150 | const Id shift{ctx.Constant(ctx.U32[1], 2U)}; | 149 | const Id shift{ctx.Const(2U)}; |
| 151 | const Id word_offset{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; | 150 | const Id word_offset{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; |
| 152 | const Id next_offset{ctx.OpIAdd(ctx.U32[1], word_offset, ctx.Constant(ctx.U32[1], 1U))}; | 151 | const Id next_offset{ctx.OpIAdd(ctx.U32[1], word_offset, ctx.Const(1U))}; |
| 153 | const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset)}; | 152 | const Id lhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, word_offset)}; |
| 154 | const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_offset)}; | 153 | const Id rhs_pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, next_offset)}; |
| 155 | ctx.OpStore(lhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 0U)); | 154 | ctx.OpStore(lhs_pointer, ctx.OpCompositeExtract(ctx.U32[1], value, 0U)); |
| @@ -162,11 +161,10 @@ void EmitWriteSharedU128(EmitContext& ctx, Id offset, Id value) { | |||
| 162 | ctx.OpStore(pointer, value); | 161 | ctx.OpStore(pointer, value); |
| 163 | return; | 162 | return; |
| 164 | } | 163 | } |
| 165 | const Id shift{ctx.Constant(ctx.U32[1], 2U)}; | 164 | const Id shift{ctx.Const(2U)}; |
| 166 | const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; | 165 | const Id base_index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift)}; |
| 167 | for (u32 i = 0; i < 4; ++i) { | 166 | for (u32 i = 0; i < 4; ++i) { |
| 168 | const Id index{i == 0 ? base_index | 167 | const Id index{i == 0 ? base_index : ctx.OpIAdd(ctx.U32[1], base_index, ctx.Const(i))}; |
| 169 | : ctx.OpIAdd(ctx.U32[1], base_index, ctx.Constant(ctx.U32[1], i))}; | ||
| 170 | const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; | 168 | const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; |
| 171 | ctx.OpStore(pointer, ctx.OpCompositeExtract(ctx.U32[1], value, i)); | 169 | ctx.OpStore(pointer, ctx.OpCompositeExtract(ctx.U32[1], value, i)); |
| 172 | } | 170 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index ae8b39f41..d5430e905 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | |||
| @@ -19,7 +19,7 @@ void ConvertDepthMode(EmitContext& ctx) { | |||
| 19 | void SetFixedPipelinePointSize(EmitContext& ctx) { | 19 | void SetFixedPipelinePointSize(EmitContext& ctx) { |
| 20 | if (ctx.profile.fixed_state_point_size) { | 20 | if (ctx.profile.fixed_state_point_size) { |
| 21 | const float point_size{*ctx.profile.fixed_state_point_size}; | 21 | const float point_size{*ctx.profile.fixed_state_point_size}; |
| 22 | ctx.OpStore(ctx.output_point_size, ctx.Constant(ctx.F32[1], point_size)); | 22 | ctx.OpStore(ctx.output_point_size, ctx.Const(point_size)); |
| 23 | } | 23 | } |
| 24 | } | 24 | } |
| 25 | 25 | ||
| @@ -75,7 +75,7 @@ void AlphaTest(EmitContext& ctx) { | |||
| 75 | 75 | ||
| 76 | const Id true_label{ctx.OpLabel()}; | 76 | const Id true_label{ctx.OpLabel()}; |
| 77 | const Id discard_label{ctx.OpLabel()}; | 77 | const Id discard_label{ctx.OpLabel()}; |
| 78 | const Id alpha_reference{ctx.Constant(ctx.F32[1], ctx.profile.alpha_test_reference)}; | 78 | const Id alpha_reference{ctx.Const(ctx.profile.alpha_test_reference)}; |
| 79 | const Id condition{ComparisonFunction(ctx, comparison, alpha, alpha_reference)}; | 79 | const Id condition{ComparisonFunction(ctx, comparison, alpha, alpha_reference)}; |
| 80 | 80 | ||
| 81 | ctx.OpSelectionMerge(true_label, spv::SelectionControlMask::MaskNone); | 81 | ctx.OpSelectionMerge(true_label, spv::SelectionControlMask::MaskNone); |
| @@ -88,8 +88,8 @@ void AlphaTest(EmitContext& ctx) { | |||
| 88 | 88 | ||
| 89 | void EmitPrologue(EmitContext& ctx) { | 89 | void EmitPrologue(EmitContext& ctx) { |
| 90 | if (ctx.stage == Stage::VertexB) { | 90 | if (ctx.stage == Stage::VertexB) { |
| 91 | const Id zero{ctx.Constant(ctx.F32[1], 0.0f)}; | 91 | const Id zero{ctx.Const(0.0f)}; |
| 92 | const Id one{ctx.Constant(ctx.F32[1], 1.0f)}; | 92 | const Id one{ctx.Const(1.0f)}; |
| 93 | const Id default_vector{ctx.ConstantComposite(ctx.F32[4], zero, zero, zero, one)}; | 93 | const Id default_vector{ctx.ConstantComposite(ctx.F32[4], zero, zero, zero, one)}; |
| 94 | ctx.OpStore(ctx.output_position, default_vector); | 94 | ctx.OpStore(ctx.output_position, default_vector); |
| 95 | for (const auto& info : ctx.output_generics) { | 95 | for (const auto& info : ctx.output_generics) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index a255f9ba7..239e2ecab 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp | |||
| @@ -54,7 +54,7 @@ Id EmitLaneId(EmitContext& ctx) { | |||
| 54 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { | 54 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
| 55 | return id; | 55 | return id; |
| 56 | } | 56 | } |
| 57 | return ctx.OpBitwiseAnd(ctx.U32[1], id, ctx.Constant(ctx.U32[1], 31U)); | 57 | return ctx.OpBitwiseAnd(ctx.U32[1], id, ctx.Const(31U)); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | Id EmitVoteAll(EmitContext& ctx, Id pred) { | 60 | Id EmitVoteAll(EmitContext& ctx, Id pred) { |
| @@ -168,10 +168,10 @@ Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | Id EmitFSwizzleAdd(EmitContext& ctx, Id op_a, Id op_b, Id swizzle) { | 170 | Id EmitFSwizzleAdd(EmitContext& ctx, Id op_a, Id op_b, Id swizzle) { |
| 171 | const Id three{ctx.Constant(ctx.U32[1], 3)}; | 171 | const Id three{ctx.Const(3U)}; |
| 172 | Id mask{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; | 172 | Id mask{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; |
| 173 | mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three); | 173 | mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three); |
| 174 | mask = ctx.OpShiftLeftLogical(ctx.U32[1], mask, ctx.Constant(ctx.U32[1], 1)); | 174 | mask = ctx.OpShiftLeftLogical(ctx.U32[1], mask, ctx.Const(1U)); |
| 175 | mask = ctx.OpShiftRightLogical(ctx.U32[1], swizzle, mask); | 175 | mask = ctx.OpShiftRightLogical(ctx.U32[1], swizzle, mask); |
| 176 | mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three); | 176 | mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three); |
| 177 | 177 | ||