diff options
| author | 2021-07-25 11:39:04 -0700 | |
|---|---|---|
| committer | 2021-07-25 11:39:04 -0700 | |
| commit | 98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f (patch) | |
| tree | 816faa96c2c4d291825063433331a8ea4b3d08f1 /src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | |
| parent | Merge pull request #6699 from lat9nq/common-threads (diff) | |
| parent | shader: Support out of bound local memory reads and immediate writes (diff) | |
| download | yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.tar.gz yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.tar.xz yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.zip | |
Merge pull request #6585 from ameerj/hades
Shader Decompiler Rewrite
Diffstat (limited to 'src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp new file mode 100644 index 000000000..544d475b4 --- /dev/null +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | |||
| @@ -0,0 +1,150 @@ | |||
| 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 "shader_recompiler/backend/glasm/emit_context.h" | ||
| 6 | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" | ||
| 7 | #include "shader_recompiler/frontend/ir/value.h" | ||
| 8 | #include "shader_recompiler/profile.h" | ||
| 9 | |||
| 10 | namespace Shader::Backend::GLASM { | ||
| 11 | |||
| 12 | void EmitLaneId(EmitContext& ctx, IR::Inst& inst) { | ||
| 13 | ctx.Add("MOV.S {}.x,{}.threadid;", inst, ctx.stage_name); | ||
| 14 | } | ||
| 15 | |||
| 16 | void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 17 | ctx.Add("TGALL.S {}.x,{};", inst, pred); | ||
| 18 | } | ||
| 19 | |||
| 20 | void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 21 | ctx.Add("TGANY.S {}.x,{};", inst, pred); | ||
| 22 | } | ||
| 23 | |||
| 24 | void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 25 | ctx.Add("TGEQ.S {}.x,{};", inst, pred); | ||
| 26 | } | ||
| 27 | |||
| 28 | void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 29 | ctx.Add("TGBALLOT {}.x,{};", inst, pred); | ||
| 30 | } | ||
| 31 | |||
| 32 | void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 33 | ctx.Add("MOV.U {},{}.threadeqmask;", inst, ctx.stage_name); | ||
| 34 | } | ||
| 35 | |||
| 36 | void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 37 | ctx.Add("MOV.U {},{}.threadltmask;", inst, ctx.stage_name); | ||
| 38 | } | ||
| 39 | |||
| 40 | void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 41 | ctx.Add("MOV.U {},{}.threadlemask;", inst, ctx.stage_name); | ||
| 42 | } | ||
| 43 | |||
| 44 | void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 45 | ctx.Add("MOV.U {},{}.threadgtmask;", inst, ctx.stage_name); | ||
| 46 | } | ||
| 47 | |||
| 48 | void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 49 | ctx.Add("MOV.U {},{}.threadgemask;", inst, ctx.stage_name); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void Shuffle(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 53 | const IR::Value& clamp, const IR::Value& segmentation_mask, | ||
| 54 | std::string_view op) { | ||
| 55 | IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)}; | ||
| 56 | if (in_bounds) { | ||
| 57 | in_bounds->Invalidate(); | ||
| 58 | } | ||
| 59 | std::string mask; | ||
| 60 | if (clamp.IsImmediate() && segmentation_mask.IsImmediate()) { | ||
| 61 | mask = fmt::to_string(clamp.U32() | (segmentation_mask.U32() << 8)); | ||
| 62 | } else { | ||
| 63 | mask = "RC"; | ||
| 64 | ctx.Add("BFI.U RC.x,{{5,8,0,0}},{},{};", | ||
| 65 | ScalarU32{ctx.reg_alloc.Consume(segmentation_mask)}, | ||
| 66 | ScalarU32{ctx.reg_alloc.Consume(clamp)}); | ||
| 67 | } | ||
| 68 | const Register value_ret{ctx.reg_alloc.Define(inst)}; | ||
| 69 | if (in_bounds) { | ||
| 70 | const Register bounds_ret{ctx.reg_alloc.Define(*in_bounds)}; | ||
| 71 | ctx.Add("SHF{}.U {},{},{},{};" | ||
| 72 | "MOV.U {}.x,{}.y;", | ||
| 73 | op, bounds_ret, value, index, mask, value_ret, bounds_ret); | ||
| 74 | } else { | ||
| 75 | ctx.Add("SHF{}.U {},{},{},{};" | ||
| 76 | "MOV.U {}.x,{}.y;", | ||
| 77 | op, value_ret, value, index, mask, value_ret, value_ret); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 82 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 83 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "IDX"); | ||
| 84 | } | ||
| 85 | |||
| 86 | void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 87 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 88 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "UP"); | ||
| 89 | } | ||
| 90 | |||
| 91 | void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 92 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 93 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "DOWN"); | ||
| 94 | } | ||
| 95 | |||
| 96 | void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 97 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 98 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "XOR"); | ||
| 99 | } | ||
| 100 | |||
| 101 | void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, ScalarF32 op_a, ScalarF32 op_b, | ||
| 102 | ScalarU32 swizzle) { | ||
| 103 | const auto ret{ctx.reg_alloc.Define(inst)}; | ||
| 104 | ctx.Add("AND.U RC.z,{}.threadid,3;" | ||
| 105 | "SHL.U RC.z,RC.z,1;" | ||
| 106 | "SHR.U RC.z,{},RC.z;" | ||
| 107 | "AND.U RC.z,RC.z,3;" | ||
| 108 | "MUL.F RC.x,{},FSWZA[RC.z];" | ||
| 109 | "MUL.F RC.y,{},FSWZB[RC.z];" | ||
| 110 | "ADD.F {}.x,RC.x,RC.y;", | ||
| 111 | ctx.stage_name, swizzle, op_a, op_b, ret); | ||
| 112 | } | ||
| 113 | |||
| 114 | void EmitDPdxFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { | ||
| 115 | if (ctx.profile.support_derivative_control) { | ||
| 116 | ctx.Add("DDX.FINE {}.x,{};", inst, p); | ||
| 117 | } else { | ||
| 118 | LOG_WARNING(Shader_GLASM, "Fine derivatives not supported by device"); | ||
| 119 | ctx.Add("DDX {}.x,{};", inst, p); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | void EmitDPdyFine(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { | ||
| 124 | if (ctx.profile.support_derivative_control) { | ||
| 125 | ctx.Add("DDY.FINE {}.x,{};", inst, p); | ||
| 126 | } else { | ||
| 127 | LOG_WARNING(Shader_GLASM, "Fine derivatives not supported by device"); | ||
| 128 | ctx.Add("DDY {}.x,{};", inst, p); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | void EmitDPdxCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { | ||
| 133 | if (ctx.profile.support_derivative_control) { | ||
| 134 | ctx.Add("DDX.COARSE {}.x,{};", inst, p); | ||
| 135 | } else { | ||
| 136 | LOG_WARNING(Shader_GLASM, "Coarse derivatives not supported by device"); | ||
| 137 | ctx.Add("DDX {}.x,{};", inst, p); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | void EmitDPdyCoarse(EmitContext& ctx, IR::Inst& inst, ScalarF32 p) { | ||
| 142 | if (ctx.profile.support_derivative_control) { | ||
| 143 | ctx.Add("DDY.COARSE {}.x,{};", inst, p); | ||
| 144 | } else { | ||
| 145 | LOG_WARNING(Shader_GLASM, "Coarse derivatives not supported by device"); | ||
| 146 | ctx.Add("DDY {}.x,{};", inst, p); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | } // namespace Shader::Backend::GLASM | ||