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 rasterizer state
Reduce FixedPipelineState's size to 600 bytes.
This commit is contained in:
		
							parent
							
								
									7790144a55
								
							
						
					
					
						commit
						548dd27f45
					
				@ -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 New Issue
	
	Block a user