summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-12-22 22:48:43 -0300
committerGravatar ReinUsesLisp2019-12-22 22:59:11 -0300
commit4a3026b16b0be26d80f5a7429755e19ee8d494a4 (patch)
treeae18e69016611568db112dbf0e5700c43f1fbed5
parentmaxwell_3d: Add depth bounds registers (diff)
downloadyuzu-4a3026b16b0be26d80f5a7429755e19ee8d494a4.tar.gz
yuzu-4a3026b16b0be26d80f5a7429755e19ee8d494a4.tar.xz
yuzu-4a3026b16b0be26d80f5a7429755e19ee8d494a4.zip
fixed_pipeline_state: Define structure and loaders
The intention behind this hasheable structure is to describe the state of fixed function pipeline state that gets compiled to a single graphics pipeline state object. This is all dynamic state in OpenGL but Vulkan wants it in an immutable state, even if hardware can edit it freely. In this commit the structure is defined in an optimized state (it uses booleans, has paddings and many data entries that can be packed to single integers). This is intentional as an initial implementation that is easier to debug, implement and review. It will be optimized in later stages, or it might change if Vulkan gets more dynamic states.
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp295
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h231
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
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/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
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 {
129 return (index << stride) ^ divisor;
130}
131
132bool FixedPipelineState::VertexBinding::operator==(const VertexBinding& rhs) const {
133 return std::tie(index, stride, divisor) == std::tie(rhs.index, rhs.stride, rhs.divisor);
134}
135
136std::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
142bool 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
147std::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
154bool 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
160std::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
173bool 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
180std::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
191bool 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
198std::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
205bool 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
210std::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
216bool 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
221std::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
229bool 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
235std::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
246bool 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
254std::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
262bool 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
267std::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
278bool 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
285FixedPipelineState 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
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;
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};
206static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexBinding>);
207static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexAttribute>);
208static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>);
209static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>);
210static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>);
211static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>);
212static_assert(std::is_trivially_copyable_v<FixedPipelineState::Tessellation>);
213static_assert(std::is_trivially_copyable_v<FixedPipelineState::Rasterizer>);
214static_assert(std::is_trivially_copyable_v<FixedPipelineState::DepthStencil>);
215static_assert(std::is_trivially_copyable_v<FixedPipelineState::ColorBlending>);
216static_assert(std::is_trivially_copyable_v<FixedPipelineState>);
217
218FixedPipelineState GetFixedPipelineState(const Maxwell& regs);
219
220} // namespace Vulkan
221
222namespace std {
223
224template <>
225struct hash<Vulkan::FixedPipelineState> {
226 std::size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept {
227 return k.Hash();
228 }
229};
230
231} // namespace std