Merge pull request #4946 from ameerj/alpha-test

renderer_vulkan: Implement alpha testing
This commit is contained in:
Rodrigo Locatti 2020-11-25 18:48:34 -03:00 committed by GitHub
commit b834c21894
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 3 deletions

View file

@ -8,6 +8,7 @@
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include "common/bit_cast.h"
#include "common/cityhash.h" #include "common/cityhash.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/renderer_vulkan/fixed_pipeline_state.h" #include "video_core/renderer_vulkan/fixed_pipeline_state.h"
@ -60,7 +61,13 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0); rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
topology.Assign(regs.draw.topology); topology.Assign(regs.draw.topology);
std::memcpy(&point_size, &regs.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast alpha_raw = 0;
const auto test_func =
regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always;
alpha_test_func.Assign(PackComparisonOp(test_func));
alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref);
point_size = Common::BitCast<u32>(regs.point_size);
for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
binding_divisors[index] = binding_divisors[index] =

View file

@ -187,6 +187,13 @@ struct FixedPipelineState {
BitField<23, 1, u32> rasterize_enable; BitField<23, 1, u32> rasterize_enable;
BitField<24, 4, Maxwell::PrimitiveTopology> topology; BitField<24, 4, Maxwell::PrimitiveTopology> topology;
}; };
u32 alpha_test_ref; ///< Alpha test reference value
union {
u32 alpha_raw;
BitField<0, 3, u32> alpha_test_func;
};
u32 point_size; u32 point_size;
std::array<u32, Maxwell::NumVertexArrays> binding_divisors; std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes;

View file

@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "common/bit_cast.h"
#include "common/microprofile.h" #include "common/microprofile.h"
#include "core/core.h" #include "core/core.h"
#include "core/memory.h" #include "core/memory.h"
@ -344,6 +345,11 @@ VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
} }
specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one; specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one;
// Alpha test
specialization.alpha_test_func =
FixedPipelineState::UnpackComparisonOp(fixed_state.alpha_test_func.Value());
specialization.alpha_test_ref = Common::BitCast<float>(fixed_state.alpha_test_ref);
SPIRVProgram program; SPIRVProgram program;
std::vector<VkDescriptorSetLayoutBinding> bindings; std::vector<VkDescriptorSetLayoutBinding> bindings;

View file

@ -2075,6 +2075,45 @@ private:
return {}; return {};
} }
Id MaxwellToSpirvComparison(Maxwell::ComparisonOp compare_op, Id operand_1, Id operand_2) {
using Compare = Maxwell::ComparisonOp;
switch (compare_op) {
case Compare::NeverOld:
return v_false; // Never let the test pass
case Compare::LessOld:
return OpFOrdLessThan(t_bool, operand_1, operand_2);
case Compare::EqualOld:
return OpFOrdEqual(t_bool, operand_1, operand_2);
case Compare::LessEqualOld:
return OpFOrdLessThanEqual(t_bool, operand_1, operand_2);
case Compare::GreaterOld:
return OpFOrdGreaterThan(t_bool, operand_1, operand_2);
case Compare::NotEqualOld:
return OpFOrdNotEqual(t_bool, operand_1, operand_2);
case Compare::GreaterEqualOld:
return OpFOrdGreaterThanEqual(t_bool, operand_1, operand_2);
default:
UNREACHABLE();
}
}
void AlphaTest(Id pointer) {
if (specialization.alpha_test_func == Maxwell::ComparisonOp::AlwaysOld) {
return;
}
const Id true_label = OpLabel();
const Id discard_label = OpLabel();
const Id alpha_reference = Constant(t_float, specialization.alpha_test_ref);
const Id alpha_value = OpLoad(t_float, pointer);
const Id condition =
MaxwellToSpirvComparison(specialization.alpha_test_func, alpha_value, alpha_reference);
OpBranchConditional(condition, true_label, discard_label);
AddLabel(discard_label);
OpKill();
AddLabel(true_label);
}
void PreExit() { void PreExit() {
if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) { if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) {
const u32 position_index = out_indices.position.value(); const u32 position_index = out_indices.position.value();
@ -2097,8 +2136,6 @@ private:
UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0,
"Sample mask write is unimplemented"); "Sample mask write is unimplemented");
// TODO(Rodrigo): Alpha testing
// Write the color outputs using the data in the shader registers, disabled // Write the color outputs using the data in the shader registers, disabled
// rendertargets/components are skipped in the register assignment. // rendertargets/components are skipped in the register assignment.
u32 current_reg = 0; u32 current_reg = 0;
@ -2110,6 +2147,9 @@ private:
} }
const Id pointer = AccessElement(t_out_float, frag_colors[rt], component); const Id pointer = AccessElement(t_out_float, frag_colors[rt], component);
OpStore(pointer, SafeGetRegister(current_reg)); OpStore(pointer, SafeGetRegister(current_reg));
if (rt == 0 && component == 3) {
AlphaTest(pointer);
}
++current_reg; ++current_reg;
} }
} }

View file

@ -95,6 +95,8 @@ struct Specialization final {
std::bitset<Maxwell::NumVertexAttributes> enabled_attributes; std::bitset<Maxwell::NumVertexAttributes> enabled_attributes;
std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{};
bool ndc_minus_one_to_one{}; bool ndc_minus_one_to_one{};
float alpha_test_ref{};
Maxwell::ComparisonOp alpha_test_func{};
}; };
// Old gcc versions don't consider this trivially copyable. // Old gcc versions don't consider this trivially copyable.
// static_assert(std::is_trivially_copyable_v<Specialization>); // static_assert(std::is_trivially_copyable_v<Specialization>);