diff options
| author | 2020-04-18 04:03:29 -0300 | |
|---|---|---|
| committer | 2020-04-18 19:22:57 -0300 | |
| commit | 548dd27f4567f751d54073f1408d6f8949344fa9 (patch) | |
| tree | b77bdf3235fb45bac3e6fee37d5728054b7dd5ef | |
| parent | fixed_pipeline_state: Pack depth stencil state (diff) | |
| download | yuzu-548dd27f4567f751d54073f1408d6f8949344fa9.tar.gz yuzu-548dd27f4567f751d54073f1408d6f8949344fa9.tar.xz yuzu-548dd27f4567f751d54073f1408d6f8949344fa9.zip | |
fixed_pipeline_state: Pack rasterizer state
Reduce FixedPipelineState's size to 600 bytes.
Diffstat (limited to '')
4 files changed, 155 insertions, 163 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 8734045e5..1a23de07f 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 5 | #include <tuple> | 6 | #include <tuple> |
| 6 | 7 | ||
| 7 | #include <boost/functional/hash.hpp> | 8 | #include <boost/functional/hash.hpp> |
| @@ -12,6 +13,31 @@ | |||
| 12 | 13 | ||
| 13 | namespace Vulkan { | 14 | namespace Vulkan { |
| 14 | 15 | ||
| 16 | namespace { | ||
| 17 | |||
| 18 | constexpr std::size_t POINT = 0; | ||
| 19 | constexpr std::size_t LINE = 1; | ||
| 20 | constexpr std::size_t POLYGON = 2; | ||
| 21 | constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { | ||
| 22 | POINT, // Points | ||
| 23 | LINE, // Lines | ||
| 24 | LINE, // LineLoop | ||
| 25 | LINE, // LineStrip | ||
| 26 | POLYGON, // Triangles | ||
| 27 | POLYGON, // TriangleStrip | ||
| 28 | POLYGON, // TriangleFan | ||
| 29 | POLYGON, // Quads | ||
| 30 | POLYGON, // QuadStrip | ||
| 31 | POLYGON, // Polygon | ||
| 32 | LINE, // LinesAdjacency | ||
| 33 | LINE, // LineStripAdjacency | ||
| 34 | POLYGON, // TrianglesAdjacency | ||
| 35 | POLYGON, // TriangleStripAdjacency | ||
| 36 | POLYGON, // Patches | ||
| 37 | }; | ||
| 38 | |||
| 39 | } // Anonymous namespace | ||
| 40 | |||
| 15 | void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept { | 41 | void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept { |
| 16 | raw = 0; | 42 | raw = 0; |
| 17 | front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail)); | 43 | front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail)); |
| @@ -36,14 +62,41 @@ void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept { | |||
| 36 | depth_test_func.Assign(PackComparisonOp(regs.depth_test_func)); | 62 | depth_test_func.Assign(PackComparisonOp(regs.depth_test_func)); |
| 37 | } | 63 | } |
| 38 | 64 | ||
| 39 | namespace { | 65 | void FixedPipelineState::Rasterizer::Fill(const Maxwell& regs) noexcept { |
| 66 | const auto& clip = regs.view_volume_clip_control; | ||
| 67 | const std::array enabled_lut = {regs.polygon_offset_point_enable, | ||
| 68 | regs.polygon_offset_line_enable, | ||
| 69 | regs.polygon_offset_fill_enable}; | ||
| 70 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); | ||
| 71 | |||
| 72 | u32 packed_front_face = PackFrontFace(regs.front_face); | ||
| 73 | if (regs.screen_y_control.triangle_rast_flip != 0 && | ||
| 74 | regs.viewport_transform[0].scale_y > 0.0f) { | ||
| 75 | // Flip front face | ||
| 76 | packed_front_face = 1 - packed_front_face; | ||
| 77 | } | ||
| 40 | 78 | ||
| 41 | constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) { | 79 | raw = 0; |
| 42 | return FixedPipelineState::InputAssembly( | 80 | topology.Assign(topology_index); |
| 43 | regs.draw.topology, regs.primitive_restart.enabled, | 81 | primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0); |
| 44 | regs.draw.topology == Maxwell::PrimitiveTopology::Points ? regs.point_size : 0.0f); | 82 | cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0); |
| 83 | depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0); | ||
| 84 | depth_clamp_enable.Assign(clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1 ? 1 : 0); | ||
| 85 | ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0); | ||
| 86 | cull_face.Assign(PackCullFace(regs.cull_face)); | ||
| 87 | front_face.Assign(packed_front_face); | ||
| 88 | polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front)); | ||
| 89 | patch_control_points_minus_one.Assign(regs.patch_vertices - 1); | ||
| 90 | tessellation_primitive.Assign(static_cast<u32>(regs.tess_mode.prim.Value())); | ||
| 91 | tessellation_spacing.Assign(static_cast<u32>(regs.tess_mode.spacing.Value())); | ||
| 92 | tessellation_clockwise.Assign(regs.tess_mode.cw.Value()); | ||
| 93 | logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0); | ||
| 94 | logic_op.Assign(PackLogicOp(regs.logic_op.operation)); | ||
| 95 | std::memcpy(&point_size, ®s.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast | ||
| 45 | } | 96 | } |
| 46 | 97 | ||
| 98 | namespace { | ||
| 99 | |||
| 47 | constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState( | 100 | constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState( |
| 48 | const Maxwell& regs, std::size_t render_target) { | 101 | const Maxwell& regs, std::size_t render_target) { |
| 49 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target]; | 102 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target]; |
| @@ -86,56 +139,6 @@ constexpr FixedPipelineState::ColorBlending GetColorBlendingState(const Maxwell& | |||
| 86 | GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)}); | 139 | GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)}); |
| 87 | } | 140 | } |
| 88 | 141 | ||
| 89 | constexpr FixedPipelineState::Tessellation GetTessellationState(const Maxwell& regs) { | ||
| 90 | return FixedPipelineState::Tessellation(regs.patch_vertices, regs.tess_mode.prim, | ||
| 91 | regs.tess_mode.spacing, regs.tess_mode.cw != 0); | ||
| 92 | } | ||
| 93 | |||
| 94 | constexpr std::size_t Point = 0; | ||
| 95 | constexpr std::size_t Line = 1; | ||
| 96 | constexpr std::size_t Polygon = 2; | ||
| 97 | constexpr std::array PolygonOffsetEnableLUT = { | ||
| 98 | Point, // Points | ||
| 99 | Line, // Lines | ||
| 100 | Line, // LineLoop | ||
| 101 | Line, // LineStrip | ||
| 102 | Polygon, // Triangles | ||
| 103 | Polygon, // TriangleStrip | ||
| 104 | Polygon, // TriangleFan | ||
| 105 | Polygon, // Quads | ||
| 106 | Polygon, // QuadStrip | ||
| 107 | Polygon, // Polygon | ||
| 108 | Line, // LinesAdjacency | ||
| 109 | Line, // LineStripAdjacency | ||
| 110 | Polygon, // TrianglesAdjacency | ||
| 111 | Polygon, // TriangleStripAdjacency | ||
| 112 | Polygon, // Patches | ||
| 113 | }; | ||
| 114 | |||
| 115 | constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs) { | ||
| 116 | const std::array enabled_lut = {regs.polygon_offset_point_enable, | ||
| 117 | regs.polygon_offset_line_enable, | ||
| 118 | regs.polygon_offset_fill_enable}; | ||
| 119 | const auto topology = static_cast<std::size_t>(regs.draw.topology.Value()); | ||
| 120 | const bool depth_bias_enabled = enabled_lut[PolygonOffsetEnableLUT[topology]]; | ||
| 121 | |||
| 122 | const auto& clip = regs.view_volume_clip_control; | ||
| 123 | const bool depth_clamp_enabled = clip.depth_clamp_near == 1 || clip.depth_clamp_far == 1; | ||
| 124 | |||
| 125 | Maxwell::FrontFace front_face = regs.front_face; | ||
| 126 | if (regs.screen_y_control.triangle_rast_flip != 0 && | ||
| 127 | regs.viewport_transform[0].scale_y > 0.0f) { | ||
| 128 | if (front_face == Maxwell::FrontFace::CounterClockWise) | ||
| 129 | front_face = Maxwell::FrontFace::ClockWise; | ||
| 130 | else if (front_face == Maxwell::FrontFace::ClockWise) | ||
| 131 | front_face = Maxwell::FrontFace::CounterClockWise; | ||
| 132 | } | ||
| 133 | |||
| 134 | const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; | ||
| 135 | return FixedPipelineState::Rasterizer(regs.cull_test_enabled, depth_bias_enabled, | ||
| 136 | depth_clamp_enabled, gl_ndc, regs.cull_face, front_face); | ||
| 137 | } | ||
| 138 | |||
| 139 | } // Anonymous namespace | 142 | } // Anonymous namespace |
| 140 | 143 | ||
| 141 | std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept { | 144 | std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept { |
| @@ -168,43 +171,14 @@ bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const n | |||
| 168 | return std::memcmp(this, &rhs, sizeof *this) == 0; | 171 | return std::memcmp(this, &rhs, sizeof *this) == 0; |
| 169 | } | 172 | } |
| 170 | 173 | ||
| 171 | std::size_t FixedPipelineState::InputAssembly::Hash() const noexcept { | ||
| 172 | std::size_t point_size_int = 0; | ||
| 173 | std::memcpy(&point_size_int, &point_size, sizeof(point_size)); | ||
| 174 | return (static_cast<std::size_t>(topology) << 24) ^ (point_size_int << 32) ^ | ||
| 175 | static_cast<std::size_t>(primitive_restart_enable); | ||
| 176 | } | ||
| 177 | |||
| 178 | bool FixedPipelineState::InputAssembly::operator==(const InputAssembly& rhs) const noexcept { | ||
| 179 | return std::tie(topology, primitive_restart_enable, point_size) == | ||
| 180 | std::tie(rhs.topology, rhs.primitive_restart_enable, rhs.point_size); | ||
| 181 | } | ||
| 182 | |||
| 183 | std::size_t FixedPipelineState::Tessellation::Hash() const noexcept { | ||
| 184 | return static_cast<std::size_t>(patch_control_points) ^ | ||
| 185 | (static_cast<std::size_t>(primitive) << 6) ^ (static_cast<std::size_t>(spacing) << 8) ^ | ||
| 186 | (static_cast<std::size_t>(clockwise) << 10); | ||
| 187 | } | ||
| 188 | |||
| 189 | bool FixedPipelineState::Tessellation::operator==(const Tessellation& rhs) const noexcept { | ||
| 190 | return std::tie(patch_control_points, primitive, spacing, clockwise) == | ||
| 191 | std::tie(rhs.patch_control_points, rhs.primitive, rhs.spacing, rhs.clockwise); | ||
| 192 | } | ||
| 193 | |||
| 194 | std::size_t FixedPipelineState::Rasterizer::Hash() const noexcept { | 174 | std::size_t FixedPipelineState::Rasterizer::Hash() const noexcept { |
| 195 | return static_cast<std::size_t>(cull_enable) ^ | 175 | u64 hash = static_cast<u64>(raw) << 32; |
| 196 | (static_cast<std::size_t>(depth_bias_enable) << 1) ^ | 176 | std::memcpy(&hash, &point_size, sizeof(u32)); |
| 197 | (static_cast<std::size_t>(depth_clamp_enable) << 2) ^ | 177 | return static_cast<std::size_t>(hash); |
| 198 | (static_cast<std::size_t>(ndc_minus_one_to_one) << 3) ^ | ||
| 199 | (static_cast<std::size_t>(cull_face) << 24) ^ | ||
| 200 | (static_cast<std::size_t>(front_face) << 48); | ||
| 201 | } | 178 | } |
| 202 | 179 | ||
| 203 | bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noexcept { | 180 | bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noexcept { |
| 204 | return std::tie(cull_enable, depth_bias_enable, depth_clamp_enable, ndc_minus_one_to_one, | 181 | return raw == rhs.raw && point_size == rhs.point_size; |
| 205 | cull_face, front_face) == | ||
| 206 | std::tie(rhs.cull_enable, rhs.depth_bias_enable, rhs.depth_clamp_enable, | ||
| 207 | rhs.ndc_minus_one_to_one, rhs.cull_face, rhs.front_face); | ||
| 208 | } | 182 | } |
| 209 | 183 | ||
| 210 | std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept { | 184 | std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept { |
| @@ -231,8 +205,6 @@ bool FixedPipelineState::ColorBlending::operator==(const ColorBlending& rhs) con | |||
| 231 | std::size_t FixedPipelineState::Hash() const noexcept { | 205 | std::size_t FixedPipelineState::Hash() const noexcept { |
| 232 | std::size_t hash = 0; | 206 | std::size_t hash = 0; |
| 233 | boost::hash_combine(hash, vertex_input.Hash()); | 207 | boost::hash_combine(hash, vertex_input.Hash()); |
| 234 | boost::hash_combine(hash, input_assembly.Hash()); | ||
| 235 | boost::hash_combine(hash, tessellation.Hash()); | ||
| 236 | boost::hash_combine(hash, rasterizer.Hash()); | 208 | boost::hash_combine(hash, rasterizer.Hash()); |
| 237 | boost::hash_combine(hash, depth_stencil.Hash()); | 209 | boost::hash_combine(hash, depth_stencil.Hash()); |
| 238 | boost::hash_combine(hash, color_blending.Hash()); | 210 | boost::hash_combine(hash, color_blending.Hash()); |
| @@ -240,17 +212,13 @@ std::size_t FixedPipelineState::Hash() const noexcept { | |||
| 240 | } | 212 | } |
| 241 | 213 | ||
| 242 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { | 214 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { |
| 243 | return std::tie(vertex_input, input_assembly, tessellation, rasterizer, depth_stencil, | 215 | return std::tie(vertex_input, rasterizer, depth_stencil, color_blending) == |
| 244 | color_blending) == std::tie(rhs.vertex_input, rhs.input_assembly, | 216 | std::tie(rhs.vertex_input, rhs.rasterizer, rhs.depth_stencil, rhs.color_blending); |
| 245 | rhs.tessellation, rhs.rasterizer, rhs.depth_stencil, | ||
| 246 | rhs.color_blending); | ||
| 247 | } | 217 | } |
| 248 | 218 | ||
| 249 | FixedPipelineState GetFixedPipelineState(const Maxwell& regs) { | 219 | FixedPipelineState GetFixedPipelineState(const Maxwell& regs) { |
| 250 | FixedPipelineState fixed_state; | 220 | FixedPipelineState fixed_state; |
| 251 | fixed_state.input_assembly = GetInputAssemblyState(regs); | 221 | fixed_state.rasterizer.Fill(regs); |
| 252 | fixed_state.tessellation = GetTessellationState(regs); | ||
| 253 | fixed_state.rasterizer = GetRasterizerState(regs); | ||
| 254 | fixed_state.depth_stencil.Fill(regs); | 222 | fixed_state.depth_stencil.Fill(regs); |
| 255 | fixed_state.color_blending = GetColorBlendingState(regs); | 223 | fixed_state.color_blending = GetColorBlendingState(regs); |
| 256 | return fixed_state; | 224 | return fixed_state; |
| @@ -307,4 +275,41 @@ Maxwell::StencilOp FixedPipelineState::UnpackStencilOp(u32 packed) noexcept { | |||
| 307 | return LUT[packed]; | 275 | return LUT[packed]; |
| 308 | } | 276 | } |
| 309 | 277 | ||
| 278 | u32 FixedPipelineState::PackCullFace(Maxwell::CullFace cull) noexcept { | ||
| 279 | // FrontAndBack is 0x408, by substracting 0x406 in it we get 2. | ||
| 280 | // Individual cull faces are in 0x404 and 0x405, substracting 0x404 we get 0 and 1. | ||
| 281 | const u32 value = static_cast<u32>(cull); | ||
| 282 | return value - (value == 0x408 ? 0x406 : 0x404); | ||
| 283 | } | ||
| 284 | |||
| 285 | Maxwell::CullFace FixedPipelineState::UnpackCullFace(u32 packed) noexcept { | ||
| 286 | static constexpr std::array LUT = {Maxwell::CullFace::Front, Maxwell::CullFace::Back, | ||
| 287 | Maxwell::CullFace::FrontAndBack}; | ||
| 288 | return LUT[packed]; | ||
| 289 | } | ||
| 290 | |||
| 291 | u32 FixedPipelineState::PackFrontFace(Maxwell::FrontFace face) noexcept { | ||
| 292 | return static_cast<u32>(face) - 0x900; | ||
| 293 | } | ||
| 294 | |||
| 295 | Maxwell::FrontFace FixedPipelineState::UnpackFrontFace(u32 packed) noexcept { | ||
| 296 | return static_cast<Maxwell::FrontFace>(packed + 0x900); | ||
| 297 | } | ||
| 298 | |||
| 299 | u32 FixedPipelineState::PackPolygonMode(Maxwell::PolygonMode mode) noexcept { | ||
| 300 | return static_cast<u32>(mode) - 0x1B00; | ||
| 301 | } | ||
| 302 | |||
| 303 | Maxwell::PolygonMode FixedPipelineState::UnpackPolygonMode(u32 packed) noexcept { | ||
| 304 | return static_cast<Maxwell::PolygonMode>(packed + 0x1B00); | ||
| 305 | } | ||
| 306 | |||
| 307 | u32 FixedPipelineState::PackLogicOp(Maxwell::LogicOperation op) noexcept { | ||
| 308 | return static_cast<u32>(op) - 0x1500; | ||
| 309 | } | ||
| 310 | |||
| 311 | Maxwell::LogicOperation FixedPipelineState::UnpackLogicOp(u32 packed) noexcept { | ||
| 312 | return static_cast<Maxwell::LogicOperation>(packed + 0x1500); | ||
| 313 | } | ||
| 314 | |||
| 310 | } // namespace Vulkan | 315 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index e30877e77..75b093e90 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -30,6 +30,18 @@ struct FixedPipelineState { | |||
| 30 | static u32 PackStencilOp(Maxwell::StencilOp op) noexcept; | 30 | static u32 PackStencilOp(Maxwell::StencilOp op) noexcept; |
| 31 | static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept; | 31 | static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept; |
| 32 | 32 | ||
| 33 | static u32 PackCullFace(Maxwell::CullFace cull) noexcept; | ||
| 34 | static Maxwell::CullFace UnpackCullFace(u32 packed) noexcept; | ||
| 35 | |||
| 36 | static u32 PackFrontFace(Maxwell::FrontFace face) noexcept; | ||
| 37 | static Maxwell::FrontFace UnpackFrontFace(u32 packed) noexcept; | ||
| 38 | |||
| 39 | static u32 PackPolygonMode(Maxwell::PolygonMode mode) noexcept; | ||
| 40 | static Maxwell::PolygonMode UnpackPolygonMode(u32 packed) noexcept; | ||
| 41 | |||
| 42 | static u32 PackLogicOp(Maxwell::LogicOperation op) noexcept; | ||
| 43 | static Maxwell::LogicOperation UnpackLogicOp(u32 packed) noexcept; | ||
| 44 | |||
| 33 | struct BlendingAttachment { | 45 | struct BlendingAttachment { |
| 34 | constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation, | 46 | constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation, |
| 35 | Maxwell::Blend::Factor src_rgb_func, | 47 | Maxwell::Blend::Factor src_rgb_func, |
| @@ -119,71 +131,52 @@ struct FixedPipelineState { | |||
| 119 | }; | 131 | }; |
| 120 | static_assert(IsHashable<VertexInput>); | 132 | static_assert(IsHashable<VertexInput>); |
| 121 | 133 | ||
| 122 | struct InputAssembly { | 134 | struct Rasterizer { |
| 123 | constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable, | 135 | union { |
| 124 | float point_size) | 136 | u32 raw; |
| 125 | : topology{topology}, primitive_restart_enable{primitive_restart_enable}, | 137 | BitField<0, 4, u32> topology; |
| 126 | point_size{point_size} {} | 138 | BitField<4, 1, u32> primitive_restart_enable; |
| 127 | InputAssembly() = default; | 139 | BitField<5, 1, u32> cull_enable; |
| 128 | 140 | BitField<6, 1, u32> depth_bias_enable; | |
| 129 | Maxwell::PrimitiveTopology topology; | 141 | BitField<7, 1, u32> depth_clamp_enable; |
| 130 | bool primitive_restart_enable; | 142 | BitField<8, 1, u32> ndc_minus_one_to_one; |
| 131 | float point_size; | 143 | BitField<9, 2, u32> cull_face; |
| 132 | 144 | BitField<11, 1, u32> front_face; | |
| 133 | std::size_t Hash() const noexcept; | 145 | BitField<12, 2, u32> polygon_mode; |
| 134 | 146 | BitField<14, 5, u32> patch_control_points_minus_one; | |
| 135 | bool operator==(const InputAssembly& rhs) const noexcept; | 147 | BitField<19, 2, u32> tessellation_primitive; |
| 136 | 148 | BitField<21, 2, u32> tessellation_spacing; | |
| 137 | bool operator!=(const InputAssembly& rhs) const noexcept { | 149 | BitField<23, 1, u32> tessellation_clockwise; |
| 138 | return !operator==(rhs); | 150 | BitField<24, 1, u32> logic_op_enable; |
| 139 | } | 151 | BitField<25, 4, u32> logic_op; |
| 140 | }; | 152 | }; |
| 141 | 153 | ||
| 142 | struct Tessellation { | 154 | // TODO(Rodrigo): Move this to push constants |
| 143 | constexpr Tessellation(u32 patch_control_points, Maxwell::TessellationPrimitive primitive, | 155 | u32 point_size; |
| 144 | Maxwell::TessellationSpacing spacing, bool clockwise) | ||
| 145 | : patch_control_points{patch_control_points}, primitive{primitive}, spacing{spacing}, | ||
| 146 | clockwise{clockwise} {} | ||
| 147 | Tessellation() = default; | ||
| 148 | 156 | ||
| 149 | u32 patch_control_points; | 157 | void Fill(const Maxwell& regs) noexcept; |
| 150 | Maxwell::TessellationPrimitive primitive; | ||
| 151 | Maxwell::TessellationSpacing spacing; | ||
| 152 | bool clockwise; | ||
| 153 | 158 | ||
| 154 | std::size_t Hash() const noexcept; | 159 | std::size_t Hash() const noexcept; |
| 155 | 160 | ||
| 156 | bool operator==(const Tessellation& rhs) const noexcept; | 161 | bool operator==(const Rasterizer& rhs) const noexcept; |
| 157 | 162 | ||
| 158 | bool operator!=(const Tessellation& rhs) const noexcept { | 163 | bool operator!=(const Rasterizer& rhs) const noexcept { |
| 159 | return !operator==(rhs); | 164 | return !operator==(rhs); |
| 160 | } | 165 | } |
| 161 | }; | ||
| 162 | |||
| 163 | struct Rasterizer { | ||
| 164 | constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool depth_clamp_enable, | ||
| 165 | bool ndc_minus_one_to_one, Maxwell::CullFace cull_face, | ||
| 166 | Maxwell::FrontFace front_face) | ||
| 167 | : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable}, | ||
| 168 | depth_clamp_enable{depth_clamp_enable}, ndc_minus_one_to_one{ndc_minus_one_to_one}, | ||
| 169 | cull_face{cull_face}, front_face{front_face} {} | ||
| 170 | Rasterizer() = default; | ||
| 171 | |||
| 172 | bool cull_enable; | ||
| 173 | bool depth_bias_enable; | ||
| 174 | bool depth_clamp_enable; | ||
| 175 | bool ndc_minus_one_to_one; | ||
| 176 | Maxwell::CullFace cull_face; | ||
| 177 | Maxwell::FrontFace front_face; | ||
| 178 | 166 | ||
| 179 | std::size_t Hash() const noexcept; | 167 | constexpr Maxwell::PrimitiveTopology Topology() const noexcept { |
| 168 | return static_cast<Maxwell::PrimitiveTopology>(topology.Value()); | ||
| 169 | } | ||
| 180 | 170 | ||
| 181 | bool operator==(const Rasterizer& rhs) const noexcept; | 171 | Maxwell::CullFace CullFace() const noexcept { |
| 172 | return UnpackCullFace(cull_face.Value()); | ||
| 173 | } | ||
| 182 | 174 | ||
| 183 | bool operator!=(const Rasterizer& rhs) const noexcept { | 175 | Maxwell::FrontFace FrontFace() const noexcept { |
| 184 | return !operator==(rhs); | 176 | return UnpackFrontFace(front_face.Value()); |
| 185 | } | 177 | } |
| 186 | }; | 178 | }; |
| 179 | static_assert(IsHashable<Rasterizer>); | ||
| 187 | 180 | ||
| 188 | struct DepthStencil { | 181 | struct DepthStencil { |
| 189 | template <std::size_t Position> | 182 | template <std::size_t Position> |
| @@ -257,8 +250,6 @@ struct FixedPipelineState { | |||
| 257 | }; | 250 | }; |
| 258 | 251 | ||
| 259 | VertexInput vertex_input; | 252 | VertexInput vertex_input; |
| 260 | InputAssembly input_assembly; | ||
| 261 | Tessellation tessellation; | ||
| 262 | Rasterizer rasterizer; | 253 | Rasterizer rasterizer; |
| 263 | DepthStencil depth_stencil; | 254 | DepthStencil depth_stencil; |
| 264 | ColorBlending color_blending; | 255 | ColorBlending color_blending; |
| @@ -273,8 +264,6 @@ struct FixedPipelineState { | |||
| 273 | }; | 264 | }; |
| 274 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>); | 265 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>); |
| 275 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>); | 266 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>); |
| 276 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>); | ||
| 277 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::Tessellation>); | ||
| 278 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>); | 267 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>); |
| 279 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>); | 268 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>); |
| 280 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>); | 269 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>); |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 0dd3ea5bc..e12c26076 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -158,10 +158,8 @@ std::vector<vk::ShaderModule> VKGraphicsPipeline::CreateShaderModules( | |||
| 158 | vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params, | 158 | vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpass_params, |
| 159 | const SPIRVProgram& program) const { | 159 | const SPIRVProgram& program) const { |
| 160 | const auto& vi = fixed_state.vertex_input; | 160 | const auto& vi = fixed_state.vertex_input; |
| 161 | const auto& ia = fixed_state.input_assembly; | ||
| 162 | const auto& ds = fixed_state.depth_stencil; | 161 | const auto& ds = fixed_state.depth_stencil; |
| 163 | const auto& cd = fixed_state.color_blending; | 162 | const auto& cd = fixed_state.color_blending; |
| 164 | const auto& ts = fixed_state.tessellation; | ||
| 165 | const auto& rs = fixed_state.rasterizer; | 163 | const auto& rs = fixed_state.rasterizer; |
| 166 | 164 | ||
| 167 | std::vector<VkVertexInputBindingDescription> vertex_bindings; | 165 | std::vector<VkVertexInputBindingDescription> vertex_bindings; |
| @@ -226,15 +224,15 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa | |||
| 226 | input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; | 224 | input_assembly_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; |
| 227 | input_assembly_ci.pNext = nullptr; | 225 | input_assembly_ci.pNext = nullptr; |
| 228 | input_assembly_ci.flags = 0; | 226 | input_assembly_ci.flags = 0; |
| 229 | input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, ia.topology); | 227 | input_assembly_ci.topology = MaxwellToVK::PrimitiveTopology(device, rs.Topology()); |
| 230 | input_assembly_ci.primitiveRestartEnable = | 228 | input_assembly_ci.primitiveRestartEnable = |
| 231 | ia.primitive_restart_enable && SupportsPrimitiveRestart(input_assembly_ci.topology); | 229 | rs.primitive_restart_enable != 0 && SupportsPrimitiveRestart(input_assembly_ci.topology); |
| 232 | 230 | ||
| 233 | VkPipelineTessellationStateCreateInfo tessellation_ci; | 231 | VkPipelineTessellationStateCreateInfo tessellation_ci; |
| 234 | tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; | 232 | tessellation_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; |
| 235 | tessellation_ci.pNext = nullptr; | 233 | tessellation_ci.pNext = nullptr; |
| 236 | tessellation_ci.flags = 0; | 234 | tessellation_ci.flags = 0; |
| 237 | tessellation_ci.patchControlPoints = ts.patch_control_points; | 235 | tessellation_ci.patchControlPoints = rs.patch_control_points_minus_one.Value() + 1; |
| 238 | 236 | ||
| 239 | VkPipelineViewportStateCreateInfo viewport_ci; | 237 | VkPipelineViewportStateCreateInfo viewport_ci; |
| 240 | viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; | 238 | viewport_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; |
| @@ -253,8 +251,8 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa | |||
| 253 | rasterization_ci.rasterizerDiscardEnable = VK_FALSE; | 251 | rasterization_ci.rasterizerDiscardEnable = VK_FALSE; |
| 254 | rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; | 252 | rasterization_ci.polygonMode = VK_POLYGON_MODE_FILL; |
| 255 | rasterization_ci.cullMode = | 253 | rasterization_ci.cullMode = |
| 256 | rs.cull_enable ? MaxwellToVK::CullFace(rs.cull_face) : VK_CULL_MODE_NONE; | 254 | rs.cull_enable ? MaxwellToVK::CullFace(rs.CullFace()) : VK_CULL_MODE_NONE; |
| 257 | rasterization_ci.frontFace = MaxwellToVK::FrontFace(rs.front_face); | 255 | rasterization_ci.frontFace = MaxwellToVK::FrontFace(rs.FrontFace()); |
| 258 | rasterization_ci.depthBiasEnable = rs.depth_bias_enable; | 256 | rasterization_ci.depthBiasEnable = rs.depth_bias_enable; |
| 259 | rasterization_ci.depthBiasConstantFactor = 0.0f; | 257 | rasterization_ci.depthBiasConstantFactor = 0.0f; |
| 260 | rasterization_ci.depthBiasClamp = 0.0f; | 258 | rasterization_ci.depthBiasClamp = 0.0f; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 083da9999..8fdc6400d 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -329,9 +329,9 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) { | |||
| 329 | const auto& gpu = system.GPU().Maxwell3D(); | 329 | const auto& gpu = system.GPU().Maxwell3D(); |
| 330 | 330 | ||
| 331 | Specialization specialization; | 331 | Specialization specialization; |
| 332 | if (fixed_state.input_assembly.topology == Maxwell::PrimitiveTopology::Points) { | 332 | if (fixed_state.rasterizer.Topology() == Maxwell::PrimitiveTopology::Points) { |
| 333 | ASSERT(fixed_state.input_assembly.point_size != 0.0f); | 333 | ASSERT(fixed_state.rasterizer.point_size != 0); |
| 334 | specialization.point_size = fixed_state.input_assembly.point_size; | 334 | std::memcpy(&specialization.point_size, &fixed_state.rasterizer.point_size, sizeof(u32)); |
| 335 | } | 335 | } |
| 336 | for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) { | 336 | for (std::size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) { |
| 337 | specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].Type(); | 337 | specialization.attribute_types[i] = fixed_state.vertex_input.attributes[i].Type(); |