|
|
|
@ -12,14 +12,15 @@ |
|
|
|
#include "common/cityhash.h"
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
|
|
|
|
#include "video_core/renderer_vulkan/vk_state_tracker.h"
|
|
|
|
|
|
|
|
namespace Vulkan { |
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
constexpr std::size_t POINT = 0; |
|
|
|
constexpr std::size_t LINE = 1; |
|
|
|
constexpr std::size_t POLYGON = 2; |
|
|
|
constexpr size_t POINT = 0; |
|
|
|
constexpr size_t LINE = 1; |
|
|
|
constexpr size_t POLYGON = 2; |
|
|
|
constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { |
|
|
|
POINT, // Points
|
|
|
|
LINE, // Lines
|
|
|
|
@ -40,10 +41,14 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { |
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) { |
|
|
|
const std::array enabled_lut = {regs.polygon_offset_point_enable, |
|
|
|
regs.polygon_offset_line_enable, |
|
|
|
regs.polygon_offset_fill_enable}; |
|
|
|
void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, |
|
|
|
bool has_extended_dynamic_state) { |
|
|
|
const Maxwell& regs = maxwell3d.regs; |
|
|
|
const std::array enabled_lut{ |
|
|
|
regs.polygon_offset_point_enable, |
|
|
|
regs.polygon_offset_line_enable, |
|
|
|
regs.polygon_offset_fill_enable, |
|
|
|
}; |
|
|
|
const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); |
|
|
|
|
|
|
|
raw1 = 0; |
|
|
|
@ -64,45 +69,53 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta |
|
|
|
|
|
|
|
raw2 = 0; |
|
|
|
const auto test_func = |
|
|
|
regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; |
|
|
|
regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; |
|
|
|
alpha_test_func.Assign(PackComparisonOp(test_func)); |
|
|
|
early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0); |
|
|
|
|
|
|
|
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) { |
|
|
|
binding_divisors[index] = |
|
|
|
regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0; |
|
|
|
if (maxwell3d.dirty.flags[Dirty::InstanceDivisors]) { |
|
|
|
maxwell3d.dirty.flags[Dirty::InstanceDivisors] = false; |
|
|
|
for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
|
|
|
const bool is_enabled = regs.instanced_arrays.IsInstancingEnabled(index); |
|
|
|
binding_divisors[index] = is_enabled ? regs.vertex_array[index].divisor : 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
|
|
|
const auto& input = regs.vertex_attrib_format[index]; |
|
|
|
auto& attribute = attributes[index]; |
|
|
|
attribute.raw = 0; |
|
|
|
attribute.enabled.Assign(input.IsConstant() ? 0 : 1); |
|
|
|
attribute.buffer.Assign(input.buffer); |
|
|
|
attribute.offset.Assign(input.offset); |
|
|
|
attribute.type.Assign(static_cast<u32>(input.type.Value())); |
|
|
|
attribute.size.Assign(static_cast<u32>(input.size.Value())); |
|
|
|
attribute.binding_index_enabled.Assign(regs.vertex_array[index].IsEnabled() ? 1 : 0); |
|
|
|
if (maxwell3d.dirty.flags[Dirty::VertexAttributes]) { |
|
|
|
maxwell3d.dirty.flags[Dirty::VertexAttributes] = false; |
|
|
|
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
|
|
|
const auto& input = regs.vertex_attrib_format[index]; |
|
|
|
auto& attribute = attributes[index]; |
|
|
|
attribute.raw = 0; |
|
|
|
attribute.enabled.Assign(input.IsConstant() ? 0 : 1); |
|
|
|
attribute.buffer.Assign(input.buffer); |
|
|
|
attribute.offset.Assign(input.offset); |
|
|
|
attribute.type.Assign(static_cast<u32>(input.type.Value())); |
|
|
|
attribute.size.Assign(static_cast<u32>(input.size.Value())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (std::size_t index = 0; index < std::size(attachments); ++index) { |
|
|
|
attachments[index].Fill(regs, index); |
|
|
|
if (maxwell3d.dirty.flags[Dirty::Blending]) { |
|
|
|
maxwell3d.dirty.flags[Dirty::Blending] = false; |
|
|
|
for (size_t index = 0; index < attachments.size(); ++index) { |
|
|
|
attachments[index].Refresh(regs, index); |
|
|
|
} |
|
|
|
} |
|
|
|
if (maxwell3d.dirty.flags[Dirty::ViewportSwizzles]) { |
|
|
|
maxwell3d.dirty.flags[Dirty::ViewportSwizzles] = false; |
|
|
|
const auto& transform = regs.viewport_transform; |
|
|
|
std::ranges::transform(transform, viewport_swizzles.begin(), [](const auto& viewport) { |
|
|
|
return static_cast<u16>(viewport.swizzle.raw); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
const auto& transform = regs.viewport_transform; |
|
|
|
std::transform(transform.begin(), transform.end(), viewport_swizzles.begin(), |
|
|
|
[](const auto& viewport) { return static_cast<u16>(viewport.swizzle.raw); }); |
|
|
|
|
|
|
|
if (!has_extended_dynamic_state) { |
|
|
|
no_extended_dynamic_state.Assign(1); |
|
|
|
dynamic_state.Fill(regs); |
|
|
|
dynamic_state.Refresh(regs); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size_t index) { |
|
|
|
void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t index) { |
|
|
|
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; |
|
|
|
|
|
|
|
raw = 0; |
|
|
|
@ -141,7 +154,7 @@ void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size |
|
|
|
enable.Assign(1); |
|
|
|
} |
|
|
|
|
|
|
|
void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { |
|
|
|
void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) { |
|
|
|
u32 packed_front_face = PackFrontFace(regs.front_face); |
|
|
|
if (regs.screen_y_control.triangle_rast_flip != 0) { |
|
|
|
// Flip front face
|
|
|
|
@ -178,9 +191,9 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
std::size_t FixedPipelineState::Hash() const noexcept { |
|
|
|
size_t FixedPipelineState::Hash() const noexcept { |
|
|
|
const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size()); |
|
|
|
return static_cast<std::size_t>(hash); |
|
|
|
return static_cast<size_t>(hash); |
|
|
|
} |
|
|
|
|
|
|
|
bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { |
|
|
|
|