diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 1b9611c59..192828300 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -61,8 +61,9 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta topology.Assign(regs.draw.topology); alpha_raw = 0; - alpha_test_enabled.Assign(regs.alpha_test_enabled); - alpha_test_func.Assign(PackComparisonOp(regs.alpha_test_func)); + const auto test_func = + regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; + alpha_test_func.Assign(PackComparisonOp(test_func)); std::memcpy(&alpha_test_ref, ®s.alpha_test_ref, sizeof(u32)); // TODO: C++20 std::bit_cast std::memcpy(&point_size, ®s.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 9a45ec6b7..42480e8d0 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -188,11 +188,10 @@ struct FixedPipelineState { BitField<24, 4, Maxwell::PrimitiveTopology> topology; }; - u32 alpha_test_ref; /// < Alpha test reference + u32 alpha_test_ref; ///< Alpha test reference value union { u32 alpha_raw; BitField<0, 3, u32> alpha_test_func; - BitField<3, 1, u32> alpha_test_enabled; }; u32 point_size; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 9ccf5d011..a66a841fb 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -345,12 +345,10 @@ VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) { specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one; // Alpha test - if (fixed_state.alpha_test_enabled == 1) { - specialization.alpha_test_enabled = true; - specialization.alpha_test_func = static_cast(fixed_state.alpha_test_func); - // memcpy from u32 to float TODO: C++20 std::bit_cast - std::memcpy(&specialization.alpha_test_ref, &fixed_state.alpha_test_ref, sizeof(float)); - } + specialization.alpha_test_func = + FixedPipelineState::UnpackComparisonOp(fixed_state.alpha_test_func.Value()); + // memcpy from u32 to float TODO: C++20 std::bit_cast + std::memcpy(&specialization.alpha_test_ref, &fixed_state.alpha_test_ref, sizeof(float)); SPIRVProgram program; std::vector bindings; diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 356d2ab7a..81550bc96 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -2075,48 +2075,42 @@ private: return {}; } - void AlphaTest(const Id& pointer) { + void AlphaTest(Id pointer) { const Id true_label = OpLabel(); const Id skip_label = OpLabel(); + const Id alpha_reference = Constant(t_float, specialization.alpha_test_ref); + const Id alpha_value = OpLoad(t_float, pointer); Id condition; + using Compare = Maxwell::ComparisonOp; switch (specialization.alpha_test_func) { - case VK_COMPARE_OP_NEVER: - condition = Constant(t_float, false); // Never true + case Compare::NeverOld: + condition = v_false; // Never true break; - case VK_COMPARE_OP_LESS: - condition = OpFOrdLessThan(t_bool, Constant(t_float, specialization.alpha_test_ref), - OpLoad(t_float, pointer)); + case Compare::LessOld: + condition = OpFOrdLessThan(t_bool, alpha_reference, alpha_value); break; - case VK_COMPARE_OP_EQUAL: - condition = OpFOrdEqual(t_bool, Constant(t_float, specialization.alpha_test_ref), - OpLoad(t_float, pointer)); + case Compare::EqualOld: + condition = OpFOrdEqual(t_bool, alpha_reference, alpha_value); break; - case VK_COMPARE_OP_LESS_OR_EQUAL: - condition = OpFOrdLessThanEqual( - t_bool, Constant(t_float, specialization.alpha_test_ref), OpLoad(t_float, pointer)); + case Compare::LessEqualOld: + condition = OpFOrdLessThanEqual(t_bool, alpha_reference, alpha_value); break; - case VK_COMPARE_OP_GREATER: + case Compare::GreaterOld: // Note: requires "Equal" to properly work for ssbu. perhaps a precision issue - condition = OpFOrdGreaterThanEqual( - t_bool, Constant(t_float, specialization.alpha_test_ref), OpLoad(t_float, pointer)); + condition = OpFOrdGreaterThanEqual(t_bool, alpha_reference, alpha_value); break; - case VK_COMPARE_OP_NOT_EQUAL: + case Compare::NotEqualOld: // Note: not accurate when tested against a unit test // TODO: confirm if used by games - condition = OpFOrdNotEqual(t_bool, Constant(t_float, specialization.alpha_test_ref), - OpLoad(t_float, pointer)); + condition = OpFOrdNotEqual(t_bool, alpha_reference, alpha_value); break; - case VK_COMPARE_OP_GREATER_OR_EQUAL: - condition = OpFOrdGreaterThanEqual( - t_bool, Constant(t_float, specialization.alpha_test_ref), OpLoad(t_float, pointer)); - break; - case VK_COMPARE_OP_ALWAYS: - condition = Constant(t_bool, true); // Always true + case Compare::GreaterEqualOld: + condition = OpFOrdGreaterThanEqual(t_bool, alpha_reference, alpha_value); break; + case Compare::AlwaysOld: + return; default: - LOG_WARNING(Render_Vulkan, "Unimplemented alpha test function"); - condition = Constant(t_bool, true); // Always true - break; + UNREACHABLE(); } OpBranchConditional(condition, true_label, skip_label); AddLabel(true_label); @@ -2157,7 +2151,7 @@ private: } const Id pointer = AccessElement(t_out_float, frag_colors[rt], component); OpStore(pointer, SafeGetRegister(current_reg)); - if (specialization.alpha_test_enabled && component == 3) { + if (rt == 0 && component == 3) { AlphaTest(pointer); } ++current_reg; diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h index ddbcb0b41..cd3d0a415 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h @@ -95,9 +95,8 @@ struct Specialization final { std::bitset enabled_attributes; std::array attribute_types{}; bool ndc_minus_one_to_one{}; - bool alpha_test_enabled{}; float alpha_test_ref{}; - u8 alpha_test_func{}; + Maxwell::ComparisonOp alpha_test_func{}; }; // Old gcc versions don't consider this trivially copyable. // static_assert(std::is_trivially_copyable_v);