diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | 45 | ||||
| -rw-r--r-- | src/shader_recompiler/profile.h | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 36 |
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 | |||
| 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) { |
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 | ||
| 30 | enum class CompareFunction { | ||
| 31 | Never, | ||
| 32 | Less, | ||
| 33 | Equal, | ||
| 34 | LessThanEqual, | ||
| 35 | Greater, | ||
| 36 | NotEqual, | ||
| 37 | GreaterThanEqual, | ||
| 38 | Always, | ||
| 39 | }; | ||
| 40 | |||
| 30 | struct TransformFeedbackVarying { | 41 | struct 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 | |||
| 496 | Shader::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 | ||
| 497 | void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 528 | void 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 | } |