summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp5
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h8
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp54
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.h3
5 files changed, 76 insertions, 2 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..1b9611c59 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -60,6 +60,11 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
60 rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0); 60 rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
61 topology.Assign(regs.draw.topology); 61 topology.Assign(regs.draw.topology);
62 62
63 alpha_raw = 0;
64 alpha_test_enabled.Assign(regs.alpha_test_enabled);
65 alpha_test_func.Assign(PackComparisonOp(regs.alpha_test_func));
66 std::memcpy(&alpha_test_ref, &regs.alpha_test_ref, sizeof(u32)); // TODO: C++20 std::bit_cast
67
63 std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast 68 std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
64 69
65 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { 70 for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++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..9a45ec6b7 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -187,6 +187,14 @@ 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
192 union {
193 u32 alpha_raw;
194 BitField<0, 3, u32> alpha_test_func;
195 BitField<3, 1, u32> alpha_test_enabled;
196 };
197
190 u32 point_size; 198 u32 point_size;
191 std::array<u32, Maxwell::NumVertexArrays> binding_divisors; 199 std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
192 std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; 200 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..9ccf5d011 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -344,6 +344,14 @@ VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
344 } 344 }
345 specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one; 345 specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one;
346 346
347 // Alpha test
348 if (fixed_state.alpha_test_enabled == 1) {
349 specialization.alpha_test_enabled = true;
350 specialization.alpha_test_func = static_cast<u8>(fixed_state.alpha_test_func);
351 // memcpy from u32 to float TODO: C++20 std::bit_cast
352 std::memcpy(&specialization.alpha_test_ref, &fixed_state.alpha_test_ref, sizeof(float));
353 }
354
347 SPIRVProgram program; 355 SPIRVProgram program;
348 std::vector<VkDescriptorSetLayoutBinding> bindings; 356 std::vector<VkDescriptorSetLayoutBinding> bindings;
349 357
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index a20452b87..356d2ab7a 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -2075,6 +2075,55 @@ private:
2075 return {}; 2075 return {};
2076 } 2076 }
2077 2077
2078 void AlphaTest(const Id& pointer) {
2079 const Id true_label = OpLabel();
2080 const Id skip_label = OpLabel();
2081 Id condition;
2082 switch (specialization.alpha_test_func) {
2083 case VK_COMPARE_OP_NEVER:
2084 condition = Constant(t_float, false); // Never true
2085 break;
2086 case VK_COMPARE_OP_LESS:
2087 condition = OpFOrdLessThan(t_bool, Constant(t_float, specialization.alpha_test_ref),
2088 OpLoad(t_float, pointer));
2089 break;
2090 case VK_COMPARE_OP_EQUAL:
2091 condition = OpFOrdEqual(t_bool, Constant(t_float, specialization.alpha_test_ref),
2092 OpLoad(t_float, pointer));
2093 break;
2094 case VK_COMPARE_OP_LESS_OR_EQUAL:
2095 condition = OpFOrdLessThanEqual(
2096 t_bool, Constant(t_float, specialization.alpha_test_ref), OpLoad(t_float, pointer));
2097 break;
2098 case VK_COMPARE_OP_GREATER:
2099 // Note: requires "Equal" to properly work for ssbu. perhaps a precision issue
2100 condition = OpFOrdGreaterThanEqual(
2101 t_bool, Constant(t_float, specialization.alpha_test_ref), OpLoad(t_float, pointer));
2102 break;
2103 case VK_COMPARE_OP_NOT_EQUAL:
2104 // Note: not accurate when tested against a unit test
2105 // TODO: confirm if used by games
2106 condition = OpFOrdNotEqual(t_bool, Constant(t_float, specialization.alpha_test_ref),
2107 OpLoad(t_float, pointer));
2108 break;
2109 case VK_COMPARE_OP_GREATER_OR_EQUAL:
2110 condition = OpFOrdGreaterThanEqual(
2111 t_bool, Constant(t_float, specialization.alpha_test_ref), OpLoad(t_float, pointer));
2112 break;
2113 case VK_COMPARE_OP_ALWAYS:
2114 condition = Constant(t_bool, true); // Always true
2115 break;
2116 default:
2117 LOG_WARNING(Render_Vulkan, "Unimplemented alpha test function");
2118 condition = Constant(t_bool, true); // Always true
2119 break;
2120 }
2121 OpBranchConditional(condition, true_label, skip_label);
2122 AddLabel(true_label);
2123 OpKill();
2124 AddLabel(skip_label);
2125 }
2126
2078 void PreExit() { 2127 void PreExit() {
2079 if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) { 2128 if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) {
2080 const u32 position_index = out_indices.position.value(); 2129 const u32 position_index = out_indices.position.value();
@@ -2097,8 +2146,6 @@ private:
2097 UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, 2146 UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0,
2098 "Sample mask write is unimplemented"); 2147 "Sample mask write is unimplemented");
2099 2148
2100 // TODO(Rodrigo): Alpha testing
2101
2102 // Write the color outputs using the data in the shader registers, disabled 2149 // Write the color outputs using the data in the shader registers, disabled
2103 // rendertargets/components are skipped in the register assignment. 2150 // rendertargets/components are skipped in the register assignment.
2104 u32 current_reg = 0; 2151 u32 current_reg = 0;
@@ -2110,6 +2157,9 @@ private:
2110 } 2157 }
2111 const Id pointer = AccessElement(t_out_float, frag_colors[rt], component); 2158 const Id pointer = AccessElement(t_out_float, frag_colors[rt], component);
2112 OpStore(pointer, SafeGetRegister(current_reg)); 2159 OpStore(pointer, SafeGetRegister(current_reg));
2160 if (specialization.alpha_test_enabled && component == 3) {
2161 AlphaTest(pointer);
2162 }
2113 ++current_reg; 2163 ++current_reg;
2114 } 2164 }
2115 } 2165 }
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h
index 2b0e90396..ddbcb0b41 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h
@@ -95,6 +95,9 @@ 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 bool alpha_test_enabled{};
99 float alpha_test_ref{};
100 u8 alpha_test_func{};
98}; 101};
99// Old gcc versions don't consider this trivially copyable. 102// Old gcc versions don't consider this trivially copyable.
100// static_assert(std::is_trivially_copyable_v<Specialization>); 103// static_assert(std::is_trivially_copyable_v<Specialization>);