diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index 7af29e4dd..8bb94f546 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | |||
| @@ -37,6 +37,48 @@ Id DefaultVarying(EmitContext& ctx, u32 num_components, u32 element, Id zero, Id | |||
| 37 | } | 37 | } |
| 38 | throw InvalidArgument("Bad element"); | 38 | throw InvalidArgument("Bad element"); |
| 39 | } | 39 | } |
| 40 | |||
| 41 | Id ComparisonFunction(EmitContext& ctx, CompareFunction comparison, Id operand_1, Id operand_2) { | ||
| 42 | switch (comparison) { | ||
| 43 | case CompareFunction::Never: | ||
| 44 | return ctx.false_value; | ||
| 45 | case CompareFunction::Less: | ||
| 46 | return ctx.OpFOrdLessThan(ctx.U1, operand_1, operand_2); | ||
| 47 | case CompareFunction::Equal: | ||
| 48 | return ctx.OpFOrdEqual(ctx.U1, operand_1, operand_2); | ||
| 49 | case CompareFunction::LessThanEqual: | ||
| 50 | return ctx.OpFOrdLessThanEqual(ctx.U1, operand_1, operand_2); | ||
| 51 | case CompareFunction::Greater: | ||
| 52 | return ctx.OpFOrdGreaterThan(ctx.U1, operand_1, operand_2); | ||
| 53 | case CompareFunction::NotEqual: | ||
| 54 | return ctx.OpFOrdNotEqual(ctx.U1, operand_1, operand_2); | ||
| 55 | case CompareFunction::GreaterThanEqual: | ||
| 56 | return ctx.OpFOrdGreaterThanEqual(ctx.U1, operand_1, operand_2); | ||
| 57 | case CompareFunction::Always: | ||
| 58 | return ctx.true_value; | ||
| 59 | } | ||
| 60 | throw InvalidArgument("Comparison function {}", comparison); | ||
| 61 | } | ||
| 62 | |||
| 63 | void AlphaTest(EmitContext& ctx) { | ||
| 64 | const auto comparison{*ctx.profile.alpha_test_func}; | ||
| 65 | if (comparison == CompareFunction::Always) { | ||
| 66 | return; | ||
| 67 | } | ||
| 68 | const Id type{ctx.F32[1]}; | ||
| 69 | const Id rt0_color{ctx.OpLoad(ctx.F32[4], ctx.frag_color[0])}; | ||
| 70 | const Id alpha{ctx.OpCompositeExtract(type, rt0_color, 3u)}; | ||
| 71 | |||
| 72 | const Id true_label{ctx.OpLabel()}; | ||
| 73 | const Id discard_label{ctx.OpLabel()}; | ||
| 74 | const Id alpha_reference{ctx.Constant(ctx.F32[1], ctx.profile.alpha_test_reference)}; | ||
| 75 | const Id condition{ComparisonFunction(ctx, comparison, alpha, alpha_reference)}; | ||
| 76 | |||
| 77 | ctx.OpBranchConditional(condition, true_label, discard_label); | ||
| 78 | ctx.AddLabel(discard_label); | ||
| 79 | ctx.OpKill(); | ||
| 80 | ctx.AddLabel(true_label); | ||
| 81 | } | ||
| 40 | } // Anonymous namespace | 82 | } // Anonymous namespace |
| 41 | 83 | ||
| 42 | void EmitPrologue(EmitContext& ctx) { | 84 | void EmitPrologue(EmitContext& ctx) { |
| @@ -68,6 +110,9 @@ void EmitEpilogue(EmitContext& ctx) { | |||
| 68 | if (ctx.stage == Stage::VertexB && ctx.profile.convert_depth_mode) { | 110 | if (ctx.stage == Stage::VertexB && ctx.profile.convert_depth_mode) { |
| 69 | ConvertDepthMode(ctx); | 111 | ConvertDepthMode(ctx); |
| 70 | } | 112 | } |
| 113 | if (ctx.stage == Stage::Fragment) { | ||
| 114 | AlphaTest(ctx); | ||
| 115 | } | ||
| 71 | } | 116 | } |
| 72 | 117 | ||
| 73 | void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { | 118 | void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { |