mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	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 {
 | 
			
		||||
 | 
			
		||||
constexpr FixedPipelineState::DepthStencil GetDepthStencilState(const Maxwell& regs) {
 | 
			
		||||
    const FixedPipelineState::StencilFace front_stencil(
 | 
			
		||||
        regs.stencil_front_op_fail, regs.stencil_front_op_zfail, regs.stencil_front_op_zpass,
 | 
			
		||||
        regs.stencil_front_func_func);
 | 
			
		||||
    const FixedPipelineState::StencilFace back_stencil =
 | 
			
		||||
        regs.stencil_two_side_enable
 | 
			
		||||
            ? FixedPipelineState::StencilFace(regs.stencil_back_op_fail, regs.stencil_back_op_zfail,
 | 
			
		||||
                                              regs.stencil_back_op_zpass,
 | 
			
		||||
                                              regs.stencil_back_func_func)
 | 
			
		||||
            : front_stencil;
 | 
			
		||||
    return FixedPipelineState::DepthStencil(
 | 
			
		||||
        regs.depth_test_enable == 1, regs.depth_write_enabled == 1, regs.depth_bounds_enable == 1,
 | 
			
		||||
        regs.stencil_enable == 1, regs.depth_test_func, front_stencil, back_stencil);
 | 
			
		||||
void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept {
 | 
			
		||||
    raw = 0;
 | 
			
		||||
    front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
 | 
			
		||||
    front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op_zfail));
 | 
			
		||||
    front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op_zpass));
 | 
			
		||||
    front.test_func.Assign(PackComparisonOp(regs.stencil_front_func_func));
 | 
			
		||||
    if (regs.stencil_two_side_enable) {
 | 
			
		||||
        back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op_fail));
 | 
			
		||||
        back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op_zfail));
 | 
			
		||||
        back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op_zpass));
 | 
			
		||||
        back.test_func.Assign(PackComparisonOp(regs.stencil_back_func_func));
 | 
			
		||||
    } else {
 | 
			
		||||
        back.action_stencil_fail.Assign(front.action_stencil_fail);
 | 
			
		||||
        back.action_depth_fail.Assign(front.action_depth_fail);
 | 
			
		||||
        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) {
 | 
			
		||||
    return FixedPipelineState::InputAssembly(
 | 
			
		||||
        regs.draw.topology, regs.primitive_restart.enabled,
 | 
			
		||||
@ -129,19 +138,6 @@ constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs)
 | 
			
		||||
 | 
			
		||||
} // 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 {
 | 
			
		||||
    return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^
 | 
			
		||||
           (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 hash = static_cast<std::size_t>(depth_test_enable) ^
 | 
			
		||||
                       (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;
 | 
			
		||||
    return raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept {
 | 
			
		||||
    return std::tie(depth_test_enable, depth_write_enable, depth_bounds_enable, depth_test_function,
 | 
			
		||||
                    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);
 | 
			
		||||
    return raw == rhs.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.tessellation = GetTessellationState(regs);
 | 
			
		||||
    fixed_state.rasterizer = GetRasterizerState(regs);
 | 
			
		||||
    fixed_state.depth_stencil = GetDepthStencilState(regs);
 | 
			
		||||
    fixed_state.depth_stencil.Fill(regs);
 | 
			
		||||
    fixed_state.color_blending = GetColorBlendingState(regs);
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -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>;
 | 
			
		||||
 | 
			
		||||
struct FixedPipelineState {
 | 
			
		||||
    struct StencilFace {
 | 
			
		||||
        constexpr StencilFace(Maxwell::StencilOp action_stencil_fail,
 | 
			
		||||
                              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;
 | 
			
		||||
    static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
 | 
			
		||||
    static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
 | 
			
		||||
 | 
			
		||||
        Maxwell::StencilOp action_stencil_fail;
 | 
			
		||||
        Maxwell::StencilOp action_depth_fail;
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
 | 
			
		||||
    static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
 | 
			
		||||
 | 
			
		||||
    struct BlendingAttachment {
 | 
			
		||||
        constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
 | 
			
		||||
@ -202,23 +186,42 @@ struct FixedPipelineState {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct DepthStencil {
 | 
			
		||||
        constexpr DepthStencil(bool depth_test_enable, bool depth_write_enable,
 | 
			
		||||
                               bool depth_bounds_enable, bool stencil_enable,
 | 
			
		||||
                               Maxwell::ComparisonOp depth_test_function, StencilFace front_stencil,
 | 
			
		||||
                               StencilFace back_stencil)
 | 
			
		||||
            : depth_test_enable{depth_test_enable}, depth_write_enable{depth_write_enable},
 | 
			
		||||
              depth_bounds_enable{depth_bounds_enable}, stencil_enable{stencil_enable},
 | 
			
		||||
              depth_test_function{depth_test_function}, front_stencil{front_stencil},
 | 
			
		||||
              back_stencil{back_stencil} {}
 | 
			
		||||
        DepthStencil() = default;
 | 
			
		||||
        template <std::size_t Position>
 | 
			
		||||
        union StencilFace {
 | 
			
		||||
            BitField<Position + 0, 3, u32> action_stencil_fail;
 | 
			
		||||
            BitField<Position + 3, 3, u32> action_depth_fail;
 | 
			
		||||
            BitField<Position + 6, 3, u32> action_depth_pass;
 | 
			
		||||
            BitField<Position + 9, 3, u32> test_func;
 | 
			
		||||
 | 
			
		||||
        bool depth_test_enable;
 | 
			
		||||
        bool depth_write_enable;
 | 
			
		||||
        bool depth_bounds_enable;
 | 
			
		||||
        bool stencil_enable;
 | 
			
		||||
        Maxwell::ComparisonOp depth_test_function;
 | 
			
		||||
        StencilFace front_stencil;
 | 
			
		||||
        StencilFace back_stencil;
 | 
			
		||||
            Maxwell::StencilOp ActionStencilFail() const noexcept {
 | 
			
		||||
                return UnpackStencilOp(action_stencil_fail);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Maxwell::StencilOp ActionDepthFail() const noexcept {
 | 
			
		||||
                return UnpackStencilOp(action_depth_fail);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
 | 
			
		||||
@ -227,7 +230,12 @@ struct FixedPipelineState {
 | 
			
		||||
        bool operator!=(const DepthStencil& rhs) const noexcept {
 | 
			
		||||
            return !operator==(rhs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Maxwell::ComparisonOp DepthTestFunc() const noexcept {
 | 
			
		||||
            return UnpackComparisonOp(depth_test_func);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(IsHashable<DepthStencil>);
 | 
			
		||||
 | 
			
		||||
    struct 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;
 | 
			
		||||
 | 
			
		||||
    bool operator==(const FixedPipelineState& rhs) const noexcept;
 | 
			
		||||
@ -255,15 +270,7 @@ struct FixedPipelineState {
 | 
			
		||||
    bool operator!=(const FixedPipelineState& rhs) const noexcept {
 | 
			
		||||
        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::VertexInput>);
 | 
			
		||||
static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>);
 | 
			
		||||
 | 
			
		||||
@ -26,12 +26,13 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache);
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
VkStencilOpState GetStencilFaceState(const FixedPipelineState::StencilFace& face) {
 | 
			
		||||
template <class StencilFace>
 | 
			
		||||
VkStencilOpState GetStencilFaceState(const StencilFace& face) {
 | 
			
		||||
    VkStencilOpState state;
 | 
			
		||||
    state.failOp = MaxwellToVK::StencilOp(face.action_stencil_fail);
 | 
			
		||||
    state.passOp = MaxwellToVK::StencilOp(face.action_depth_pass);
 | 
			
		||||
    state.depthFailOp = MaxwellToVK::StencilOp(face.action_depth_fail);
 | 
			
		||||
    state.compareOp = MaxwellToVK::ComparisonOp(face.test_func);
 | 
			
		||||
    state.failOp = MaxwellToVK::StencilOp(face.ActionStencilFail());
 | 
			
		||||
    state.passOp = MaxwellToVK::StencilOp(face.ActionDepthPass());
 | 
			
		||||
    state.depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail());
 | 
			
		||||
    state.compareOp = MaxwellToVK::ComparisonOp(face.TestFunc());
 | 
			
		||||
    state.compareMask = 0;
 | 
			
		||||
    state.writeMask = 0;
 | 
			
		||||
    state.reference = 0;
 | 
			
		||||
@ -277,13 +278,12 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
 | 
			
		||||
    depth_stencil_ci.flags = 0;
 | 
			
		||||
    depth_stencil_ci.depthTestEnable = ds.depth_test_enable;
 | 
			
		||||
    depth_stencil_ci.depthWriteEnable = ds.depth_write_enable;
 | 
			
		||||
    depth_stencil_ci.depthCompareOp = ds.depth_test_enable
 | 
			
		||||
                                          ? MaxwellToVK::ComparisonOp(ds.depth_test_function)
 | 
			
		||||
                                          : VK_COMPARE_OP_ALWAYS;
 | 
			
		||||
    depth_stencil_ci.depthCompareOp =
 | 
			
		||||
        ds.depth_test_enable ? MaxwellToVK::ComparisonOp(ds.DepthTestFunc()) : VK_COMPARE_OP_ALWAYS;
 | 
			
		||||
    depth_stencil_ci.depthBoundsTestEnable = ds.depth_bounds_enable;
 | 
			
		||||
    depth_stencil_ci.stencilTestEnable = ds.stencil_enable;
 | 
			
		||||
    depth_stencil_ci.front = GetStencilFaceState(ds.front_stencil);
 | 
			
		||||
    depth_stencil_ci.back = GetStencilFaceState(ds.back_stencil);
 | 
			
		||||
    depth_stencil_ci.front = GetStencilFaceState(ds.front);
 | 
			
		||||
    depth_stencil_ci.back = GetStencilFaceState(ds.back);
 | 
			
		||||
    depth_stencil_ci.minDepthBounds = 0.0f;
 | 
			
		||||
    depth_stencil_ci.maxDepthBounds = 0.0f;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user