summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_special.cpp45
-rw-r--r--src/shader_recompiler/profile.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp36
3 files changed, 95 insertions, 1 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
41Id 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
63void 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
42void EmitPrologue(EmitContext& ctx) { 84void 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
73void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { 118void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) {
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 5ecae71b9..c26017d75 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -5,8 +5,8 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <vector>
9#include <optional> 8#include <optional>
9#include <vector>
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12 12
@@ -27,6 +27,17 @@ enum class InputTopology {
27 TrianglesAdjacency, 27 TrianglesAdjacency,
28}; 28};
29 29
30enum class CompareFunction {
31 Never,
32 Less,
33 Equal,
34 LessThanEqual,
35 Greater,
36 NotEqual,
37 GreaterThanEqual,
38 Always,
39};
40
30struct TransformFeedbackVarying { 41struct TransformFeedbackVarying {
31 u32 buffer{}; 42 u32 buffer{};
32 u32 stride{}; 43 u32 stride{};
@@ -66,6 +77,8 @@ struct Profile {
66 InputTopology input_topology{}; 77 InputTopology input_topology{};
67 78
68 std::optional<float> fixed_state_point_size; 79 std::optional<float> fixed_state_point_size;
80 std::optional<CompareFunction> alpha_test_func;
81 float alpha_test_reference{};
69 82
70 std::vector<TransformFeedbackVarying> xfb_varyings; 83 std::vector<TransformFeedbackVarying> xfb_varyings;
71}; 84};
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index de52d0f30..80f196d0e 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -492,6 +492,37 @@ private:
492 u32 read_lowest{}; 492 u32 read_lowest{};
493 u32 read_highest{}; 493 u32 read_highest{};
494}; 494};
495
496Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) {
497 switch (comparison) {
498 case Maxwell::ComparisonOp::Never:
499 case Maxwell::ComparisonOp::NeverOld:
500 return Shader::CompareFunction::Never;
501 case Maxwell::ComparisonOp::Less:
502 case Maxwell::ComparisonOp::LessOld:
503 return Shader::CompareFunction::Less;
504 case Maxwell::ComparisonOp::Equal:
505 case Maxwell::ComparisonOp::EqualOld:
506 return Shader::CompareFunction::Equal;
507 case Maxwell::ComparisonOp::LessEqual:
508 case Maxwell::ComparisonOp::LessEqualOld:
509 return Shader::CompareFunction::LessThanEqual;
510 case Maxwell::ComparisonOp::Greater:
511 case Maxwell::ComparisonOp::GreaterOld:
512 return Shader::CompareFunction::Greater;
513 case Maxwell::ComparisonOp::NotEqual:
514 case Maxwell::ComparisonOp::NotEqualOld:
515 return Shader::CompareFunction::NotEqual;
516 case Maxwell::ComparisonOp::GreaterEqual:
517 case Maxwell::ComparisonOp::GreaterEqualOld:
518 return Shader::CompareFunction::GreaterThanEqual;
519 case Maxwell::ComparisonOp::Always:
520 case Maxwell::ComparisonOp::AlwaysOld:
521 return Shader::CompareFunction::Always;
522 }
523 UNIMPLEMENTED_MSG("Unimplemented comparison op={}", comparison);
524 return {};
525}
495} // Anonymous namespace 526} // Anonymous namespace
496 527
497void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, 528void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
@@ -1016,6 +1047,11 @@ Shader::Profile PipelineCache::MakeProfile(const GraphicsPipelineCacheKey& key,
1016 } 1047 }
1017 profile.convert_depth_mode = gl_ndc; 1048 profile.convert_depth_mode = gl_ndc;
1018 break; 1049 break;
1050 case Shader::Stage::Fragment:
1051 profile.alpha_test_func = MaxwellToCompareFunction(
1052 key.state.UnpackComparisonOp(key.state.alpha_test_func.Value()));
1053 profile.alpha_test_reference = Common::BitCast<float>(key.state.alpha_test_ref);
1054 break;
1019 default: 1055 default:
1020 break; 1056 break;
1021 } 1057 }