diff options
5 files changed, 65 insertions, 3 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index da5c550ea..fffae528e 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include <boost/functional/hash.hpp> | 9 | #include <boost/functional/hash.hpp> |
| 10 | 10 | ||
| 11 | #include "common/bit_cast.h" | ||
| 11 | #include "common/cityhash.h" | 12 | #include "common/cityhash.h" |
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 14 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| @@ -60,7 +61,13 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta | |||
| 60 | rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0); | 61 | rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0); |
| 61 | topology.Assign(regs.draw.topology); | 62 | topology.Assign(regs.draw.topology); |
| 62 | 63 | ||
| 63 | std::memcpy(&point_size, ®s.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast | 64 | alpha_raw = 0; |
| 65 | const auto test_func = | ||
| 66 | regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; | ||
| 67 | alpha_test_func.Assign(PackComparisonOp(test_func)); | ||
| 68 | alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref); | ||
| 69 | |||
| 70 | point_size = Common::BitCast<u32>(regs.point_size); | ||
| 64 | 71 | ||
| 65 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 72 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
| 66 | binding_divisors[index] = | 73 | binding_divisors[index] = |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 2c18eeaae..42480e8d0 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -187,6 +187,13 @@ struct FixedPipelineState { | |||
| 187 | BitField<23, 1, u32> rasterize_enable; | 187 | BitField<23, 1, u32> rasterize_enable; |
| 188 | BitField<24, 4, Maxwell::PrimitiveTopology> topology; | 188 | BitField<24, 4, Maxwell::PrimitiveTopology> topology; |
| 189 | }; | 189 | }; |
| 190 | |||
| 191 | u32 alpha_test_ref; ///< Alpha test reference value | ||
| 192 | union { | ||
| 193 | u32 alpha_raw; | ||
| 194 | BitField<0, 3, u32> alpha_test_func; | ||
| 195 | }; | ||
| 196 | |||
| 190 | u32 point_size; | 197 | u32 point_size; |
| 191 | std::array<u32, Maxwell::NumVertexArrays> binding_divisors; | 198 | std::array<u32, Maxwell::NumVertexArrays> binding_divisors; |
| 192 | std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; | 199 | std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index dedc9c466..f9efe526d 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/bit_cast.h" | ||
| 10 | #include "common/microprofile.h" | 11 | #include "common/microprofile.h" |
| 11 | #include "core/core.h" | 12 | #include "core/core.h" |
| 12 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| @@ -344,6 +345,11 @@ VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) { | |||
| 344 | } | 345 | } |
| 345 | specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one; | 346 | specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one; |
| 346 | 347 | ||
| 348 | // Alpha test | ||
| 349 | specialization.alpha_test_func = | ||
| 350 | FixedPipelineState::UnpackComparisonOp(fixed_state.alpha_test_func.Value()); | ||
| 351 | specialization.alpha_test_ref = Common::BitCast<float>(fixed_state.alpha_test_ref); | ||
| 352 | |||
| 347 | SPIRVProgram program; | 353 | SPIRVProgram program; |
| 348 | std::vector<VkDescriptorSetLayoutBinding> bindings; | 354 | std::vector<VkDescriptorSetLayoutBinding> bindings; |
| 349 | 355 | ||
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index a20452b87..1c52f40bb 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -2075,6 +2075,45 @@ private: | |||
| 2075 | return {}; | 2075 | return {}; |
| 2076 | } | 2076 | } |
| 2077 | 2077 | ||
| 2078 | Id MaxwellToSpirvComparison(Maxwell::ComparisonOp compare_op, Id operand_1, Id operand_2) { | ||
| 2079 | using Compare = Maxwell::ComparisonOp; | ||
| 2080 | switch (compare_op) { | ||
| 2081 | case Compare::NeverOld: | ||
| 2082 | return v_false; // Never let the test pass | ||
| 2083 | case Compare::LessOld: | ||
| 2084 | return OpFOrdLessThan(t_bool, operand_1, operand_2); | ||
| 2085 | case Compare::EqualOld: | ||
| 2086 | return OpFOrdEqual(t_bool, operand_1, operand_2); | ||
| 2087 | case Compare::LessEqualOld: | ||
| 2088 | return OpFOrdLessThanEqual(t_bool, operand_1, operand_2); | ||
| 2089 | case Compare::GreaterOld: | ||
| 2090 | return OpFOrdGreaterThan(t_bool, operand_1, operand_2); | ||
| 2091 | case Compare::NotEqualOld: | ||
| 2092 | return OpFOrdNotEqual(t_bool, operand_1, operand_2); | ||
| 2093 | case Compare::GreaterEqualOld: | ||
| 2094 | return OpFOrdGreaterThanEqual(t_bool, operand_1, operand_2); | ||
| 2095 | default: | ||
| 2096 | UNREACHABLE(); | ||
| 2097 | } | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | void AlphaTest(Id pointer) { | ||
| 2101 | if (specialization.alpha_test_func == Maxwell::ComparisonOp::AlwaysOld) { | ||
| 2102 | return; | ||
| 2103 | } | ||
| 2104 | const Id true_label = OpLabel(); | ||
| 2105 | const Id discard_label = OpLabel(); | ||
| 2106 | const Id alpha_reference = Constant(t_float, specialization.alpha_test_ref); | ||
| 2107 | const Id alpha_value = OpLoad(t_float, pointer); | ||
| 2108 | const Id condition = | ||
| 2109 | MaxwellToSpirvComparison(specialization.alpha_test_func, alpha_value, alpha_reference); | ||
| 2110 | |||
| 2111 | OpBranchConditional(condition, true_label, discard_label); | ||
| 2112 | AddLabel(discard_label); | ||
| 2113 | OpKill(); | ||
| 2114 | AddLabel(true_label); | ||
| 2115 | } | ||
| 2116 | |||
| 2078 | void PreExit() { | 2117 | void PreExit() { |
| 2079 | if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) { | 2118 | if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) { |
| 2080 | const u32 position_index = out_indices.position.value(); | 2119 | const u32 position_index = out_indices.position.value(); |
| @@ -2097,8 +2136,6 @@ private: | |||
| 2097 | UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, | 2136 | UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, |
| 2098 | "Sample mask write is unimplemented"); | 2137 | "Sample mask write is unimplemented"); |
| 2099 | 2138 | ||
| 2100 | // TODO(Rodrigo): Alpha testing | ||
| 2101 | |||
| 2102 | // Write the color outputs using the data in the shader registers, disabled | 2139 | // Write the color outputs using the data in the shader registers, disabled |
| 2103 | // rendertargets/components are skipped in the register assignment. | 2140 | // rendertargets/components are skipped in the register assignment. |
| 2104 | u32 current_reg = 0; | 2141 | u32 current_reg = 0; |
| @@ -2110,6 +2147,9 @@ private: | |||
| 2110 | } | 2147 | } |
| 2111 | const Id pointer = AccessElement(t_out_float, frag_colors[rt], component); | 2148 | const Id pointer = AccessElement(t_out_float, frag_colors[rt], component); |
| 2112 | OpStore(pointer, SafeGetRegister(current_reg)); | 2149 | OpStore(pointer, SafeGetRegister(current_reg)); |
| 2150 | if (rt == 0 && component == 3) { | ||
| 2151 | AlphaTest(pointer); | ||
| 2152 | } | ||
| 2113 | ++current_reg; | 2153 | ++current_reg; |
| 2114 | } | 2154 | } |
| 2115 | } | 2155 | } |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h index 2b0e90396..cd3d0a415 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h | |||
| @@ -95,6 +95,8 @@ struct Specialization final { | |||
| 95 | std::bitset<Maxwell::NumVertexAttributes> enabled_attributes; | 95 | std::bitset<Maxwell::NumVertexAttributes> enabled_attributes; |
| 96 | std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; | 96 | std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; |
| 97 | bool ndc_minus_one_to_one{}; | 97 | bool ndc_minus_one_to_one{}; |
| 98 | float alpha_test_ref{}; | ||
| 99 | Maxwell::ComparisonOp alpha_test_func{}; | ||
| 98 | }; | 100 | }; |
| 99 | // Old gcc versions don't consider this trivially copyable. | 101 | // Old gcc versions don't consider this trivially copyable. |
| 100 | // static_assert(std::is_trivially_copyable_v<Specialization>); | 102 | // static_assert(std::is_trivially_copyable_v<Specialization>); |