fixed_pipeline_state: Pack rasterizer state
Reduce FixedPipelineState's size to 600 bytes.
This commit is contained in:
parent
7790144a55
commit
548dd27f45
4 changed files with 157 additions and 165 deletions
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include <boost/functional/hash.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
|
@ -12,6 +13,31 @@
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr std::size_t POINT = 0;
|
||||||
|
constexpr std::size_t LINE = 1;
|
||||||
|
constexpr std::size_t POLYGON = 2;
|
||||||
|
constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
|
||||||
|
POINT, // Points
|
||||||
|
LINE, // Lines
|
||||||
|
LINE, // LineLoop
|
||||||
|
LINE, // LineStrip
|
||||||
|
POLYGON, // Triangles
|
||||||
|
POLYGON, // TriangleStrip
|
||||||
|
POLYGON, // TriangleFan
|
||||||
|
POLYGON, // Quads
|
||||||
|
POLYGON, // QuadStrip
|
||||||
|
POLYGON, // Polygon
|
||||||
|
LINE, // LinesAdjacency
|
||||||
|
LINE, // LineStripAdjacency
|
||||||
|
POLYGON, // TrianglesAdjacency
|
||||||
|
POLYGON, // TriangleStripAdjacency
|
||||||
|
POLYGON, // Patches
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept {
|
void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept {
|
||||||
raw = 0;
|
raw = 0;
|
||||||
front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
|
front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
|
||||||
|
@ -36,14 +62,41 @@ void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept {
|
||||||
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
void FixedPipelineState::Rasterizer::Fill(const Maxwell& regs) noexcept {
|
||||||
|
const auto& clip = regs.view_volume_clip_control;
|
||||||
|
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());
|
||||||
|
|
||||||
constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) {
|
u32 packed_front_face = PackFrontFace(regs.front_face);
|
||||||
return FixedPipelineState::InputAssembly(
|
if (regs.screen_y_control.triangle_rast_flip != 0 &&
|
||||||
regs.draw.topology, regs.primitive_restart.enabled,
|
regs.viewport_transform[0].scale_y > 0.0f) {
|
||||||
regs.draw.topology == Maxwell::PrimitiveTopology::Points ? regs.point_size : 0.0f);
|
// Flip front face
|
||||||
|
packed_front_face = 1 - packed_front_face;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
raw = 0;
|
||||||
|
topology.Assign(topology_index);
|
||||||
|
primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
|
||||||
|
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
|
||||||
|
depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
|
||||||
|
depth_clamp_enable.Assign(clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1 ? 1 : 0);
|
||||||
|
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
|
||||||
|
cull_face.Assign(PackCullFace(regs.cull_face));
|
||||||
|
front_face.Assign(packed_front_face);
|
||||||
|
polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front));
|
||||||
|
patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
|
||||||
|
tessellation_primitive.Assign(static_cast<u32>(regs.tess_mode.prim.Value()));
|
||||||
|
tessellation_spacing.Assign(static_cast<u32>(regs.tess_mode.spacing.Value()));
|
||||||
|
tessellation_clockwise.Assign(regs.tess_mode.cw.Value());
|
||||||
|
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
||||||
|
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
|
||||||
|
std::memcpy(&point_size, ®s.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState(
|
constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState(
|
||||||
const Maxwell& regs, std::size_t render_target) {
|
const Maxwell& regs, std::size_t render_target) {
|
||||||
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target];
|
const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target];
|
||||||
|
@ -86,56 +139,6 @@ constexpr FixedPipelineState::ColorBlending GetColorBlendingState(const Maxwell&
|
||||||
GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)});
|
GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)});
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr FixedPipelineState::Tessellation GetTessellationState(const Maxwell& regs) {
|
|
||||||
return FixedPipelineState::Tessellation(regs.patch_vertices, regs.tess_mode.prim,
|
|
||||||
regs.tess_mode.spacing, regs.tess_mode.cw != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr std::size_t Point = 0;
|
|
||||||
constexpr std::size_t Line = 1;
|
|
||||||
constexpr std::size_t Polygon = 2;
|
|
||||||
constexpr std::array PolygonOffsetEnableLUT = {
|
|
||||||
Point, // Points
|
|
||||||
Line, // Lines
|
|
||||||
Line, // LineLoop
|
|
||||||
Line, // LineStrip
|
|
||||||
Polygon, // Triangles
|
|
||||||
Polygon, // TriangleStrip
|
|
||||||
Polygon, // TriangleFan
|
|
||||||
Polygon, // Quads
|
|
||||||
Polygon, // QuadStrip
|
|
||||||
Polygon, // Polygon
|
|
||||||
Line, // LinesAdjacency
|
|
||||||
Line, // LineStripAdjacency
|
|
||||||
Polygon, // TrianglesAdjacency
|
|
||||||
Polygon, // TriangleStripAdjacency
|
|
||||||
Polygon, // Patches
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs) {
|
|
||||||
const std::array enabled_lut = {regs.polygon_offset_point_enable,
|
|
||||||
regs.polygon_offset_line_enable,
|
|
||||||
regs.polygon_offset_fill_enable};
|
|
||||||
const auto topology = static_cast<std::size_t>(regs.draw.topology.Value());
|
|
||||||
const bool depth_bias_enabled = enabled_lut[PolygonOffsetEnableLUT[topology]];
|
|
||||||
|
|
||||||
const auto& clip = regs.view_volume_clip_control;
|
|
||||||
const bool depth_clamp_enabled = clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1;
|
|
||||||
|
|
||||||
Maxwell::FrontFace front_face = regs.front_face;
|
|
||||||
if (regs.screen_y_control.triangle_rast_flip != 0 &&
|
|
||||||
regs.viewport_transform[0].scale_y > 0.0f) {
|
|
||||||
if (front_face == Maxwell::FrontFace::CounterClockWise)
|
|
||||||
front_face = Maxwell::FrontFace::ClockWise;
|
|
||||||
else if (front_face == Maxwell::FrontFace::ClockWise)
|
|
||||||
front_face = Maxwell::FrontFace::CounterClockWise;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
|
|
||||||
return FixedPipelineState::Rasterizer(regs.cull_test_enabled, depth_bias_enabled,
|
|
||||||
depth_clamp_enabled, gl_ndc, regs.cull_face, front_face);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
|
std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
|
||||||
|
@ -168,43 +171,14 @@ bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const n
|
||||||
return std::memcmp(this, &rhs, sizeof *this) == 0;
|
return std::memcmp(this, &rhs, sizeof *this) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t FixedPipelineState::InputAssembly::Hash() const noexcept {
|
|
||||||
std::size_t point_size_int = 0;
|
|
||||||
std::memcpy(&point_size_int, &point_size, sizeof(point_size));
|
|
||||||
return (static_cast<std::size_t>(topology) << 24) ^ (point_size_int << 32) ^
|
|
||||||
static_cast<std::size_t>(primitive_restart_enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FixedPipelineState::InputAssembly::operator==(const InputAssembly& rhs) const noexcept {
|
|
||||||
return std::tie(topology, primitive_restart_enable, point_size) ==
|
|
||||||
std::tie(rhs.topology, rhs.primitive_restart_enable, rhs.point_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t FixedPipelineState::Tessellation::Hash() const noexcept {
|
|
||||||
return static_cast<std::size_t>(patch_control_points) ^
|
|
||||||
(static_cast<std::size_t>(primitive) << 6) ^ (static_cast<std::size_t>(spacing) << 8) ^
|
|
||||||
(static_cast<std::size_t>(clockwise) << 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FixedPipelineState::Tessellation::operator==(const Tessellation& rhs) const noexcept {
|
|
||||||
return std::tie(patch_control_points, primitive, spacing, clockwise) ==
|
|
||||||
std::tie(rhs.patch_control_points, rhs.primitive, rhs.spacing, rhs.clockwise);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t FixedPipelineState::Rasterizer::Hash() const noexcept {
|
std::size_t FixedPipelineState::Rasterizer::Hash() const noexcept {
|
||||||
return static_cast<std::size_t>(cull_enable) ^
|
u64 hash = static_cast<u64>(raw) << 32;
|
||||||
(static_cast<std::size_t>(depth_bias_enable) << 1) ^
|
std::memcpy(&hash, &point_size, sizeof(u32));
|
||||||
(static_cast<std::size_t>(depth_clamp_enable) << 2) ^
|
return static_cast<std::size_t>(hash);
|
||||||
(static_cast<std::size_t>(ndc_minus_one_to_one) << 3) ^
|
|
||||||
(static_cast<std::size_t>(cull_face) << 24) ^
|
|
||||||
(static_cast<std::size_t>(front_face) << 48);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noexcept {
|
bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noexcept {
|
||||||
return std::tie(cull_enable, depth_bias_enable, depth_clamp_enable, ndc_minus_one_to_one,
|
return raw == rhs.raw && point_size == rhs.point_size;
|
||||||
cull_face, front_face) ==
|
|
||||||
std::tie(rhs.cull_enable, rhs.depth_bias_enable, rhs.depth_clamp_enable,
|
|
||||||
rhs.ndc_minus_one_to_one, rhs.cull_face, rhs.front_face);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept {
|
std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept {
|
||||||
|
@ -231,8 +205,6 @@ bool FixedPipelineState::ColorBlending::operator==(const ColorBlending& rhs) con
|
||||||
std::size_t FixedPipelineState::Hash() const noexcept {
|
std::size_t FixedPipelineState::Hash() const noexcept {
|
||||||
std::size_t hash = 0;
|
std::size_t hash = 0;
|
||||||
boost::hash_combine(hash, vertex_input.Hash());
|
boost::hash_combine(hash, vertex_input.Hash());
|
||||||
boost::hash_combine(hash, input_assembly.Hash());
|
|
||||||
boost::hash_combine(hash, tessellation.Hash());
|
|
||||||
boost::hash_combine(hash, rasterizer.Hash());
|
boost::hash_combine(hash, rasterizer.Hash());
|
||||||
boost::hash_combine(hash, depth_stencil.Hash());
|
boost::hash_combine(hash, depth_stencil.Hash());
|
||||||
boost::hash_combine(hash, color_blending.Hash());
|
boost::hash_combine(hash, color_blending.Hash());
|
||||||
|
@ -240,17 +212,13 @@ std::size_t FixedPipelineState::Hash() const noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept {
|
bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept {
|
||||||
return std::tie(vertex_input, input_assembly, tessellation, rasterizer, depth_stencil,
|
return std::tie(vertex_input, rasterizer, depth_stencil, color_blending) ==
|
||||||
color_blending) == std::tie(rhs.vertex_input, rhs.input_assembly,
|
std::tie(rhs.vertex_input, rhs.rasterizer, rhs.depth_stencil, rhs.color_blending);
|
||||||
rhs.tessellation, rhs.rasterizer, rhs.depth_stencil,
|
|
||||||
rhs.color_blending);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedPipelineState GetFixedPipelineState(const Maxwell& regs) {
|
FixedPipelineState GetFixedPipelineState(const Maxwell& regs) {
|
||||||
FixedPipelineState fixed_state;
|
FixedPipelineState fixed_state;
|
||||||
fixed_state.input_assembly = GetInputAssemblyState(regs);
|
fixed_state.rasterizer.Fill(regs);
|
||||||
fixed_state.tessellation = GetTessellationState(regs);
|
|
||||||
fixed_state.rasterizer = GetRasterizerState(regs);
|
|
||||||
fixed_state.depth_stencil.Fill(regs);
|
fixed_state.depth_stencil.Fill(regs);
|
||||||
fixed_state.color_blending = GetColorBlendingState(regs);
|
fixed_state.color_blending = GetColorBlendingState(regs);
|
||||||
return fixed_state;
|
return fixed_state;
|
||||||
|
@ -307,4 +275,41 @@ Maxwell::StencilOp FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
|
||||||
return LUT[packed];
|
return LUT[packed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 FixedPipelineState::PackCullFace(Maxwell::CullFace cull) noexcept {
|
||||||
|
// FrontAndBack is 0x408, by substracting 0x406 in it we get 2.
|
||||||
|
// Individual cull faces are in 0x404 and 0x405, substracting 0x404 we get 0 and 1.
|
||||||
|
const u32 value = static_cast<u32>(cull);
|
||||||
|
return value - (value == 0x408 ? 0x406 : 0x404);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::CullFace FixedPipelineState::UnpackCullFace(u32 packed) noexcept {
|
||||||
|
static constexpr std::array LUT = {Maxwell::CullFace::Front, Maxwell::CullFace::Back,
|
||||||
|
Maxwell::CullFace::FrontAndBack};
|
||||||
|
return LUT[packed];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 FixedPipelineState::PackFrontFace(Maxwell::FrontFace face) noexcept {
|
||||||
|
return static_cast<u32>(face) - 0x900;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::FrontFace FixedPipelineState::UnpackFrontFace(u32 packed) noexcept {
|
||||||
|
return static_cast<Maxwell::FrontFace>(packed + 0x900);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 FixedPipelineState::PackPolygonMode(Maxwell::PolygonMode mode) noexcept {
|
||||||
|
return static_cast<u32>(mode) - 0x1B00;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::PolygonMode FixedPipelineState::UnpackPolygonMode(u32 packed) noexcept {
|
||||||
|
return static_cast<Maxwell::PolygonMode>(packed + 0x1B00);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOperation op) noexcept {
|
||||||
|
return static_cast<u32>(op) - 0x1500;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::LogicOperation FixedPipelineState::UnpackLogicOp(u32 packed) noexcept {
|
||||||
|
return static_cast<Maxwell::LogicOperation>(packed + 0x1500);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -30,6 +30,18 @@ struct FixedPipelineState {
|
||||||
static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
|
static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
|
||||||
static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
|
static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
|
||||||
|
|
||||||
|
static u32 PackCullFace(Maxwell::CullFace cull) noexcept;
|
||||||
|
static Maxwell::CullFace UnpackCullFace(u32 packed) noexcept;
|
||||||
|
|
||||||
|
static u32 PackFrontFace(Maxwell::FrontFace face) noexcept;
|
||||||
|
static Maxwell::FrontFace UnpackFrontFace(u32 packed) noexcept;
|
||||||
|
|
||||||
|
static u32 PackPolygonMode(Maxwell::PolygonMode mode) noexcept;
|
||||||
|
static Maxwell::PolygonMode UnpackPolygonMode(u32 packed) noexcept;
|
||||||
|
|
||||||
|
static u32 PackLogicOp(Maxwell::LogicOperation op) noexcept;
|
||||||
|
static Maxwell::LogicOperation UnpackLogicOp(u32 packed) noexcept;
|
||||||
|
|
||||||
struct BlendingAttachment {
|
struct BlendingAttachment {
|
||||||
constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
|
constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
|
||||||
Maxwell::Blend::Factor src_rgb_func,
|
Maxwell::Blend::Factor src_rgb_func,
|
||||||
|
@ -119,62 +131,30 @@ struct FixedPipelineState {
|
||||||
};
|
};
|
||||||
static_assert(IsHashable<VertexInput>);
|
static_assert(IsHashable<VertexInput>);
|
||||||
|
|
||||||
struct InputAssembly {
|
|
||||||
constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable,
|
|
||||||
float point_size)
|
|
||||||
: topology{topology}, primitive_restart_enable{primitive_restart_enable},
|
|
||||||
point_size{point_size} {}
|
|
||||||
InputAssembly() = default;
|
|
||||||
|
|
||||||
Maxwell::PrimitiveTopology topology;
|
|
||||||
bool primitive_restart_enable;
|
|
||||||
float point_size;
|
|
||||||
|
|
||||||
std::size_t Hash() const noexcept;
|
|
||||||
|
|
||||||
bool operator==(const InputAssembly& rhs) const noexcept;
|
|
||||||
|
|
||||||
bool operator!=(const InputAssembly& rhs) const noexcept {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Tessellation {
|
|
||||||
constexpr Tessellation(u32 patch_control_points, Maxwell::TessellationPrimitive primitive,
|
|
||||||
Maxwell::TessellationSpacing spacing, bool clockwise)
|
|
||||||
: patch_control_points{patch_control_points}, primitive{primitive}, spacing{spacing},
|
|
||||||
clockwise{clockwise} {}
|
|
||||||
Tessellation() = default;
|
|
||||||
|
|
||||||
u32 patch_control_points;
|
|
||||||
Maxwell::TessellationPrimitive primitive;
|
|
||||||
Maxwell::TessellationSpacing spacing;
|
|
||||||
bool clockwise;
|
|
||||||
|
|
||||||
std::size_t Hash() const noexcept;
|
|
||||||
|
|
||||||
bool operator==(const Tessellation& rhs) const noexcept;
|
|
||||||
|
|
||||||
bool operator!=(const Tessellation& rhs) const noexcept {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rasterizer {
|
struct Rasterizer {
|
||||||
constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool depth_clamp_enable,
|
union {
|
||||||
bool ndc_minus_one_to_one, Maxwell::CullFace cull_face,
|
u32 raw;
|
||||||
Maxwell::FrontFace front_face)
|
BitField<0, 4, u32> topology;
|
||||||
: cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable},
|
BitField<4, 1, u32> primitive_restart_enable;
|
||||||
depth_clamp_enable{depth_clamp_enable}, ndc_minus_one_to_one{ndc_minus_one_to_one},
|
BitField<5, 1, u32> cull_enable;
|
||||||
cull_face{cull_face}, front_face{front_face} {}
|
BitField<6, 1, u32> depth_bias_enable;
|
||||||
Rasterizer() = default;
|
BitField<7, 1, u32> depth_clamp_enable;
|
||||||
|
BitField<8, 1, u32> ndc_minus_one_to_one;
|
||||||
|
BitField<9, 2, u32> cull_face;
|
||||||
|
BitField<11, 1, u32> front_face;
|
||||||
|
BitField<12, 2, u32> polygon_mode;
|
||||||
|
BitField<14, 5, u32> patch_control_points_minus_one;
|
||||||
|
BitField<19, 2, u32> tessellation_primitive;
|
||||||
|
BitField<21, 2, u32> tessellation_spacing;
|
||||||
|
BitField<23, 1, u32> tessellation_clockwise;
|
||||||
|
BitField<24, 1, u32> logic_op_enable;
|
||||||
|
BitField<25, 4, u32> logic_op;
|
||||||
|
};
|
||||||
|
|
||||||
bool cull_enable;
|
// TODO(Rodrigo): Move this to push constants
|
||||||
bool depth_bias_enable;
|
u32 point_size;
|
||||||
bool depth_clamp_enable;
|
|
||||||
bool ndc_minus_one_to_one;
|
void Fill(const Maxwell& regs) noexcept;
|
||||||
Maxwell::CullFace cull_face;
|
|
||||||
Maxwell::FrontFace front_face;
|
|
||||||
|
|
||||||
std::size_t Hash() const noexcept;
|
std::size_t Hash() const noexcept;
|
||||||
|
|
||||||
|
@ -183,7 +163,20 @@ struct FixedPipelineState {
|
||||||
bool operator!=(const Rasterizer& rhs) const noexcept {
|
bool operator!=(const Rasterizer& rhs) const noexcept {
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr Maxwell::PrimitiveTopology Topology() const noexcept {
|
||||||
|
return static_cast<Maxwell::PrimitiveTopology>(topology.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::CullFace CullFace() const noexcept {
|
||||||
|
return UnpackCullFace(cull_face.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::FrontFace FrontFace() const noexcept {
|
||||||
|
return UnpackFrontFace(front_face.Value());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
static_assert(IsHashable<Rasterizer>);
|
||||||
|
|
||||||
struct DepthStencil {
|
struct DepthStencil {
|
||||||
template <std::size_t Position>
|
template <std::size_t Position>
|
||||||
|
@ -257,8 +250,6 @@ struct FixedPipelineState {
|
||||||
};
|
};
|
||||||
|
|
||||||
VertexInput vertex_input;
|
VertexInput vertex_input;
|
||||||
InputAssembly input_assembly;
|
|
||||||
Tessellation tessellation;
|
|
||||||
Rasterizer rasterizer;
|
Rasterizer rasterizer;
|
||||||
DepthStencil depth_stencil;
|
DepthStencil depth_stencil;
|
||||||
ColorBlending color_blending;
|
ColorBlending color_blending;
|
||||||
|
@ -273,8 +264,6 @@ struct FixedPipelineState {
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>);
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>);
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>);
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>);
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>);
|
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::Tessellation>);
|
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>);
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>);
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>);
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>);
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>);
|
static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>);
|
||||||
|
|
|
@ -158,10 +158,8 @@ std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules(
|
||||||
vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params,
|
vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params,
|
||||||
const SPIRVProgram& program) const {
|
const SPIRVProgram& program) const {
|
||||||
const auto& vi = fixed_state.vertex_input;
|
const auto& vi = fixed_state.vertex_input;
|
||||||
const auto& ia = fixed_state.input_assembly;
|
|
||||||
const auto& ds = fixed_state.depth_stencil;
|
const auto& ds = fixed_state.depth_stencil;
|
||||||
const auto& cd = fixed_state.color_blending;
|
const auto& cd = fixed_state.color_blending;
|
||||||
const auto& ts = fixed_state.tessellation;
|
|
||||||
const auto& rs = fixed_state.rasterizer;
|
const auto& rs = fixed_state.rasterizer;
|
||||||
|
|
||||||
std::vector<VkVertexInputBindingDescription> vertex_bindings;
|
std::vector<VkVertexInputBindingDescription> vertex_bindings;
|
||||||
|
@ -226,15 +224,15 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
||||||
input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
input_assembly_ci.pNext = nullptr;
|
input_assembly_ci.pNext = nullptr;
|
||||||
input_assembly_ci.flags = 0;
|
input_assembly_ci.flags = 0;
|
||||||
input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, ia.topology);
|
input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, rs.Topology());
|
||||||
input_assembly_ci.primitiveRestartEnable =
|
input_assembly_ci.primitiveRestartEnable =
|
||||||
ia.primitive_restart_enable && SupportsPrimitiveRestart(input_assembly_ci.topology);
|
rs.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology);
|
||||||
|
|
||||||
VkPipelineTessellationStateCreateInfo tessellation_ci;
|
VkPipelineTessellationStateCreateInfo tessellation_ci;
|
||||||
tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
|
tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
|
||||||
tessellation_ci.pNext = nullptr;
|
tessellation_ci.pNext = nullptr;
|
||||||
tessellation_ci.flags = 0;
|
tessellation_ci.flags = 0;
|
||||||
tessellation_ci.patchControlPoints = ts.patch_control_points;
|
tessellation_ci.patchControlPoints = rs.patch_control_points_minus_one.Value() + 1;
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo viewport_ci;
|
VkPipelineViewportStateCreateInfo viewport_ci;
|
||||||
viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
@ -253,8 +251,8 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
||||||
rasterization_ci.rasterizerDiscardEnable = VK_FALSE;
|
rasterization_ci.rasterizerDiscardEnable = VK_FALSE;
|
||||||
rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL;
|
rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
rasterization_ci.cullMode =
|
rasterization_ci.cullMode =
|
||||||
rs.cull_enable ? MaxwellToVK::CullFace(rs.cull_face) : VK_CULL_MODE_NONE;
|
rs.cull_enable ? MaxwellToVK::CullFace(rs.CullFace()) : VK_CULL_MODE_NONE;
|
||||||
rasterization_ci.frontFace = MaxwellToVK::FrontFace(rs.front_face);
|
rasterization_ci.frontFace = MaxwellToVK::FrontFace(rs.FrontFace());
|
||||||
rasterization_ci.depthBiasEnable = rs.depth_bias_enable;
|
rasterization_ci.depthBiasEnable = rs.depth_bias_enable;
|
||||||
rasterization_ci.depthBiasConstantFactor = 0.0f;
|
rasterization_ci.depthBiasConstantFactor = 0.0f;
|
||||||
rasterization_ci.depthBiasClamp = 0.0f;
|
rasterization_ci.depthBiasClamp = 0.0f;
|
||||||
|
|
|
@ -329,9 +329,9 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
|
||||||
const auto& gpu = system.GPU().Maxwell3D();
|
const auto& gpu = system.GPU().Maxwell3D();
|
||||||
|
|
||||||
Specialization specialization;
|
Specialization specialization;
|
||||||
if (fixed_state.input_assembly.topology == Maxwell::PrimitiveTopology::Points) {
|
if (fixed_state.rasterizer.Topology() == Maxwell::PrimitiveTopology::Points) {
|
||||||
ASSERT(fixed_state.input_assembly.point_size != 0.0f);
|
ASSERT(fixed_state.rasterizer.point_size != 0);
|
||||||
specialization.point_size = fixed_state.input_assembly.point_size;
|
std::memcpy(&specialization.point_size, &fixed_state.rasterizer.point_size, sizeof(u32));
|
||||||
}
|
}
|
||||||
for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
|
for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
|
||||||
specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].Type();
|
specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].Type();
|
||||||
|
|
Loading…
Reference in a new issue