diff options
| author | 2021-03-28 22:23:45 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:25 -0400 | |
| commit | 6c51f496320f698e123207c09ca61e55180a31b5 (patch) | |
| tree | c5ecbbce29797fd7ba3138e11f9c364899375e2b /src/shader_recompiler | |
| parent | shader: Implement BRX (diff) | |
| download | yuzu-6c51f496320f698e123207c09ca61e55180a31b5.tar.gz yuzu-6c51f496320f698e123207c09ca61e55180a31b5.tar.xz yuzu-6c51f496320f698e123207c09ca61e55180a31b5.zip | |
shader: Implement FSWZADD
Diffstat (limited to '')
14 files changed, 87 insertions, 4 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 44ab929b7..5ce420cbf 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -89,6 +89,7 @@ add_library(shader_recompiler STATIC | |||
| 89 | frontend/maxwell/translate/impl/floating_point_multiply.cpp | 89 | frontend/maxwell/translate/impl/floating_point_multiply.cpp |
| 90 | frontend/maxwell/translate/impl/floating_point_range_reduction.cpp | 90 | frontend/maxwell/translate/impl/floating_point_range_reduction.cpp |
| 91 | frontend/maxwell/translate/impl/floating_point_set_predicate.cpp | 91 | frontend/maxwell/translate/impl/floating_point_set_predicate.cpp |
| 92 | frontend/maxwell/translate/impl/floating_point_swizzled_add.cpp | ||
| 92 | frontend/maxwell/translate/impl/half_floating_point_add.cpp | 93 | frontend/maxwell/translate/impl/half_floating_point_add.cpp |
| 93 | frontend/maxwell/translate/impl/half_floating_point_fused_multiply_add.cpp | 94 | frontend/maxwell/translate/impl/half_floating_point_fused_multiply_add.cpp |
| 94 | frontend/maxwell/translate/impl/half_floating_point_helper.cpp | 95 | frontend/maxwell/translate/impl/half_floating_point_helper.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 96d0e9b4d..7531f8b21 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -393,6 +393,14 @@ void EmitContext::DefineInputs(const Info& info) { | |||
| 393 | subgroup_local_invocation_id = | 393 | subgroup_local_invocation_id = |
| 394 | DefineInput(*this, U32[1], spv::BuiltIn::SubgroupLocalInvocationId); | 394 | DefineInput(*this, U32[1], spv::BuiltIn::SubgroupLocalInvocationId); |
| 395 | } | 395 | } |
| 396 | if (info.uses_fswzadd) { | ||
| 397 | const Id f32_one{Constant(F32[1], 1.0f)}; | ||
| 398 | const Id f32_minus_one{Constant(F32[1], -1.0f)}; | ||
| 399 | const Id f32_zero{Constant(F32[1], 0.0f)}; | ||
| 400 | fswzadd_lut_a = ConstantComposite(F32[4], f32_minus_one, f32_one, f32_minus_one, f32_zero); | ||
| 401 | fswzadd_lut_b = | ||
| 402 | ConstantComposite(F32[4], f32_minus_one, f32_minus_one, f32_one, f32_minus_one); | ||
| 403 | } | ||
| 396 | if (info.loads_position) { | 404 | if (info.loads_position) { |
| 397 | const bool is_fragment{stage != Stage::Fragment}; | 405 | const bool is_fragment{stage != Stage::Fragment}; |
| 398 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; | 406 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 1a4e8221a..ffac39c4f 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -103,6 +103,8 @@ public: | |||
| 103 | Id vertex_index{}; | 103 | Id vertex_index{}; |
| 104 | Id base_vertex{}; | 104 | Id base_vertex{}; |
| 105 | Id front_face{}; | 105 | Id front_face{}; |
| 106 | Id fswzadd_lut_a{}; | ||
| 107 | Id fswzadd_lut_b{}; | ||
| 106 | 108 | ||
| 107 | Id local_memory{}; | 109 | Id local_memory{}; |
| 108 | 110 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 02648d769..3d0c6f7ba 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -397,5 +397,6 @@ Id EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clam | |||
| 397 | Id segmentation_mask); | 397 | Id segmentation_mask); |
| 398 | Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, | 398 | Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, |
| 399 | Id segmentation_mask); | 399 | Id segmentation_mask); |
| 400 | Id EmitFSwizzleAdd(EmitContext& ctx, Id op_a, Id op_b, Id swizzle); | ||
| 400 | 401 | ||
| 401 | } // namespace Shader::Backend::SPIRV | 402 | } // namespace Shader::Backend::SPIRV |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index 44d8a347f..cbc5b1c96 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp | |||
| @@ -132,4 +132,20 @@ Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id | |||
| 132 | return SelectValue(ctx, in_range, value, src_thread_id); | 132 | return SelectValue(ctx, in_range, value, src_thread_id); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | Id EmitFSwizzleAdd(EmitContext& ctx, Id op_a, Id op_b, Id swizzle) { | ||
| 136 | const Id three{ctx.Constant(ctx.U32[1], 3)}; | ||
| 137 | Id mask{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; | ||
| 138 | mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three); | ||
| 139 | mask = ctx.OpShiftLeftLogical(ctx.U32[1], mask, ctx.Constant(ctx.U32[1], 1)); | ||
| 140 | mask = ctx.OpShiftRightLogical(ctx.U32[1], swizzle, mask); | ||
| 141 | mask = ctx.OpBitwiseAnd(ctx.U32[1], mask, three); | ||
| 142 | |||
| 143 | const Id modifier_a{ctx.OpVectorExtractDynamic(ctx.F32[1], ctx.fswzadd_lut_a, mask)}; | ||
| 144 | const Id modifier_b{ctx.OpVectorExtractDynamic(ctx.F32[1], ctx.fswzadd_lut_b, mask)}; | ||
| 145 | |||
| 146 | const Id result_a{ctx.OpFMul(ctx.F32[1], op_a, modifier_a)}; | ||
| 147 | const Id result_b{ctx.OpFMul(ctx.F32[1], op_b, modifier_b)}; | ||
| 148 | return ctx.OpFAdd(ctx.F32[1], result_a, result_b); | ||
| 149 | } | ||
| 150 | |||
| 135 | } // namespace Shader::Backend::SPIRV | 151 | } // namespace Shader::Backend::SPIRV |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 552472487..505fba46a 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -1602,4 +1602,7 @@ U32 IREmitter::ShuffleButterfly(const IR::U32& value, const IR::U32& index, cons | |||
| 1602 | const IR::U32& seg_mask) { | 1602 | const IR::U32& seg_mask) { |
| 1603 | return Inst<U32>(Opcode::ShuffleButterfly, value, index, clamp, seg_mask); | 1603 | return Inst<U32>(Opcode::ShuffleButterfly, value, index, clamp, seg_mask); |
| 1604 | } | 1604 | } |
| 1605 | F32 IREmitter::FSwizzleAdd(const F32& a, const F32& b, const U32& swizzle, FpControl control) { | ||
| 1606 | return Inst<F32>(Opcode::FSwizzleAdd, Flags{control}, a, b, swizzle); | ||
| 1607 | } | ||
| 1605 | } // namespace Shader::IR | 1608 | } // namespace Shader::IR |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 17bc32fc8..8f3325738 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -277,6 +277,8 @@ public: | |||
| 277 | const IR::U32& seg_mask); | 277 | const IR::U32& seg_mask); |
| 278 | [[nodiscard]] U32 ShuffleButterfly(const IR::U32& value, const IR::U32& index, | 278 | [[nodiscard]] U32 ShuffleButterfly(const IR::U32& value, const IR::U32& index, |
| 279 | const IR::U32& clamp, const IR::U32& seg_mask); | 279 | const IR::U32& clamp, const IR::U32& seg_mask); |
| 280 | [[nodiscard]] F32 FSwizzleAdd(const F32& a, const F32& b, const U32& swizzle, | ||
| 281 | FpControl control = {}); | ||
| 280 | 282 | ||
| 281 | private: | 283 | private: |
| 282 | IR::Block::iterator insertion_point; | 284 | IR::Block::iterator insertion_point; |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index fb79e3d8d..717aa71ca 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -408,3 +408,4 @@ OPCODE(ShuffleIndex, U32, U32, | |||
| 408 | OPCODE(ShuffleUp, U32, U32, U32, U32, U32, ) | 408 | OPCODE(ShuffleUp, U32, U32, U32, U32, U32, ) |
| 409 | OPCODE(ShuffleDown, U32, U32, U32, U32, U32, ) | 409 | OPCODE(ShuffleDown, U32, U32, U32, U32, U32, ) |
| 410 | OPCODE(ShuffleButterfly, U32, U32, U32, U32, U32, ) | 410 | OPCODE(ShuffleButterfly, U32, U32, U32, U32, U32, ) |
| 411 | OPCODE(FSwizzleAdd, F32, F32, F32, U32, ) | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_swizzled_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_swizzled_add.cpp new file mode 100644 index 000000000..e42921a21 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_swizzled_add.cpp | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "shader_recompiler/exception.h" | ||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_encoding.h" | ||
| 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 9 | |||
| 10 | namespace Shader::Maxwell { | ||
| 11 | void TranslatorVisitor::FSWZADD(u64 insn) { | ||
| 12 | union { | ||
| 13 | u64 raw; | ||
| 14 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 15 | BitField<28, 8, u64> swizzle; | ||
| 16 | BitField<38, 1, u64> ndv; | ||
| 17 | BitField<39, 2, FpRounding> round; | ||
| 18 | BitField<44, 1, u64> ftz; | ||
| 19 | BitField<47, 1, u64> cc; | ||
| 20 | } const fswzadd{insn}; | ||
| 21 | |||
| 22 | if (fswzadd.ndv != 0) { | ||
| 23 | throw NotImplementedException("FSWZADD NDV"); | ||
| 24 | } | ||
| 25 | |||
| 26 | const IR::F32 src_a{GetFloatReg8(insn)}; | ||
| 27 | const IR::F32 src_b{GetFloatReg20(insn)}; | ||
| 28 | const IR::U32 swizzle{ir.Imm32(static_cast<u32>(fswzadd.swizzle))}; | ||
| 29 | |||
| 30 | const IR::FpControl fp_control{ | ||
| 31 | .no_contraction{false}, | ||
| 32 | .rounding{CastFpRounding(fswzadd.round)}, | ||
| 33 | .fmz_mode{fswzadd.ftz != 0 ? IR::FmzMode::FTZ : IR::FmzMode::None}, | ||
| 34 | }; | ||
| 35 | |||
| 36 | const IR::F32 result{ir.FSwizzleAdd(src_a, src_b, swizzle, fp_control)}; | ||
| 37 | F(fswzadd.dest_reg, result); | ||
| 38 | |||
| 39 | if (fswzadd.cc != 0) { | ||
| 40 | throw NotImplementedException("FSWZADD CC"); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index 9bae89c10..30b570ce4 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -91,6 +91,10 @@ IR::U32 TranslatorVisitor::GetReg39(u64 insn) { | |||
| 91 | return X(reg.index); | 91 | return X(reg.index); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | IR::F32 TranslatorVisitor::GetFloatReg8(u64 insn) { | ||
| 95 | return ir.BitCast<IR::F32>(GetReg8(insn)); | ||
| 96 | } | ||
| 97 | |||
| 94 | IR::F32 TranslatorVisitor::GetFloatReg20(u64 insn) { | 98 | IR::F32 TranslatorVisitor::GetFloatReg20(u64 insn) { |
| 95 | return ir.BitCast<IR::F32>(GetReg20(insn)); | 99 | return ir.BitCast<IR::F32>(GetReg20(insn)); |
| 96 | } | 100 | } |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index 54c31deb4..bf7d1bae8 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -353,6 +353,7 @@ public: | |||
| 353 | [[nodiscard]] IR::U32 GetReg8(u64 insn); | 353 | [[nodiscard]] IR::U32 GetReg8(u64 insn); |
| 354 | [[nodiscard]] IR::U32 GetReg20(u64 insn); | 354 | [[nodiscard]] IR::U32 GetReg20(u64 insn); |
| 355 | [[nodiscard]] IR::U32 GetReg39(u64 insn); | 355 | [[nodiscard]] IR::U32 GetReg39(u64 insn); |
| 356 | [[nodiscard]] IR::F32 GetFloatReg8(u64 insn); | ||
| 356 | [[nodiscard]] IR::F32 GetFloatReg20(u64 insn); | 357 | [[nodiscard]] IR::F32 GetFloatReg20(u64 insn); |
| 357 | [[nodiscard]] IR::F32 GetFloatReg39(u64 insn); | 358 | [[nodiscard]] IR::F32 GetFloatReg39(u64 insn); |
| 358 | [[nodiscard]] IR::F64 GetDoubleReg20(u64 insn); | 359 | [[nodiscard]] IR::F64 GetDoubleReg20(u64 insn); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index a0057a473..6a580f831 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -89,10 +89,6 @@ void TranslatorVisitor::FCHK_imm(u64) { | |||
| 89 | ThrowNotImplemented(Opcode::FCHK_imm); | 89 | ThrowNotImplemented(Opcode::FCHK_imm); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | void TranslatorVisitor::FSWZADD(u64) { | ||
| 93 | ThrowNotImplemented(Opcode::FSWZADD); | ||
| 94 | } | ||
| 95 | |||
| 96 | void TranslatorVisitor::GETCRSPTR(u64) { | 92 | void TranslatorVisitor::GETCRSPTR(u64) { |
| 97 | ThrowNotImplemented(Opcode::GETCRSPTR); | 93 | ThrowNotImplemented(Opcode::GETCRSPTR); |
| 98 | } | 94 | } |
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index c932c307b..81090335f 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -389,6 +389,9 @@ void VisitUsages(Info& info, IR::Inst& inst) { | |||
| 389 | case IR::Opcode::SubgroupBallot: | 389 | case IR::Opcode::SubgroupBallot: |
| 390 | info.uses_subgroup_vote = true; | 390 | info.uses_subgroup_vote = true; |
| 391 | break; | 391 | break; |
| 392 | case IR::Opcode::FSwizzleAdd: | ||
| 393 | info.uses_fswzadd = true; | ||
| 394 | break; | ||
| 392 | default: | 395 | default: |
| 393 | break; | 396 | break; |
| 394 | } | 397 | } |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 9111159f3..4b4006b7f 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -94,6 +94,7 @@ struct Info { | |||
| 94 | bool uses_sparse_residency{}; | 94 | bool uses_sparse_residency{}; |
| 95 | bool uses_demote_to_helper_invocation{}; | 95 | bool uses_demote_to_helper_invocation{}; |
| 96 | bool uses_subgroup_vote{}; | 96 | bool uses_subgroup_vote{}; |
| 97 | bool uses_fswzadd{}; | ||
| 97 | 98 | ||
| 98 | IR::Type used_constant_buffer_types{}; | 99 | IR::Type used_constant_buffer_types{}; |
| 99 | 100 | ||