Просмотр исходного кода

fixed_pipeline_state: Pack rasterizer state

Reduce FixedPipelineState's size to 600 bytes.
ReinUsesLisp 6 лет назад
Родитель
Сommit
548dd27f45

+ 102 - 97
src/video_core/renderer_vulkan/fixed_pipeline_state.cpp

@@ -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());
+
+    u32 packed_front_face = PackFrontFace(regs.front_face);
+    if (regs.screen_y_control.triangle_rast_flip != 0 &&
+        regs.viewport_transform[0].scale_y > 0.0f) {
+        // Flip front face
+        packed_front_face = 1 - packed_front_face;
+    }
 
 
-constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) {
-    return FixedPipelineState::InputAssembly(
-        regs.draw.topology, regs.primitive_restart.enabled,
-        regs.draw.topology == Maxwell::PrimitiveTopology::Points ? regs.point_size : 0.0f);
+    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, &regs.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) ^
-           (static_cast<std::size_t>(depth_bias_enable) << 1) ^
-           (static_cast<std::size_t>(depth_clamp_enable) << 2) ^
-           (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);
+    u64 hash = static_cast<u64>(raw) << 32;
+    std::memcpy(&hash, &point_size, sizeof(u32));
+    return static_cast<std::size_t>(hash);
 }
 }
 
 
 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,
-                    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);
+    return raw == rhs.raw && point_size == rhs.point_size;
 }
 }
 
 
 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,
-                    color_blending) == std::tie(rhs.vertex_input, rhs.input_assembly,
-                                                rhs.tessellation, rhs.rasterizer, rhs.depth_stencil,
-                                                rhs.color_blending);
+    return std::tie(vertex_input, rasterizer, depth_stencil, color_blending) ==
+           std::tie(rhs.vertex_input, 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.tessellation = GetTessellationState(regs);
-    fixed_state.rasterizer = GetRasterizerState(regs);
+    fixed_state.rasterizer.Fill(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

+ 45 - 56
src/video_core/renderer_vulkan/fixed_pipeline_state.h

@@ -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,71 +131,52 @@ 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 Rasterizer {
+        union {
+            u32 raw;
+            BitField<0, 4, u32> topology;
+            BitField<4, 1, u32> primitive_restart_enable;
+            BitField<5, 1, u32> cull_enable;
+            BitField<6, 1, u32> depth_bias_enable;
+            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;
+        };
 
 
-    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;
+        // TODO(Rodrigo): Move this to push constants
+        u32 point_size;
 
 
-        u32 patch_control_points;
-        Maxwell::TessellationPrimitive primitive;
-        Maxwell::TessellationSpacing spacing;
-        bool clockwise;
+        void Fill(const Maxwell& regs) noexcept;
 
 
         std::size_t Hash() const noexcept;
         std::size_t Hash() const noexcept;
 
 
-        bool operator==(const Tessellation& rhs) const noexcept;
+        bool operator==(const Rasterizer& rhs) const noexcept;
 
 
-        bool operator!=(const Tessellation& rhs) const noexcept {
+        bool operator!=(const Rasterizer& rhs) const noexcept {
             return !operator==(rhs);
             return !operator==(rhs);
         }
         }
-    };
-
-    struct Rasterizer {
-        constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool depth_clamp_enable,
-                             bool ndc_minus_one_to_one, Maxwell::CullFace cull_face,
-                             Maxwell::FrontFace front_face)
-            : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable},
-              depth_clamp_enable{depth_clamp_enable}, ndc_minus_one_to_one{ndc_minus_one_to_one},
-              cull_face{cull_face}, front_face{front_face} {}
-        Rasterizer() = default;
-
-        bool cull_enable;
-        bool depth_bias_enable;
-        bool depth_clamp_enable;
-        bool ndc_minus_one_to_one;
-        Maxwell::CullFace cull_face;
-        Maxwell::FrontFace front_face;
 
 
-        std::size_t Hash() const noexcept;
+        constexpr Maxwell::PrimitiveTopology Topology() const noexcept {
+            return static_cast<Maxwell::PrimitiveTopology>(topology.Value());
+        }
 
 
-        bool operator==(const Rasterizer& rhs) const noexcept;
+        Maxwell::CullFace CullFace() const noexcept {
+            return UnpackCullFace(cull_face.Value());
+        }
 
 
-        bool operator!=(const Rasterizer& rhs) const noexcept {
-            return !operator==(rhs);
+        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>);

+ 5 - 7
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@@ -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;
-    rasterization_ci.frontFace = MaxwellToVK::FrontFace(rs.front_face);
+        rs.cull_enable ? MaxwellToVK::CullFace(rs.CullFace()) : VK_CULL_MODE_NONE;
+    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;

+ 3 - 3
src/video_core/renderer_vulkan/vk_pipeline_cache.cpp

@@ -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) {
-        ASSERT(fixed_state.input_assembly.point_size != 0.0f);
-        specialization.point_size = fixed_state.input_assembly.point_size;
+    if (fixed_state.rasterizer.Topology() == Maxwell::PrimitiveTopology::Points) {
+        ASSERT(fixed_state.rasterizer.point_size != 0);
+        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();