diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | 295 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.h | 231 |
3 files changed, 528 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3b20c7d34..e615b238e 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -151,6 +151,8 @@ add_library(video_core STATIC | |||
| 151 | if (ENABLE_VULKAN) | 151 | if (ENABLE_VULKAN) |
| 152 | target_sources(video_core PRIVATE | 152 | target_sources(video_core PRIVATE |
| 153 | renderer_vulkan/declarations.h | 153 | renderer_vulkan/declarations.h |
| 154 | renderer_vulkan/fixed_pipeline_state.cpp | ||
| 155 | renderer_vulkan/fixed_pipeline_state.h | ||
| 154 | renderer_vulkan/maxwell_to_vk.cpp | 156 | renderer_vulkan/maxwell_to_vk.cpp |
| 155 | renderer_vulkan/maxwell_to_vk.h | 157 | renderer_vulkan/maxwell_to_vk.h |
| 156 | renderer_vulkan/vk_buffer_cache.cpp | 158 | renderer_vulkan/vk_buffer_cache.cpp |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp new file mode 100644 index 000000000..f75c348fe --- /dev/null +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <tuple> | ||
| 6 | |||
| 7 | #include <boost/functional/hash.hpp> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | ||
| 11 | |||
| 12 | namespace Vulkan { | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | constexpr FixedPipelineState::DepthStencil GetDepthStencilState(const Maxwell& regs) { | ||
| 17 | const FixedPipelineState::StencilFace front_stencil( | ||
| 18 | regs.stencil_front_op_fail, regs.stencil_front_op_zfail, regs.stencil_front_op_zpass, | ||
| 19 | regs.stencil_front_func_func); | ||
| 20 | const FixedPipelineState::StencilFace back_stencil = | ||
| 21 | regs.stencil_two_side_enable | ||
| 22 | ? FixedPipelineState::StencilFace(regs.stencil_back_op_fail, regs.stencil_back_op_zfail, | ||
| 23 | regs.stencil_back_op_zpass, | ||
| 24 | regs.stencil_back_func_func) | ||
| 25 | : front_stencil; | ||
| 26 | return FixedPipelineState::DepthStencil( | ||
| 27 | regs.depth_test_enable == 1, regs.depth_write_enabled == 1, regs.depth_bounds_enable == 1, | ||
| 28 | regs.stencil_enable == 1, regs.depth_test_func, front_stencil, back_stencil); | ||
| 29 | } | ||
| 30 | |||
| 31 | constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) { | ||
| 32 | return FixedPipelineState::InputAssembly( | ||
| 33 | regs.draw.topology, regs.primitive_restart.enabled, | ||
| 34 | regs.draw.topology == Maxwell::PrimitiveTopology::Points ? regs.point_size : 0.0f); | ||
| 35 | } | ||
| 36 | |||
| 37 | constexpr FixedPipelineState::BlendingAttachment GetBlendingAttachmentState( | ||
| 38 | const Maxwell& regs, std::size_t render_target) { | ||
| 39 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : render_target]; | ||
| 40 | const std::array components = {mask.R != 0, mask.G != 0, mask.B != 0, mask.A != 0}; | ||
| 41 | |||
| 42 | const FixedPipelineState::BlendingAttachment default_blending( | ||
| 43 | false, Maxwell::Blend::Equation::Add, Maxwell::Blend::Factor::One, | ||
| 44 | Maxwell::Blend::Factor::Zero, Maxwell::Blend::Equation::Add, Maxwell::Blend::Factor::One, | ||
| 45 | Maxwell::Blend::Factor::Zero, components); | ||
| 46 | if (render_target >= regs.rt_control.count) { | ||
| 47 | return default_blending; | ||
| 48 | } | ||
| 49 | |||
| 50 | if (!regs.independent_blend_enable) { | ||
| 51 | const auto& src = regs.blend; | ||
| 52 | if (!src.enable[render_target]) { | ||
| 53 | return default_blending; | ||
| 54 | } | ||
| 55 | return FixedPipelineState::BlendingAttachment( | ||
| 56 | true, src.equation_rgb, src.factor_source_rgb, src.factor_dest_rgb, src.equation_a, | ||
| 57 | src.factor_source_a, src.factor_dest_a, components); | ||
| 58 | } | ||
| 59 | |||
| 60 | if (!regs.blend.enable[render_target]) { | ||
| 61 | return default_blending; | ||
| 62 | } | ||
| 63 | const auto& src = regs.independent_blend[render_target]; | ||
| 64 | return FixedPipelineState::BlendingAttachment( | ||
| 65 | true, src.equation_rgb, src.factor_source_rgb, src.factor_dest_rgb, src.equation_a, | ||
| 66 | src.factor_source_a, src.factor_dest_a, components); | ||
| 67 | } | ||
| 68 | |||
| 69 | constexpr FixedPipelineState::ColorBlending GetColorBlendingState(const Maxwell& regs) { | ||
| 70 | return FixedPipelineState::ColorBlending( | ||
| 71 | {regs.blend_color.r, regs.blend_color.g, regs.blend_color.b, regs.blend_color.a}, | ||
| 72 | regs.rt_control.count, | ||
| 73 | {GetBlendingAttachmentState(regs, 0), GetBlendingAttachmentState(regs, 1), | ||
| 74 | GetBlendingAttachmentState(regs, 2), GetBlendingAttachmentState(regs, 3), | ||
| 75 | GetBlendingAttachmentState(regs, 4), GetBlendingAttachmentState(regs, 5), | ||
| 76 | GetBlendingAttachmentState(regs, 6), GetBlendingAttachmentState(regs, 7)}); | ||
| 77 | } | ||
| 78 | |||
| 79 | constexpr FixedPipelineState::Tessellation GetTessellationState(const Maxwell& regs) { | ||
| 80 | return FixedPipelineState::Tessellation(regs.patch_vertices, regs.tess_mode.prim, | ||
| 81 | regs.tess_mode.spacing, regs.tess_mode.cw != 0); | ||
| 82 | } | ||
| 83 | |||
| 84 | constexpr std::size_t Point = 0; | ||
| 85 | constexpr std::size_t Line = 1; | ||
| 86 | constexpr std::size_t Polygon = 2; | ||
| 87 | constexpr std::array PolygonOffsetEnableLUT = { | ||
| 88 | Point, // Points | ||
| 89 | Line, // Lines | ||
| 90 | Line, // LineLoop | ||
| 91 | Line, // LineStrip | ||
| 92 | Polygon, // Triangles | ||
| 93 | Polygon, // TriangleStrip | ||
| 94 | Polygon, // TriangleFan | ||
| 95 | Polygon, // Quads | ||
| 96 | Polygon, // QuadStrip | ||
| 97 | Polygon, // Polygon | ||
| 98 | Line, // LinesAdjacency | ||
| 99 | Line, // LineStripAdjacency | ||
| 100 | Polygon, // TrianglesAdjacency | ||
| 101 | Polygon, // TriangleStripAdjacency | ||
| 102 | Polygon, // Patches | ||
| 103 | }; | ||
| 104 | |||
| 105 | constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs) { | ||
| 106 | const std::array enabled_lut = {regs.polygon_offset_point_enable, | ||
| 107 | regs.polygon_offset_line_enable, | ||
| 108 | regs.polygon_offset_fill_enable}; | ||
| 109 | const auto topology = static_cast<std::size_t>(regs.draw.topology.Value()); | ||
| 110 | const bool depth_bias_enabled = enabled_lut[PolygonOffsetEnableLUT[topology]]; | ||
| 111 | |||
| 112 | Maxwell::Cull::FrontFace front_face = regs.cull.front_face; | ||
| 113 | if (regs.screen_y_control.triangle_rast_flip != 0 && | ||
| 114 | regs.viewport_transform[0].scale_y > 0.0f) { | ||
| 115 | if (front_face == Maxwell::Cull::FrontFace::CounterClockWise) | ||
| 116 | front_face = Maxwell::Cull::FrontFace::ClockWise; | ||
| 117 | else if (front_face == Maxwell::Cull::FrontFace::ClockWise) | ||
| 118 | front_face = Maxwell::Cull::FrontFace::CounterClockWise; | ||
| 119 | } | ||
| 120 | |||
| 121 | const bool gl_ndc = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; | ||
| 122 | return FixedPipelineState::Rasterizer(regs.cull.enabled, depth_bias_enabled, gl_ndc, | ||
| 123 | regs.cull.cull_face, front_face); | ||
| 124 | } | ||
| 125 | |||
| 126 | } // Anonymous namespace | ||
| 127 | |||
| 128 | std::size_t FixedPipelineState::VertexBinding::Hash() const { | ||
| 129 | return (index << stride) ^ divisor; | ||
| 130 | } | ||
| 131 | |||
| 132 | bool FixedPipelineState::VertexBinding::operator==(const VertexBinding& rhs) const { | ||
| 133 | return std::tie(index, stride, divisor) == std::tie(rhs.index, rhs.stride, rhs.divisor); | ||
| 134 | } | ||
| 135 | |||
| 136 | std::size_t FixedPipelineState::VertexAttribute::Hash() const { | ||
| 137 | return static_cast<std::size_t>(index) ^ (static_cast<std::size_t>(buffer) << 13) ^ | ||
| 138 | (static_cast<std::size_t>(type) << 22) ^ (static_cast<std::size_t>(size) << 31) ^ | ||
| 139 | (static_cast<std::size_t>(offset) << 36); | ||
| 140 | } | ||
| 141 | |||
| 142 | bool FixedPipelineState::VertexAttribute::operator==(const VertexAttribute& rhs) const { | ||
| 143 | return std::tie(index, buffer, type, size, offset) == | ||
| 144 | std::tie(rhs.index, rhs.buffer, rhs.type, rhs.size, rhs.offset); | ||
| 145 | } | ||
| 146 | |||
| 147 | std::size_t FixedPipelineState::StencilFace::Hash() const { | ||
| 148 | return static_cast<std::size_t>(action_stencil_fail) ^ | ||
| 149 | (static_cast<std::size_t>(action_depth_fail) << 4) ^ | ||
| 150 | (static_cast<std::size_t>(action_depth_fail) << 20) ^ | ||
| 151 | (static_cast<std::size_t>(action_depth_pass) << 36); | ||
| 152 | } | ||
| 153 | |||
| 154 | bool FixedPipelineState::StencilFace::operator==(const StencilFace& rhs) const { | ||
| 155 | return std::tie(action_stencil_fail, action_depth_fail, action_depth_pass, test_func) == | ||
| 156 | std::tie(rhs.action_stencil_fail, rhs.action_depth_fail, rhs.action_depth_pass, | ||
| 157 | rhs.test_func); | ||
| 158 | } | ||
| 159 | |||
| 160 | std::size_t FixedPipelineState::BlendingAttachment::Hash() const { | ||
| 161 | return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^ | ||
| 162 | (static_cast<std::size_t>(src_rgb_func) << 10) ^ | ||
| 163 | (static_cast<std::size_t>(dst_rgb_func) << 15) ^ | ||
| 164 | (static_cast<std::size_t>(a_equation) << 20) ^ | ||
| 165 | (static_cast<std::size_t>(src_a_func) << 25) ^ | ||
| 166 | (static_cast<std::size_t>(dst_a_func) << 30) ^ | ||
| 167 | (static_cast<std::size_t>(components[0]) << 35) ^ | ||
| 168 | (static_cast<std::size_t>(components[1]) << 36) ^ | ||
| 169 | (static_cast<std::size_t>(components[2]) << 37) ^ | ||
| 170 | (static_cast<std::size_t>(components[3]) << 38); | ||
| 171 | } | ||
| 172 | |||
| 173 | bool FixedPipelineState::BlendingAttachment::operator==(const BlendingAttachment& rhs) const { | ||
| 174 | return std::tie(enable, rgb_equation, src_rgb_func, dst_rgb_func, a_equation, src_a_func, | ||
| 175 | dst_a_func, components) == | ||
| 176 | std::tie(rhs.enable, rhs.rgb_equation, rhs.src_rgb_func, rhs.dst_rgb_func, | ||
| 177 | rhs.a_equation, rhs.src_a_func, rhs.dst_a_func, rhs.components); | ||
| 178 | } | ||
| 179 | |||
| 180 | std::size_t FixedPipelineState::VertexInput::Hash() const { | ||
| 181 | std::size_t hash = num_bindings ^ (num_attributes << 32); | ||
| 182 | for (std::size_t i = 0; i < num_bindings; ++i) { | ||
| 183 | boost::hash_combine(hash, bindings[i].Hash()); | ||
| 184 | } | ||
| 185 | for (std::size_t i = 0; i < num_attributes; ++i) { | ||
| 186 | boost::hash_combine(hash, attributes[i].Hash()); | ||
| 187 | } | ||
| 188 | return hash; | ||
| 189 | } | ||
| 190 | |||
| 191 | bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const { | ||
| 192 | return std::equal(bindings.begin(), bindings.begin() + num_bindings, rhs.bindings.begin(), | ||
| 193 | rhs.bindings.begin() + rhs.num_bindings) && | ||
| 194 | std::equal(attributes.begin(), attributes.begin() + num_attributes, | ||
| 195 | rhs.attributes.begin(), rhs.attributes.begin() + rhs.num_attributes); | ||
| 196 | } | ||
| 197 | |||
| 198 | std::size_t FixedPipelineState::InputAssembly::Hash() const { | ||
| 199 | std::size_t point_size_int = 0; | ||
| 200 | std::memcpy(&point_size_int, &point_size, sizeof(point_size)); | ||
| 201 | return (static_cast<std::size_t>(topology) << 24) ^ (point_size_int << 32) ^ | ||
| 202 | static_cast<std::size_t>(primitive_restart_enable); | ||
| 203 | } | ||
| 204 | |||
| 205 | bool FixedPipelineState::InputAssembly::operator==(const InputAssembly& rhs) const { | ||
| 206 | return std::tie(topology, primitive_restart_enable, point_size) == | ||
| 207 | std::tie(rhs.topology, rhs.primitive_restart_enable, rhs.point_size); | ||
| 208 | } | ||
| 209 | |||
| 210 | std::size_t FixedPipelineState::Tessellation::Hash() const { | ||
| 211 | return static_cast<std::size_t>(patch_control_points) ^ | ||
| 212 | (static_cast<std::size_t>(primitive) << 6) ^ (static_cast<std::size_t>(spacing) << 8) ^ | ||
| 213 | (static_cast<std::size_t>(clockwise) << 10); | ||
| 214 | } | ||
| 215 | |||
| 216 | bool FixedPipelineState::Tessellation::operator==(const Tessellation& rhs) const { | ||
| 217 | return std::tie(patch_control_points, primitive, spacing, clockwise) == | ||
| 218 | std::tie(rhs.patch_control_points, rhs.primitive, rhs.spacing, rhs.clockwise); | ||
| 219 | } | ||
| 220 | |||
| 221 | std::size_t FixedPipelineState::Rasterizer::Hash() const { | ||
| 222 | return static_cast<std::size_t>(cull_enable) ^ | ||
| 223 | (static_cast<std::size_t>(depth_bias_enable) << 1) ^ | ||
| 224 | (static_cast<std::size_t>(ndc_minus_one_to_one) << 2) ^ | ||
| 225 | (static_cast<std::size_t>(cull_face) << 24) ^ | ||
| 226 | (static_cast<std::size_t>(front_face) << 48); | ||
| 227 | } | ||
| 228 | |||
| 229 | bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const { | ||
| 230 | return std::tie(cull_enable, depth_bias_enable, ndc_minus_one_to_one, cull_face, front_face) == | ||
| 231 | std::tie(rhs.cull_enable, rhs.depth_bias_enable, rhs.ndc_minus_one_to_one, rhs.cull_face, | ||
| 232 | rhs.front_face); | ||
| 233 | } | ||
| 234 | |||
| 235 | std::size_t FixedPipelineState::DepthStencil::Hash() const { | ||
| 236 | std::size_t hash = static_cast<std::size_t>(depth_test_enable) ^ | ||
| 237 | (static_cast<std::size_t>(depth_write_enable) << 1) ^ | ||
| 238 | (static_cast<std::size_t>(depth_bounds_enable) << 2) ^ | ||
| 239 | (static_cast<std::size_t>(stencil_enable) << 3) ^ | ||
| 240 | (static_cast<std::size_t>(depth_test_function) << 4); | ||
| 241 | boost::hash_combine(hash, front_stencil.Hash()); | ||
| 242 | boost::hash_combine(hash, back_stencil.Hash()); | ||
| 243 | return hash; | ||
| 244 | } | ||
| 245 | |||
| 246 | bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const { | ||
| 247 | return std::tie(depth_test_enable, depth_write_enable, depth_bounds_enable, depth_test_function, | ||
| 248 | stencil_enable, front_stencil, back_stencil) == | ||
| 249 | std::tie(rhs.depth_test_enable, rhs.depth_write_enable, rhs.depth_bounds_enable, | ||
| 250 | rhs.depth_test_function, rhs.stencil_enable, rhs.front_stencil, | ||
| 251 | rhs.back_stencil); | ||
| 252 | } | ||
| 253 | |||
| 254 | std::size_t FixedPipelineState::ColorBlending::Hash() const { | ||
| 255 | std::size_t hash = attachments_count << 13; | ||
| 256 | for (std::size_t rt = 0; rt < static_cast<std::size_t>(attachments_count); ++rt) { | ||
| 257 | boost::hash_combine(hash, attachments[rt].Hash()); | ||
| 258 | } | ||
| 259 | return hash; | ||
| 260 | } | ||
| 261 | |||
| 262 | bool FixedPipelineState::ColorBlending::operator==(const ColorBlending& rhs) const { | ||
| 263 | return std::equal(attachments.begin(), attachments.begin() + attachments_count, | ||
| 264 | rhs.attachments.begin(), rhs.attachments.begin() + rhs.attachments_count); | ||
| 265 | } | ||
| 266 | |||
| 267 | std::size_t FixedPipelineState::Hash() const noexcept { | ||
| 268 | std::size_t hash = 0; | ||
| 269 | boost::hash_combine(hash, vertex_input.Hash()); | ||
| 270 | boost::hash_combine(hash, input_assembly.Hash()); | ||
| 271 | boost::hash_combine(hash, tessellation.Hash()); | ||
| 272 | boost::hash_combine(hash, rasterizer.Hash()); | ||
| 273 | boost::hash_combine(hash, depth_stencil.Hash()); | ||
| 274 | boost::hash_combine(hash, color_blending.Hash()); | ||
| 275 | return hash; | ||
| 276 | } | ||
| 277 | |||
| 278 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { | ||
| 279 | return std::tie(vertex_input, input_assembly, tessellation, rasterizer, depth_stencil, | ||
| 280 | color_blending) == std::tie(rhs.vertex_input, rhs.input_assembly, | ||
| 281 | rhs.tessellation, rhs.rasterizer, rhs.depth_stencil, | ||
| 282 | rhs.color_blending); | ||
| 283 | } | ||
| 284 | |||
| 285 | FixedPipelineState GetFixedPipelineState(const Maxwell& regs) { | ||
| 286 | FixedPipelineState fixed_state; | ||
| 287 | fixed_state.input_assembly = GetInputAssemblyState(regs); | ||
| 288 | fixed_state.tessellation = GetTessellationState(regs); | ||
| 289 | fixed_state.rasterizer = GetRasterizerState(regs); | ||
| 290 | fixed_state.depth_stencil = GetDepthStencilState(regs); | ||
| 291 | fixed_state.color_blending = GetColorBlendingState(regs); | ||
| 292 | return fixed_state; | ||
| 293 | } | ||
| 294 | |||
| 295 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h new file mode 100644 index 000000000..01f82be68 --- /dev/null +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -0,0 +1,231 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <type_traits> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | #include "video_core/engines/maxwell_3d.h" | ||
| 13 | #include "video_core/surface.h" | ||
| 14 | |||
| 15 | namespace Vulkan { | ||
| 16 | |||
| 17 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||
| 18 | |||
| 19 | // TODO(Rodrigo): Optimize this structure. | ||
| 20 | |||
| 21 | struct FixedPipelineState { | ||
| 22 | using PixelFormat = VideoCore::Surface::PixelFormat; | ||
| 23 | |||
| 24 | struct VertexBinding { | ||
| 25 | constexpr VertexBinding(u32 index, u32 stride, u32 divisor) | ||
| 26 | : index{index}, stride{stride}, divisor{divisor} {} | ||
| 27 | VertexBinding() = default; | ||
| 28 | |||
| 29 | u32 index; | ||
| 30 | u32 stride; | ||
| 31 | u32 divisor; | ||
| 32 | |||
| 33 | std::size_t Hash() const; | ||
| 34 | bool operator==(const VertexBinding& rhs) const; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct VertexAttribute { | ||
| 38 | constexpr VertexAttribute(u32 index, u32 buffer, Maxwell::VertexAttribute::Type type, | ||
| 39 | Maxwell::VertexAttribute::Size size, u32 offset) | ||
| 40 | : index{index}, buffer{buffer}, type{type}, size{size}, offset{offset} {} | ||
| 41 | VertexAttribute() = default; | ||
| 42 | |||
| 43 | u32 index; | ||
| 44 | u32 buffer; | ||
| 45 | Maxwell::VertexAttribute::Type type; | ||
| 46 | Maxwell::VertexAttribute::Size size; | ||
| 47 | u32 offset; | ||
| 48 | |||
| 49 | std::size_t Hash() const; | ||
| 50 | bool operator==(const VertexAttribute& rhs) const; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct StencilFace { | ||
| 54 | constexpr StencilFace(Maxwell::StencilOp action_stencil_fail, | ||
| 55 | Maxwell::StencilOp action_depth_fail, | ||
| 56 | Maxwell::StencilOp action_depth_pass, Maxwell::ComparisonOp test_func) | ||
| 57 | : action_stencil_fail{action_stencil_fail}, action_depth_fail{action_depth_fail}, | ||
| 58 | action_depth_pass{action_depth_pass}, test_func{test_func} {} | ||
| 59 | StencilFace() = default; | ||
| 60 | |||
| 61 | Maxwell::StencilOp action_stencil_fail; | ||
| 62 | Maxwell::StencilOp action_depth_fail; | ||
| 63 | Maxwell::StencilOp action_depth_pass; | ||
| 64 | Maxwell::ComparisonOp test_func; | ||
| 65 | |||
| 66 | std::size_t Hash() const; | ||
| 67 | bool operator==(const StencilFace& rhs) const; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct BlendingAttachment { | ||
| 71 | constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation, | ||
| 72 | Maxwell::Blend::Factor src_rgb_func, | ||
| 73 | Maxwell::Blend::Factor dst_rgb_func, | ||
| 74 | Maxwell::Blend::Equation a_equation, | ||
| 75 | Maxwell::Blend::Factor src_a_func, | ||
| 76 | Maxwell::Blend::Factor dst_a_func, | ||
| 77 | std::array<bool, 4> components) | ||
| 78 | : enable{enable}, rgb_equation{rgb_equation}, src_rgb_func{src_rgb_func}, | ||
| 79 | dst_rgb_func{dst_rgb_func}, a_equation{a_equation}, src_a_func{src_a_func}, | ||
| 80 | dst_a_func{dst_a_func}, components{components} {} | ||
| 81 | BlendingAttachment() = default; | ||
| 82 | |||
| 83 | bool enable; | ||
| 84 | Maxwell::Blend::Equation rgb_equation; | ||
| 85 | Maxwell::Blend::Factor src_rgb_func; | ||
| 86 | Maxwell::Blend::Factor dst_rgb_func; | ||
| 87 | Maxwell::Blend::Equation a_equation; | ||
| 88 | Maxwell::Blend::Factor src_a_func; | ||
| 89 | Maxwell::Blend::Factor dst_a_func; | ||
| 90 | std::array<bool, 4> components; | ||
| 91 | |||
| 92 | std::size_t Hash() const; | ||
| 93 | bool operator==(const BlendingAttachment& rhs) const; | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct VertexInput { | ||
| 97 | std::size_t num_bindings = 0; | ||
| 98 | std::size_t num_attributes = 0; | ||
| 99 | std::array<VertexBinding, Maxwell::NumVertexArrays> bindings; | ||
| 100 | std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; | ||
| 101 | |||
| 102 | std::size_t Hash() const; | ||
| 103 | bool operator==(const VertexInput& rhs) const; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct InputAssembly { | ||
| 107 | constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable, | ||
| 108 | float point_size) | ||
| 109 | : topology{topology}, primitive_restart_enable{primitive_restart_enable}, | ||
| 110 | point_size{point_size} {} | ||
| 111 | InputAssembly() = default; | ||
| 112 | |||
| 113 | Maxwell::PrimitiveTopology topology; | ||
| 114 | bool primitive_restart_enable; | ||
| 115 | float point_size; | ||
| 116 | |||
| 117 | std::size_t Hash() const; | ||
| 118 | bool operator==(const InputAssembly& rhs) const; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct Tessellation { | ||
| 122 | constexpr Tessellation(u32 patch_control_points, Maxwell::TessellationPrimitive primitive, | ||
| 123 | Maxwell::TessellationSpacing spacing, bool clockwise) | ||
| 124 | : patch_control_points{patch_control_points}, primitive{primitive}, spacing{spacing}, | ||
| 125 | clockwise{clockwise} {} | ||
| 126 | Tessellation() = default; | ||
| 127 | |||
| 128 | u32 patch_control_points; | ||
| 129 | Maxwell::TessellationPrimitive primitive; | ||
| 130 | Maxwell::TessellationSpacing spacing; | ||
| 131 | bool clockwise; | ||
| 132 | |||
| 133 | std::size_t Hash() const; | ||
| 134 | bool operator==(const Tessellation& rhs) const; | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct Rasterizer { | ||
| 138 | constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool ndc_minus_one_to_one, | ||
| 139 | Maxwell::Cull::CullFace cull_face, Maxwell::Cull::FrontFace front_face) | ||
| 140 | : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable}, | ||
| 141 | ndc_minus_one_to_one{ndc_minus_one_to_one}, cull_face{cull_face}, front_face{ | ||
| 142 | front_face} {} | ||
| 143 | Rasterizer() = default; | ||
| 144 | |||
| 145 | bool cull_enable; | ||
| 146 | bool depth_bias_enable; | ||
| 147 | bool ndc_minus_one_to_one; | ||
| 148 | Maxwell::Cull::CullFace cull_face; | ||
| 149 | Maxwell::Cull::FrontFace front_face; | ||
| 150 | |||
| 151 | std::size_t Hash() const; | ||
| 152 | bool operator==(const Rasterizer& rhs) const; | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct DepthStencil { | ||
| 156 | constexpr DepthStencil(bool depth_test_enable, bool depth_write_enable, | ||
| 157 | bool depth_bounds_enable, bool stencil_enable, | ||
| 158 | Maxwell::ComparisonOp depth_test_function, StencilFace front_stencil, | ||
| 159 | StencilFace back_stencil) | ||
| 160 | : depth_test_enable{depth_test_enable}, depth_write_enable{depth_write_enable}, | ||
| 161 | depth_bounds_enable{depth_bounds_enable}, stencil_enable{stencil_enable}, | ||
| 162 | depth_test_function{depth_test_function}, front_stencil{front_stencil}, | ||
| 163 | back_stencil{back_stencil} {} | ||
| 164 | DepthStencil() = default; | ||
| 165 | |||
| 166 | bool depth_test_enable; | ||
| 167 | bool depth_write_enable; | ||
| 168 | bool depth_bounds_enable; | ||
| 169 | bool stencil_enable; | ||
| 170 | Maxwell::ComparisonOp depth_test_function; | ||
| 171 | StencilFace front_stencil; | ||
| 172 | StencilFace back_stencil; | ||
| 173 | |||
| 174 | std::size_t Hash() const; | ||
| 175 | bool operator==(const DepthStencil& rhs) const; | ||
| 176 | }; | ||
| 177 | |||
| 178 | struct ColorBlending { | ||
| 179 | constexpr ColorBlending( | ||
| 180 | std::array<float, 4> blend_constants, std::size_t attachments_count, | ||
| 181 | std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments) | ||
| 182 | : attachments_count{attachments_count}, attachments{attachments} {} | ||
| 183 | ColorBlending() = default; | ||
| 184 | |||
| 185 | std::size_t attachments_count; | ||
| 186 | std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments; | ||
| 187 | |||
| 188 | std::size_t Hash() const; | ||
| 189 | bool operator==(const ColorBlending& rhs) const; | ||
| 190 | }; | ||
| 191 | |||
| 192 | std::size_t Hash() const noexcept; | ||
| 193 | bool operator==(const FixedPipelineState& rhs) const noexcept; | ||
| 194 | |||
| 195 | bool operator!=(const FixedPipelineState& rhs) const noexcept { | ||
| 196 | return !operator==(rhs); | ||
| 197 | } | ||
| 198 | |||
| 199 | VertexInput vertex_input; | ||
| 200 | InputAssembly input_assembly; | ||
| 201 | Tessellation tessellation; | ||
| 202 | Rasterizer rasterizer; | ||
| 203 | DepthStencil depth_stencil; | ||
| 204 | ColorBlending color_blending; | ||
| 205 | }; | ||
| 206 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexBinding>); | ||
| 207 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexAttribute>); | ||
| 208 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>); | ||
| 209 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>); | ||
| 210 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>); | ||
| 211 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>); | ||
| 212 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::Tessellation>); | ||
| 213 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>); | ||
| 214 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>); | ||
| 215 | static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>); | ||
| 216 | static_assert(std::is_trivially_copyable_v<FixedPipelineState>); | ||
| 217 | |||
| 218 | FixedPipelineState GetFixedPipelineState(const Maxwell& regs); | ||
| 219 | |||
| 220 | } // namespace Vulkan | ||
| 221 | |||
| 222 | namespace std { | ||
| 223 | |||
| 224 | template <> | ||
| 225 | struct hash<Vulkan::FixedPipelineState> { | ||
| 226 | std::size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept { | ||
| 227 | return k.Hash(); | ||
| 228 | } | ||
| 229 | }; | ||
| 230 | |||
| 231 | } // namespace std | ||