summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/engines/maxwell_3d.h20
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp296
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h282
4 files changed, 594 insertions, 6 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
151if (ENABLE_VULKAN) 151if (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/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 870b359be..a35e7a195 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -711,13 +711,15 @@ public:
711 711
712 u32 color_mask_common; 712 u32 color_mask_common;
713 713
714 INSERT_UNION_PADDING_WORDS(0x6); 714 INSERT_UNION_PADDING_WORDS(0x2);
715
716 u32 rt_separate_frag_data;
717 715
718 f32 depth_bounds[2]; 716 f32 depth_bounds[2];
719 717
720 INSERT_UNION_PADDING_WORDS(0xA); 718 INSERT_UNION_PADDING_WORDS(0x2);
719
720 u32 rt_separate_frag_data;
721
722 INSERT_UNION_PADDING_WORDS(0xC);
721 723
722 struct { 724 struct {
723 u32 address_high; 725 u32 address_high;
@@ -1034,7 +1036,12 @@ public:
1034 BitField<4, 1, u32> depth_clamp_far; 1036 BitField<4, 1, u32> depth_clamp_far;
1035 } view_volume_clip_control; 1037 } view_volume_clip_control;
1036 1038
1037 INSERT_UNION_PADDING_WORDS(0x21); 1039 INSERT_UNION_PADDING_WORDS(0x1F);
1040
1041 u32 depth_bounds_enable;
1042
1043 INSERT_UNION_PADDING_WORDS(1);
1044
1038 struct { 1045 struct {
1039 u32 enable; 1046 u32 enable;
1040 LogicOperation operation; 1047 LogicOperation operation;
@@ -1444,7 +1451,7 @@ ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D6);
1444ASSERT_REG_POSITION(stencil_back_mask, 0x3D7); 1451ASSERT_REG_POSITION(stencil_back_mask, 0x3D7);
1445ASSERT_REG_POSITION(color_mask_common, 0x3E4); 1452ASSERT_REG_POSITION(color_mask_common, 0x3E4);
1446ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); 1453ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
1447ASSERT_REG_POSITION(depth_bounds, 0x3EC); 1454ASSERT_REG_POSITION(depth_bounds, 0x3E7);
1448ASSERT_REG_POSITION(zeta, 0x3F8); 1455ASSERT_REG_POSITION(zeta, 0x3F8);
1449ASSERT_REG_POSITION(clear_flags, 0x43E); 1456ASSERT_REG_POSITION(clear_flags, 0x43E);
1450ASSERT_REG_POSITION(vertex_attrib_format, 0x458); 1457ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
@@ -1500,6 +1507,7 @@ ASSERT_REG_POSITION(cull, 0x646);
1500ASSERT_REG_POSITION(pixel_center_integer, 0x649); 1507ASSERT_REG_POSITION(pixel_center_integer, 0x649);
1501ASSERT_REG_POSITION(viewport_transform_enabled, 0x64B); 1508ASSERT_REG_POSITION(viewport_transform_enabled, 0x64B);
1502ASSERT_REG_POSITION(view_volume_clip_control, 0x64F); 1509ASSERT_REG_POSITION(view_volume_clip_control, 0x64F);
1510ASSERT_REG_POSITION(depth_bounds_enable, 0x66F);
1503ASSERT_REG_POSITION(logic_op, 0x671); 1511ASSERT_REG_POSITION(logic_op, 0x671);
1504ASSERT_REG_POSITION(clear_buffers, 0x674); 1512ASSERT_REG_POSITION(clear_buffers, 0x674);
1505ASSERT_REG_POSITION(color_mask, 0x680); 1513ASSERT_REG_POSITION(color_mask, 0x680);
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..5a490f6ef
--- /dev/null
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -0,0 +1,296 @@
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
12namespace Vulkan {
13
14namespace {
15
16constexpr 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
31constexpr 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
37constexpr 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
69constexpr 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
79constexpr 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
84constexpr std::size_t Point = 0;
85constexpr std::size_t Line = 1;
86constexpr std::size_t Polygon = 2;
87constexpr 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
105constexpr 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
128std::size_t FixedPipelineState::VertexBinding::Hash() const noexcept {
129 return (index << stride) ^ divisor;
130}
131
132bool FixedPipelineState::VertexBinding::operator==(const VertexBinding& rhs) const noexcept {
133 return std::tie(index, stride, divisor) == std::tie(rhs.index, rhs.stride, rhs.divisor);
134}
135
136std::size_t FixedPipelineState::VertexAttribute::Hash() const noexcept {
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
142bool FixedPipelineState::VertexAttribute::operator==(const VertexAttribute& rhs) const noexcept {
143 return std::tie(index, buffer, type, size, offset) ==
144 std::tie(rhs.index, rhs.buffer, rhs.type, rhs.size, rhs.offset);
145}
146
147std::size_t FixedPipelineState::StencilFace::Hash() const noexcept {
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
154bool FixedPipelineState::StencilFace::operator==(const StencilFace& rhs) const noexcept {
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
160std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
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
173bool FixedPipelineState::BlendingAttachment::operator==(const BlendingAttachment& rhs) const
174 noexcept {
175 return std::tie(enable, rgb_equation, src_rgb_func, dst_rgb_func, a_equation, src_a_func,
176 dst_a_func, components) ==
177 std::tie(rhs.enable, rhs.rgb_equation, rhs.src_rgb_func, rhs.dst_rgb_func,
178 rhs.a_equation, rhs.src_a_func, rhs.dst_a_func, rhs.components);
179}
180
181std::size_t FixedPipelineState::VertexInput::Hash() const noexcept {
182 std::size_t hash = num_bindings ^ (num_attributes << 32);
183 for (std::size_t i = 0; i < num_bindings; ++i) {
184 boost::hash_combine(hash, bindings[i].Hash());
185 }
186 for (std::size_t i = 0; i < num_attributes; ++i) {
187 boost::hash_combine(hash, attributes[i].Hash());
188 }
189 return hash;
190}
191
192bool FixedPipelineState::VertexInput::operator==(const VertexInput& rhs) const noexcept {
193 return std::equal(bindings.begin(), bindings.begin() + num_bindings, rhs.bindings.begin(),
194 rhs.bindings.begin() + rhs.num_bindings) &&
195 std::equal(attributes.begin(), attributes.begin() + num_attributes,
196 rhs.attributes.begin(), rhs.attributes.begin() + rhs.num_attributes);
197}
198
199std::size_t FixedPipelineState::InputAssembly::Hash() const noexcept {
200 std::size_t point_size_int = 0;
201 std::memcpy(&point_size_int, &point_size, sizeof(point_size));
202 return (static_cast<std::size_t>(topology) << 24) ^ (point_size_int << 32) ^
203 static_cast<std::size_t>(primitive_restart_enable);
204}
205
206bool FixedPipelineState::InputAssembly::operator==(const InputAssembly& rhs) const noexcept {
207 return std::tie(topology, primitive_restart_enable, point_size) ==
208 std::tie(rhs.topology, rhs.primitive_restart_enable, rhs.point_size);
209}
210
211std::size_t FixedPipelineState::Tessellation::Hash() const noexcept {
212 return static_cast<std::size_t>(patch_control_points) ^
213 (static_cast<std::size_t>(primitive) << 6) ^ (static_cast<std::size_t>(spacing) << 8) ^
214 (static_cast<std::size_t>(clockwise) << 10);
215}
216
217bool FixedPipelineState::Tessellation::operator==(const Tessellation& rhs) const noexcept {
218 return std::tie(patch_control_points, primitive, spacing, clockwise) ==
219 std::tie(rhs.patch_control_points, rhs.primitive, rhs.spacing, rhs.clockwise);
220}
221
222std::size_t FixedPipelineState::Rasterizer::Hash() const noexcept {
223 return static_cast<std::size_t>(cull_enable) ^
224 (static_cast<std::size_t>(depth_bias_enable) << 1) ^
225 (static_cast<std::size_t>(ndc_minus_one_to_one) << 2) ^
226 (static_cast<std::size_t>(cull_face) << 24) ^
227 (static_cast<std::size_t>(front_face) << 48);
228}
229
230bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noexcept {
231 return std::tie(cull_enable, depth_bias_enable, ndc_minus_one_to_one, cull_face, front_face) ==
232 std::tie(rhs.cull_enable, rhs.depth_bias_enable, rhs.ndc_minus_one_to_one, rhs.cull_face,
233 rhs.front_face);
234}
235
236std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept {
237 std::size_t hash = static_cast<std::size_t>(depth_test_enable) ^
238 (static_cast<std::size_t>(depth_write_enable) << 1) ^
239 (static_cast<std::size_t>(depth_bounds_enable) << 2) ^
240 (static_cast<std::size_t>(stencil_enable) << 3) ^
241 (static_cast<std::size_t>(depth_test_function) << 4);
242 boost::hash_combine(hash, front_stencil.Hash());
243 boost::hash_combine(hash, back_stencil.Hash());
244 return hash;
245}
246
247bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept {
248 return std::tie(depth_test_enable, depth_write_enable, depth_bounds_enable, depth_test_function,
249 stencil_enable, front_stencil, back_stencil) ==
250 std::tie(rhs.depth_test_enable, rhs.depth_write_enable, rhs.depth_bounds_enable,
251 rhs.depth_test_function, rhs.stencil_enable, rhs.front_stencil,
252 rhs.back_stencil);
253}
254
255std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept {
256 std::size_t hash = attachments_count << 13;
257 for (std::size_t rt = 0; rt < static_cast<std::size_t>(attachments_count); ++rt) {
258 boost::hash_combine(hash, attachments[rt].Hash());
259 }
260 return hash;
261}
262
263bool FixedPipelineState::ColorBlending::operator==(const ColorBlending& rhs) const noexcept {
264 return std::equal(attachments.begin(), attachments.begin() + attachments_count,
265 rhs.attachments.begin(), rhs.attachments.begin() + rhs.attachments_count);
266}
267
268std::size_t FixedPipelineState::Hash() const noexcept {
269 std::size_t hash = 0;
270 boost::hash_combine(hash, vertex_input.Hash());
271 boost::hash_combine(hash, input_assembly.Hash());
272 boost::hash_combine(hash, tessellation.Hash());
273 boost::hash_combine(hash, rasterizer.Hash());
274 boost::hash_combine(hash, depth_stencil.Hash());
275 boost::hash_combine(hash, color_blending.Hash());
276 return hash;
277}
278
279bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept {
280 return std::tie(vertex_input, input_assembly, tessellation, rasterizer, depth_stencil,
281 color_blending) == std::tie(rhs.vertex_input, rhs.input_assembly,
282 rhs.tessellation, rhs.rasterizer, rhs.depth_stencil,
283 rhs.color_blending);
284}
285
286FixedPipelineState GetFixedPipelineState(const Maxwell& regs) {
287 FixedPipelineState fixed_state;
288 fixed_state.input_assembly = GetInputAssemblyState(regs);
289 fixed_state.tessellation = GetTessellationState(regs);
290 fixed_state.rasterizer = GetRasterizerState(regs);
291 fixed_state.depth_stencil = GetDepthStencilState(regs);
292 fixed_state.color_blending = GetColorBlendingState(regs);
293 return fixed_state;
294}
295
296} // 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..04152c0d4
--- /dev/null
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -0,0 +1,282 @@
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
15namespace Vulkan {
16
17using Maxwell = Tegra::Engines::Maxwell3D::Regs;
18
19// TODO(Rodrigo): Optimize this structure.
20
21struct 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 noexcept;
34
35 bool operator==(const VertexBinding& rhs) const noexcept;
36
37 bool operator!=(const VertexBinding& rhs) const noexcept {
38 return !operator==(rhs);
39 }
40 };
41
42 struct VertexAttribute {
43 constexpr VertexAttribute(u32 index, u32 buffer, Maxwell::VertexAttribute::Type type,
44 Maxwell::VertexAttribute::Size size, u32 offset)
45 : index{index}, buffer{buffer}, type{type}, size{size}, offset{offset} {}
46 VertexAttribute() = default;
47
48 u32 index;
49 u32 buffer;
50 Maxwell::VertexAttribute::Type type;
51 Maxwell::VertexAttribute::Size size;
52 u32 offset;
53
54 std::size_t Hash() const noexcept;
55
56 bool operator==(const VertexAttribute& rhs) const noexcept;
57
58 bool operator!=(const VertexAttribute& rhs) const noexcept {
59 return !operator==(rhs);
60 }
61 };
62
63 struct StencilFace {
64 constexpr StencilFace(Maxwell::StencilOp action_stencil_fail,
65 Maxwell::StencilOp action_depth_fail,
66 Maxwell::StencilOp action_depth_pass, Maxwell::ComparisonOp test_func)
67 : action_stencil_fail{action_stencil_fail}, action_depth_fail{action_depth_fail},
68 action_depth_pass{action_depth_pass}, test_func{test_func} {}
69 StencilFace() = default;
70
71 Maxwell::StencilOp action_stencil_fail;
72 Maxwell::StencilOp action_depth_fail;
73 Maxwell::StencilOp action_depth_pass;
74 Maxwell::ComparisonOp test_func;
75
76 std::size_t Hash() const noexcept;
77
78 bool operator==(const StencilFace& rhs) const noexcept;
79
80 bool operator!=(const StencilFace& rhs) const noexcept {
81 return !operator==(rhs);
82 }
83 };
84
85 struct BlendingAttachment {
86 constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
87 Maxwell::Blend::Factor src_rgb_func,
88 Maxwell::Blend::Factor dst_rgb_func,
89 Maxwell::Blend::Equation a_equation,
90 Maxwell::Blend::Factor src_a_func,
91 Maxwell::Blend::Factor dst_a_func,
92 std::array<bool, 4> components)
93 : enable{enable}, rgb_equation{rgb_equation}, src_rgb_func{src_rgb_func},
94 dst_rgb_func{dst_rgb_func}, a_equation{a_equation}, src_a_func{src_a_func},
95 dst_a_func{dst_a_func}, components{components} {}
96 BlendingAttachment() = default;
97
98 bool enable;
99 Maxwell::Blend::Equation rgb_equation;
100 Maxwell::Blend::Factor src_rgb_func;
101 Maxwell::Blend::Factor dst_rgb_func;
102 Maxwell::Blend::Equation a_equation;
103 Maxwell::Blend::Factor src_a_func;
104 Maxwell::Blend::Factor dst_a_func;
105 std::array<bool, 4> components;
106
107 std::size_t Hash() const noexcept;
108
109 bool operator==(const BlendingAttachment& rhs) const noexcept;
110
111 bool operator!=(const BlendingAttachment& rhs) const noexcept {
112 return !operator==(rhs);
113 }
114 };
115
116 struct VertexInput {
117 std::size_t num_bindings = 0;
118 std::size_t num_attributes = 0;
119 std::array<VertexBinding, Maxwell::NumVertexArrays> bindings;
120 std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes;
121
122 std::size_t Hash() const noexcept;
123
124 bool operator==(const VertexInput& rhs) const noexcept;
125
126 bool operator!=(const VertexInput& rhs) const noexcept {
127 return !operator==(rhs);
128 }
129 };
130
131 struct InputAssembly {
132 constexpr InputAssembly(Maxwell::PrimitiveTopology topology, bool primitive_restart_enable,
133 float point_size)
134 : topology{topology}, primitive_restart_enable{primitive_restart_enable},
135 point_size{point_size} {}
136 InputAssembly() = default;
137
138 Maxwell::PrimitiveTopology topology;
139 bool primitive_restart_enable;
140 float point_size;
141
142 std::size_t Hash() const noexcept;
143
144 bool operator==(const InputAssembly& rhs) const noexcept;
145
146 bool operator!=(const InputAssembly& rhs) const noexcept {
147 return !operator==(rhs);
148 }
149 };
150
151 struct Tessellation {
152 constexpr Tessellation(u32 patch_control_points, Maxwell::TessellationPrimitive primitive,
153 Maxwell::TessellationSpacing spacing, bool clockwise)
154 : patch_control_points{patch_control_points}, primitive{primitive}, spacing{spacing},
155 clockwise{clockwise} {}
156 Tessellation() = default;
157
158 u32 patch_control_points;
159 Maxwell::TessellationPrimitive primitive;
160 Maxwell::TessellationSpacing spacing;
161 bool clockwise;
162
163 std::size_t Hash() const noexcept;
164
165 bool operator==(const Tessellation& rhs) const noexcept;
166
167 bool operator!=(const Tessellation& rhs) const noexcept {
168 return !operator==(rhs);
169 }
170 };
171
172 struct Rasterizer {
173 constexpr Rasterizer(bool cull_enable, bool depth_bias_enable, bool ndc_minus_one_to_one,
174 Maxwell::Cull::CullFace cull_face, Maxwell::Cull::FrontFace front_face)
175 : cull_enable{cull_enable}, depth_bias_enable{depth_bias_enable},
176 ndc_minus_one_to_one{ndc_minus_one_to_one}, cull_face{cull_face}, front_face{
177 front_face} {}
178 Rasterizer() = default;
179
180 bool cull_enable;
181 bool depth_bias_enable;
182 bool ndc_minus_one_to_one;
183 Maxwell::Cull::CullFace cull_face;
184 Maxwell::Cull::FrontFace front_face;
185
186 std::size_t Hash() const noexcept;
187
188 bool operator==(const Rasterizer& rhs) const noexcept;
189
190 bool operator!=(const Rasterizer& rhs) const noexcept {
191 return !operator==(rhs);
192 }
193 };
194
195 struct DepthStencil {
196 constexpr DepthStencil(bool depth_test_enable, bool depth_write_enable,
197 bool depth_bounds_enable, bool stencil_enable,
198 Maxwell::ComparisonOp depth_test_function, StencilFace front_stencil,
199 StencilFace back_stencil)
200 : depth_test_enable{depth_test_enable}, depth_write_enable{depth_write_enable},
201 depth_bounds_enable{depth_bounds_enable}, stencil_enable{stencil_enable},
202 depth_test_function{depth_test_function}, front_stencil{front_stencil},
203 back_stencil{back_stencil} {}
204 DepthStencil() = default;
205
206 bool depth_test_enable;
207 bool depth_write_enable;
208 bool depth_bounds_enable;
209 bool stencil_enable;
210 Maxwell::ComparisonOp depth_test_function;
211 StencilFace front_stencil;
212 StencilFace back_stencil;
213
214 std::size_t Hash() const noexcept;
215
216 bool operator==(const DepthStencil& rhs) const noexcept;
217
218 bool operator!=(const DepthStencil& rhs) const noexcept {
219 return !operator==(rhs);
220 }
221 };
222
223 struct ColorBlending {
224 constexpr ColorBlending(
225 std::array<float, 4> blend_constants, std::size_t attachments_count,
226 std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments)
227 : attachments_count{attachments_count}, attachments{attachments} {}
228 ColorBlending() = default;
229
230 std::size_t attachments_count;
231 std::array<BlendingAttachment, Maxwell::NumRenderTargets> attachments;
232
233 std::size_t Hash() const noexcept;
234
235 bool operator==(const ColorBlending& rhs) const noexcept;
236
237 bool operator!=(const ColorBlending& rhs) const noexcept {
238 return !operator==(rhs);
239 }
240 };
241
242 std::size_t Hash() const noexcept;
243
244 bool operator==(const FixedPipelineState& rhs) const noexcept;
245
246 bool operator!=(const FixedPipelineState& rhs) const noexcept {
247 return !operator==(rhs);
248 }
249
250 VertexInput vertex_input;
251 InputAssembly input_assembly;
252 Tessellation tessellation;
253 Rasterizer rasterizer;
254 DepthStencil depth_stencil;
255 ColorBlending color_blending;
256};
257static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexBinding>);
258static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexAttribute>);
259static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>);
260static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>);
261static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>);
262static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>);
263static_assert(std::is_trivially_copyable_v<FixedPipelineState::Tessellation>);
264static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>);
265static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>);
266static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>);
267static_assert(std::is_trivially_copyable_v<FixedPipelineState>);
268
269FixedPipelineState GetFixedPipelineState(const Maxwell& regs);
270
271} // namespace Vulkan
272
273namespace std {
274
275template <>
276struct hash<Vulkan::FixedPipelineState> {
277 std::size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept {
278 return k.Hash();
279 }
280};
281
282} // namespace std