fixed_pipeline_state: Pack depth stencil state
Reduce FixedPipelineState's size to 632 bytes.
This commit is contained in:
parent
ab6704f20c
commit
7790144a55
|
@ -12,23 +12,32 @@
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
namespace {
|
void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept {
|
||||||
|
raw = 0;
|
||||||
constexpr FixedPipelineState::DepthStencil GetDepthStencilState(const Maxwell& regs) {
|
front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
|
||||||
const FixedPipelineState::StencilFace front_stencil(
|
front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op_zfail));
|
||||||
regs.stencil_front_op_fail, regs.stencil_front_op_zfail, regs.stencil_front_op_zpass,
|
front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op_zpass));
|
||||||
regs.stencil_front_func_func);
|
front.test_func.Assign(PackComparisonOp(regs.stencil_front_func_func));
|
||||||
const FixedPipelineState::StencilFace back_stencil =
|
if (regs.stencil_two_side_enable) {
|
||||||
regs.stencil_two_side_enable
|
back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op_fail));
|
||||||
? FixedPipelineState::StencilFace(regs.stencil_back_op_fail, regs.stencil_back_op_zfail,
|
back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op_zfail));
|
||||||
regs.stencil_back_op_zpass,
|
back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op_zpass));
|
||||||
regs.stencil_back_func_func)
|
back.test_func.Assign(PackComparisonOp(regs.stencil_back_func_func));
|
||||||
: front_stencil;
|
} else {
|
||||||
return FixedPipelineState::DepthStencil(
|
back.action_stencil_fail.Assign(front.action_stencil_fail);
|
||||||
regs.depth_test_enable == 1, regs.depth_write_enabled == 1, regs.depth_bounds_enable == 1,
|
back.action_depth_fail.Assign(front.action_depth_fail);
|
||||||
regs.stencil_enable == 1, regs.depth_test_func, front_stencil, back_stencil);
|
back.action_depth_pass.Assign(front.action_depth_pass);
|
||||||
|
back.test_func.Assign(front.test_func);
|
||||||
|
}
|
||||||
|
depth_test_enable.Assign(regs.depth_test_enable);
|
||||||
|
depth_write_enable.Assign(regs.depth_write_enabled);
|
||||||
|
depth_bounds_enable.Assign(regs.depth_bounds_enable);
|
||||||
|
stencil_enable.Assign(regs.stencil_enable);
|
||||||
|
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) {
|
constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) {
|
||||||
return FixedPipelineState::InputAssembly(
|
return FixedPipelineState::InputAssembly(
|
||||||
regs.draw.topology, regs.primitive_restart.enabled,
|
regs.draw.topology, regs.primitive_restart.enabled,
|
||||||
|
@ -129,19 +138,6 @@ constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs)
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::size_t FixedPipelineState::StencilFace::Hash() const noexcept {
|
|
||||||
return static_cast<std::size_t>(action_stencil_fail) ^
|
|
||||||
(static_cast<std::size_t>(action_depth_fail) << 4) ^
|
|
||||||
(static_cast<std::size_t>(action_depth_fail) << 20) ^
|
|
||||||
(static_cast<std::size_t>(action_depth_pass) << 36);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FixedPipelineState::StencilFace::operator==(const StencilFace& rhs) const noexcept {
|
|
||||||
return std::tie(action_stencil_fail, action_depth_fail, action_depth_pass, test_func) ==
|
|
||||||
std::tie(rhs.action_stencil_fail, rhs.action_depth_fail, rhs.action_depth_pass,
|
|
||||||
rhs.test_func);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
|
std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
|
||||||
return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^
|
return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^
|
||||||
(static_cast<std::size_t>(src_rgb_func) << 10) ^
|
(static_cast<std::size_t>(src_rgb_func) << 10) ^
|
||||||
|
@ -212,22 +208,11 @@ bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noe
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept {
|
std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept {
|
||||||
std::size_t hash = static_cast<std::size_t>(depth_test_enable) ^
|
return raw;
|
||||||
(static_cast<std::size_t>(depth_write_enable) << 1) ^
|
|
||||||
(static_cast<std::size_t>(depth_bounds_enable) << 2) ^
|
|
||||||
(static_cast<std::size_t>(stencil_enable) << 3) ^
|
|
||||||
(static_cast<std::size_t>(depth_test_function) << 4);
|
|
||||||
boost::hash_combine(hash, front_stencil.Hash());
|
|
||||||
boost::hash_combine(hash, back_stencil.Hash());
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept {
|
bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept {
|
||||||
return std::tie(depth_test_enable, depth_write_enable, depth_bounds_enable, depth_test_function,
|
return raw == rhs.raw;
|
||||||
stencil_enable, front_stencil, back_stencil) ==
|
|
||||||
std::tie(rhs.depth_test_enable, rhs.depth_write_enable, rhs.depth_bounds_enable,
|
|
||||||
rhs.depth_test_function, rhs.stencil_enable, rhs.front_stencil,
|
|
||||||
rhs.back_stencil);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept {
|
std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept {
|
||||||
|
@ -266,9 +251,60 @@ FixedPipelineState GetFixedPipelineState(const Maxwell& regs) {
|
||||||
fixed_state.input_assembly = GetInputAssemblyState(regs);
|
fixed_state.input_assembly = GetInputAssemblyState(regs);
|
||||||
fixed_state.tessellation = GetTessellationState(regs);
|
fixed_state.tessellation = GetTessellationState(regs);
|
||||||
fixed_state.rasterizer = GetRasterizerState(regs);
|
fixed_state.rasterizer = GetRasterizerState(regs);
|
||||||
fixed_state.depth_stencil = GetDepthStencilState(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 FixedPipelineState::PackComparisonOp(Maxwell::ComparisonOp op) noexcept {
|
||||||
|
// OpenGL enums go from 0x200 to 0x207 and the others from 1 to 8
|
||||||
|
// If we substract 0x200 to OpenGL enums and 1 to the others we get a 0-7 range.
|
||||||
|
// Perfect for a hash.
|
||||||
|
const u32 value = static_cast<u32>(op);
|
||||||
|
return value - (value >= 0x200 ? 0x200 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::ComparisonOp FixedPipelineState::UnpackComparisonOp(u32 packed) noexcept {
|
||||||
|
// Read PackComparisonOp for the logic behind this.
|
||||||
|
return static_cast<Maxwell::ComparisonOp>(packed + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp op) noexcept {
|
||||||
|
switch (op) {
|
||||||
|
case Maxwell::StencilOp::Keep:
|
||||||
|
case Maxwell::StencilOp::KeepOGL:
|
||||||
|
return 0;
|
||||||
|
case Maxwell::StencilOp::Zero:
|
||||||
|
case Maxwell::StencilOp::ZeroOGL:
|
||||||
|
return 1;
|
||||||
|
case Maxwell::StencilOp::Replace:
|
||||||
|
case Maxwell::StencilOp::ReplaceOGL:
|
||||||
|
return 2;
|
||||||
|
case Maxwell::StencilOp::Incr:
|
||||||
|
case Maxwell::StencilOp::IncrOGL:
|
||||||
|
return 3;
|
||||||
|
case Maxwell::StencilOp::Decr:
|
||||||
|
case Maxwell::StencilOp::DecrOGL:
|
||||||
|
return 4;
|
||||||
|
case Maxwell::StencilOp::Invert:
|
||||||
|
case Maxwell::StencilOp::InvertOGL:
|
||||||
|
return 5;
|
||||||
|
case Maxwell::StencilOp::IncrWrap:
|
||||||
|
case Maxwell::StencilOp::IncrWrapOGL:
|
||||||
|
return 6;
|
||||||
|
case Maxwell::StencilOp::DecrWrap:
|
||||||
|
case Maxwell::StencilOp::DecrWrapOGL:
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::StencilOp FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
|
||||||
|
static constexpr std::array LUT = {Maxwell::StencilOp::Keep, Maxwell::StencilOp::Zero,
|
||||||
|
Maxwell::StencilOp::Replace, Maxwell::StencilOp::Incr,
|
||||||
|
Maxwell::StencilOp::Decr, Maxwell::StencilOp::Invert,
|
||||||
|
Maxwell::StencilOp::IncrWrap, Maxwell::StencilOp::DecrWrap};
|
||||||
|
return LUT[packed];
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -24,27 +24,11 @@ inline constexpr bool IsHashable = std::has_unique_object_representations_v<T>&&
|
||||||
std::is_trivially_copyable_v<T>&& std::is_trivially_constructible_v<T>;
|
std::is_trivially_copyable_v<T>&& std::is_trivially_constructible_v<T>;
|
||||||
|
|
||||||
struct FixedPipelineState {
|
struct FixedPipelineState {
|
||||||
struct StencilFace {
|
static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
|
||||||
constexpr StencilFace(Maxwell::StencilOp action_stencil_fail,
|
static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
|
||||||
Maxwell::StencilOp action_depth_fail,
|
|
||||||
Maxwell::StencilOp action_depth_pass, Maxwell::ComparisonOp test_func)
|
|
||||||
: action_stencil_fail{action_stencil_fail}, action_depth_fail{action_depth_fail},
|
|
||||||
action_depth_pass{action_depth_pass}, test_func{test_func} {}
|
|
||||||
StencilFace() = default;
|
|
||||||
|
|
||||||
Maxwell::StencilOp action_stencil_fail;
|
static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
|
||||||
Maxwell::StencilOp action_depth_fail;
|
static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
|
||||||
Maxwell::StencilOp action_depth_pass;
|
|
||||||
Maxwell::ComparisonOp test_func;
|
|
||||||
|
|
||||||
std::size_t Hash() const noexcept;
|
|
||||||
|
|
||||||
bool operator==(const StencilFace& rhs) const noexcept;
|
|
||||||
|
|
||||||
bool operator!=(const StencilFace& rhs) const noexcept {
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlendingAttachment {
|
struct BlendingAttachment {
|
||||||
constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
|
constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
|
||||||
|
@ -202,23 +186,42 @@ struct FixedPipelineState {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DepthStencil {
|
struct DepthStencil {
|
||||||
constexpr DepthStencil(bool depth_test_enable, bool depth_write_enable,
|
template <std::size_t Position>
|
||||||
bool depth_bounds_enable, bool stencil_enable,
|
union StencilFace {
|
||||||
Maxwell::ComparisonOp depth_test_function, StencilFace front_stencil,
|
BitField<Position + 0, 3, u32> action_stencil_fail;
|
||||||
StencilFace back_stencil)
|
BitField<Position + 3, 3, u32> action_depth_fail;
|
||||||
: depth_test_enable{depth_test_enable}, depth_write_enable{depth_write_enable},
|
BitField<Position + 6, 3, u32> action_depth_pass;
|
||||||
depth_bounds_enable{depth_bounds_enable}, stencil_enable{stencil_enable},
|
BitField<Position + 9, 3, u32> test_func;
|
||||||
depth_test_function{depth_test_function}, front_stencil{front_stencil},
|
|
||||||
back_stencil{back_stencil} {}
|
|
||||||
DepthStencil() = default;
|
|
||||||
|
|
||||||
bool depth_test_enable;
|
Maxwell::StencilOp ActionStencilFail() const noexcept {
|
||||||
bool depth_write_enable;
|
return UnpackStencilOp(action_stencil_fail);
|
||||||
bool depth_bounds_enable;
|
}
|
||||||
bool stencil_enable;
|
|
||||||
Maxwell::ComparisonOp depth_test_function;
|
Maxwell::StencilOp ActionDepthFail() const noexcept {
|
||||||
StencilFace front_stencil;
|
return UnpackStencilOp(action_depth_fail);
|
||||||
StencilFace back_stencil;
|
}
|
||||||
|
|
||||||
|
Maxwell::StencilOp ActionDepthPass() const noexcept {
|
||||||
|
return UnpackStencilOp(action_depth_pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maxwell::ComparisonOp TestFunc() const noexcept {
|
||||||
|
return UnpackComparisonOp(test_func);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 raw;
|
||||||
|
StencilFace<0> front;
|
||||||
|
StencilFace<12> back;
|
||||||
|
BitField<24, 1, u32> depth_test_enable;
|
||||||
|
BitField<25, 1, u32> depth_write_enable;
|
||||||
|
BitField<26, 1, u32> depth_bounds_enable;
|
||||||
|
BitField<27, 1, u32> stencil_enable;
|
||||||
|
BitField<28, 3, u32> depth_test_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Fill(const Maxwell& regs) noexcept;
|
||||||
|
|
||||||
std::size_t Hash() const noexcept;
|
std::size_t Hash() const noexcept;
|
||||||
|
|
||||||
|
@ -227,7 +230,12 @@ struct FixedPipelineState {
|
||||||
bool operator!=(const DepthStencil& rhs) const noexcept {
|
bool operator!=(const DepthStencil& rhs) const noexcept {
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maxwell::ComparisonOp DepthTestFunc() const noexcept {
|
||||||
|
return UnpackComparisonOp(depth_test_func);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
static_assert(IsHashable<DepthStencil>);
|
||||||
|
|
||||||
struct ColorBlending {
|
struct ColorBlending {
|
||||||
constexpr ColorBlending(
|
constexpr ColorBlending(
|
||||||
|
@ -248,6 +256,13 @@ struct FixedPipelineState {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VertexInput vertex_input;
|
||||||
|
InputAssembly input_assembly;
|
||||||
|
Tessellation tessellation;
|
||||||
|
Rasterizer rasterizer;
|
||||||
|
DepthStencil depth_stencil;
|
||||||
|
ColorBlending color_blending;
|
||||||
|
|
||||||
std::size_t Hash() const noexcept;
|
std::size_t Hash() const noexcept;
|
||||||
|
|
||||||
bool operator==(const FixedPipelineState& rhs) const noexcept;
|
bool operator==(const FixedPipelineState& rhs) const noexcept;
|
||||||
|
@ -255,15 +270,7 @@ struct FixedPipelineState {
|
||||||
bool operator!=(const FixedPipelineState& rhs) const noexcept {
|
bool operator!=(const FixedPipelineState& rhs) const noexcept {
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexInput vertex_input;
|
|
||||||
InputAssembly input_assembly;
|
|
||||||
Tessellation tessellation;
|
|
||||||
Rasterizer rasterizer;
|
|
||||||
DepthStencil depth_stencil;
|
|
||||||
ColorBlending color_blending;
|
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>);
|
|
||||||
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::InputAssembly>);
|
||||||
|
|
|
@ -26,12 +26,13 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
VkStencilOpState GetStencilFaceState(const FixedPipelineState::StencilFace& face) {
|
template <class StencilFace>
|
||||||
|
VkStencilOpState GetStencilFaceState(const StencilFace& face) {
|
||||||
VkStencilOpState state;
|
VkStencilOpState state;
|
||||||
state.failOp = MaxwellToVK::StencilOp(face.action_stencil_fail);
|
state.failOp = MaxwellToVK::StencilOp(face.ActionStencilFail());
|
||||||
state.passOp = MaxwellToVK::StencilOp(face.action_depth_pass);
|
state.passOp = MaxwellToVK::StencilOp(face.ActionDepthPass());
|
||||||
state.depthFailOp = MaxwellToVK::StencilOp(face.action_depth_fail);
|
state.depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail());
|
||||||
state.compareOp = MaxwellToVK::ComparisonOp(face.test_func);
|
state.compareOp = MaxwellToVK::ComparisonOp(face.TestFunc());
|
||||||
state.compareMask = 0;
|
state.compareMask = 0;
|
||||||
state.writeMask = 0;
|
state.writeMask = 0;
|
||||||
state.reference = 0;
|
state.reference = 0;
|
||||||
|
@ -277,13 +278,12 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
||||||
depth_stencil_ci.flags = 0;
|
depth_stencil_ci.flags = 0;
|
||||||
depth_stencil_ci.depthTestEnable = ds.depth_test_enable;
|
depth_stencil_ci.depthTestEnable = ds.depth_test_enable;
|
||||||
depth_stencil_ci.depthWriteEnable = ds.depth_write_enable;
|
depth_stencil_ci.depthWriteEnable = ds.depth_write_enable;
|
||||||
depth_stencil_ci.depthCompareOp = ds.depth_test_enable
|
depth_stencil_ci.depthCompareOp =
|
||||||
? MaxwellToVK::ComparisonOp(ds.depth_test_function)
|
ds.depth_test_enable ? MaxwellToVK::ComparisonOp(ds.DepthTestFunc()) : VK_COMPARE_OP_ALWAYS;
|
||||||
: VK_COMPARE_OP_ALWAYS;
|
|
||||||
depth_stencil_ci.depthBoundsTestEnable = ds.depth_bounds_enable;
|
depth_stencil_ci.depthBoundsTestEnable = ds.depth_bounds_enable;
|
||||||
depth_stencil_ci.stencilTestEnable = ds.stencil_enable;
|
depth_stencil_ci.stencilTestEnable = ds.stencil_enable;
|
||||||
depth_stencil_ci.front = GetStencilFaceState(ds.front_stencil);
|
depth_stencil_ci.front = GetStencilFaceState(ds.front);
|
||||||
depth_stencil_ci.back = GetStencilFaceState(ds.back_stencil);
|
depth_stencil_ci.back = GetStencilFaceState(ds.back);
|
||||||
depth_stencil_ci.minDepthBounds = 0.0f;
|
depth_stencil_ci.minDepthBounds = 0.0f;
|
||||||
depth_stencil_ci.maxDepthBounds = 0.0f;
|
depth_stencil_ci.maxDepthBounds = 0.0f;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue