summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-04-18 00:05:41 -0300
committerGravatar ReinUsesLisp2020-04-18 19:22:11 -0300
commit7790144a55cf1ee05e79a2b842ba38aa510fea29 (patch)
treef11e274963af534d96a73f8a2d436c9739d9fdcf /src
parentfixed_pipeline_state: Pack attribute state (diff)
downloadyuzu-7790144a55cf1ee05e79a2b842ba38aa510fea29.tar.gz
yuzu-7790144a55cf1ee05e79a2b842ba38aa510fea29.tar.xz
yuzu-7790144a55cf1ee05e79a2b842ba38aa510fea29.zip
fixed_pipeline_state: Pack depth stencil state
Reduce FixedPipelineState's size to 632 bytes.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp120
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h97
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp20
3 files changed, 140 insertions, 97 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index 97aab951a..8734045e5 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -12,23 +12,32 @@
12 12
13namespace Vulkan { 13namespace Vulkan {
14 14
15namespace { 15void FixedPipelineState::DepthStencil::Fill(const Maxwell& regs) noexcept {
16 16 raw = 0;
17constexpr FixedPipelineState::DepthStencil GetDepthStencilState(const Maxwell& regs) { 17 front.action_stencil_fail.Assign(PackStencilOp(regs.stencil_front_op_fail));
18 const FixedPipelineState::StencilFace front_stencil( 18 front.action_depth_fail.Assign(PackStencilOp(regs.stencil_front_op_zfail));
19 regs.stencil_front_op_fail, regs.stencil_front_op_zfail, regs.stencil_front_op_zpass, 19 front.action_depth_pass.Assign(PackStencilOp(regs.stencil_front_op_zpass));
20 regs.stencil_front_func_func); 20 front.test_func.Assign(PackComparisonOp(regs.stencil_front_func_func));
21 const FixedPipelineState::StencilFace back_stencil = 21 if (regs.stencil_two_side_enable) {
22 regs.stencil_two_side_enable 22 back.action_stencil_fail.Assign(PackStencilOp(regs.stencil_back_op_fail));
23 ? FixedPipelineState::StencilFace(regs.stencil_back_op_fail, regs.stencil_back_op_zfail, 23 back.action_depth_fail.Assign(PackStencilOp(regs.stencil_back_op_zfail));
24 regs.stencil_back_op_zpass, 24 back.action_depth_pass.Assign(PackStencilOp(regs.stencil_back_op_zpass));
25 regs.stencil_back_func_func) 25 back.test_func.Assign(PackComparisonOp(regs.stencil_back_func_func));
26 : front_stencil; 26 } else {
27 return FixedPipelineState::DepthStencil( 27 back.action_stencil_fail.Assign(front.action_stencil_fail);
28 regs.depth_test_enable == 1, regs.depth_write_enabled == 1, regs.depth_bounds_enable == 1, 28 back.action_depth_fail.Assign(front.action_depth_fail);
29 regs.stencil_enable == 1, regs.depth_test_func, front_stencil, back_stencil); 29 back.action_depth_pass.Assign(front.action_depth_pass);
30 back.test_func.Assign(front.test_func);
31 }
32 depth_test_enable.Assign(regs.depth_test_enable);
33 depth_write_enable.Assign(regs.depth_write_enabled);
34 depth_bounds_enable.Assign(regs.depth_bounds_enable);
35 stencil_enable.Assign(regs.stencil_enable);
36 depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
30} 37}
31 38
39namespace {
40
32constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) { 41constexpr FixedPipelineState::InputAssembly GetInputAssemblyState(const Maxwell& regs) {
33 return FixedPipelineState::InputAssembly( 42 return FixedPipelineState::InputAssembly(
34 regs.draw.topology, regs.primitive_restart.enabled, 43 regs.draw.topology, regs.primitive_restart.enabled,
@@ -129,19 +138,6 @@ constexpr FixedPipelineState::Rasterizer GetRasterizerState(const Maxwell& regs)
129 138
130} // Anonymous namespace 139} // Anonymous namespace
131 140
132std::size_t FixedPipelineState::StencilFace::Hash() const noexcept {
133 return static_cast<std::size_t>(action_stencil_fail) ^
134 (static_cast<std::size_t>(action_depth_fail) << 4) ^
135 (static_cast<std::size_t>(action_depth_fail) << 20) ^
136 (static_cast<std::size_t>(action_depth_pass) << 36);
137}
138
139bool FixedPipelineState::StencilFace::operator==(const StencilFace& rhs) const noexcept {
140 return std::tie(action_stencil_fail, action_depth_fail, action_depth_pass, test_func) ==
141 std::tie(rhs.action_stencil_fail, rhs.action_depth_fail, rhs.action_depth_pass,
142 rhs.test_func);
143}
144
145std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept { 141std::size_t FixedPipelineState::BlendingAttachment::Hash() const noexcept {
146 return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^ 142 return static_cast<std::size_t>(enable) ^ (static_cast<std::size_t>(rgb_equation) << 5) ^
147 (static_cast<std::size_t>(src_rgb_func) << 10) ^ 143 (static_cast<std::size_t>(src_rgb_func) << 10) ^
@@ -212,22 +208,11 @@ bool FixedPipelineState::Rasterizer::operator==(const Rasterizer& rhs) const noe
212} 208}
213 209
214std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept { 210std::size_t FixedPipelineState::DepthStencil::Hash() const noexcept {
215 std::size_t hash = static_cast<std::size_t>(depth_test_enable) ^ 211 return raw;
216 (static_cast<std::size_t>(depth_write_enable) << 1) ^
217 (static_cast<std::size_t>(depth_bounds_enable) << 2) ^
218 (static_cast<std::size_t>(stencil_enable) << 3) ^
219 (static_cast<std::size_t>(depth_test_function) << 4);
220 boost::hash_combine(hash, front_stencil.Hash());
221 boost::hash_combine(hash, back_stencil.Hash());
222 return hash;
223} 212}
224 213
225bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept { 214bool FixedPipelineState::DepthStencil::operator==(const DepthStencil& rhs) const noexcept {
226 return std::tie(depth_test_enable, depth_write_enable, depth_bounds_enable, depth_test_function, 215 return raw == rhs.raw;
227 stencil_enable, front_stencil, back_stencil) ==
228 std::tie(rhs.depth_test_enable, rhs.depth_write_enable, rhs.depth_bounds_enable,
229 rhs.depth_test_function, rhs.stencil_enable, rhs.front_stencil,
230 rhs.back_stencil);
231} 216}
232 217
233std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept { 218std::size_t FixedPipelineState::ColorBlending::Hash() const noexcept {
@@ -266,9 +251,60 @@ FixedPipelineState GetFixedPipelineState(const Maxwell& regs) {
266 fixed_state.input_assembly = GetInputAssemblyState(regs); 251 fixed_state.input_assembly = GetInputAssemblyState(regs);
267 fixed_state.tessellation = GetTessellationState(regs); 252 fixed_state.tessellation = GetTessellationState(regs);
268 fixed_state.rasterizer = GetRasterizerState(regs); 253 fixed_state.rasterizer = GetRasterizerState(regs);
269 fixed_state.depth_stencil = GetDepthStencilState(regs); 254 fixed_state.depth_stencil.Fill(regs);
270 fixed_state.color_blending = GetColorBlendingState(regs); 255 fixed_state.color_blending = GetColorBlendingState(regs);
271 return fixed_state; 256 return fixed_state;
272} 257}
273 258
259u32 FixedPipelineState::PackComparisonOp(Maxwell::ComparisonOp op) noexcept {
260 // OpenGL enums go from 0x200 to 0x207 and the others from 1 to 8
261 // If we substract 0x200 to OpenGL enums and 1 to the others we get a 0-7 range.
262 // Perfect for a hash.
263 const u32 value = static_cast<u32>(op);
264 return value - (value >= 0x200 ? 0x200 : 1);
265}
266
267Maxwell::ComparisonOp FixedPipelineState::UnpackComparisonOp(u32 packed) noexcept {
268 // Read PackComparisonOp for the logic behind this.
269 return static_cast<Maxwell::ComparisonOp>(packed + 1);
270}
271
272u32 FixedPipelineState::PackStencilOp(Maxwell::StencilOp op) noexcept {
273 switch (op) {
274 case Maxwell::StencilOp::Keep:
275 case Maxwell::StencilOp::KeepOGL:
276 return 0;
277 case Maxwell::StencilOp::Zero:
278 case Maxwell::StencilOp::ZeroOGL:
279 return 1;
280 case Maxwell::StencilOp::Replace:
281 case Maxwell::StencilOp::ReplaceOGL:
282 return 2;
283 case Maxwell::StencilOp::Incr:
284 case Maxwell::StencilOp::IncrOGL:
285 return 3;
286 case Maxwell::StencilOp::Decr:
287 case Maxwell::StencilOp::DecrOGL:
288 return 4;
289 case Maxwell::StencilOp::Invert:
290 case Maxwell::StencilOp::InvertOGL:
291 return 5;
292 case Maxwell::StencilOp::IncrWrap:
293 case Maxwell::StencilOp::IncrWrapOGL:
294 return 6;
295 case Maxwell::StencilOp::DecrWrap:
296 case Maxwell::StencilOp::DecrWrapOGL:
297 return 7;
298 }
299 return 0;
300}
301
302Maxwell::StencilOp FixedPipelineState::UnpackStencilOp(u32 packed) noexcept {
303 static constexpr std::array LUT = {Maxwell::StencilOp::Keep, Maxwell::StencilOp::Zero,
304 Maxwell::StencilOp::Replace, Maxwell::StencilOp::Incr,
305 Maxwell::StencilOp::Decr, Maxwell::StencilOp::Invert,
306 Maxwell::StencilOp::IncrWrap, Maxwell::StencilOp::DecrWrap};
307 return LUT[packed];
308}
309
274} // namespace Vulkan 310} // 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 d82a82f75..e30877e77 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -24,27 +24,11 @@ inline constexpr bool IsHashable = std::has_unique_object_representations_v<T>&&
24 std::is_trivially_copyable_v<T>&& std::is_trivially_constructible_v<T>; 24 std::is_trivially_copyable_v<T>&& std::is_trivially_constructible_v<T>;
25 25
26struct FixedPipelineState { 26struct FixedPipelineState {
27 struct StencilFace { 27 static u32 PackComparisonOp(Maxwell::ComparisonOp op) noexcept;
28 constexpr StencilFace(Maxwell::StencilOp action_stencil_fail, 28 static Maxwell::ComparisonOp UnpackComparisonOp(u32 packed) noexcept;
29 Maxwell::StencilOp action_depth_fail,
30 Maxwell::StencilOp action_depth_pass, Maxwell::ComparisonOp test_func)
31 : action_stencil_fail{action_stencil_fail}, action_depth_fail{action_depth_fail},
32 action_depth_pass{action_depth_pass}, test_func{test_func} {}
33 StencilFace() = default;
34
35 Maxwell::StencilOp action_stencil_fail;
36 Maxwell::StencilOp action_depth_fail;
37 Maxwell::StencilOp action_depth_pass;
38 Maxwell::ComparisonOp test_func;
39 29
40 std::size_t Hash() const noexcept; 30 static u32 PackStencilOp(Maxwell::StencilOp op) noexcept;
41 31 static Maxwell::StencilOp UnpackStencilOp(u32 packed) noexcept;
42 bool operator==(const StencilFace& rhs) const noexcept;
43
44 bool operator!=(const StencilFace& rhs) const noexcept {
45 return !operator==(rhs);
46 }
47 };
48 32
49 struct BlendingAttachment { 33 struct BlendingAttachment {
50 constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation, 34 constexpr BlendingAttachment(bool enable, Maxwell::Blend::Equation rgb_equation,
@@ -202,23 +186,42 @@ struct FixedPipelineState {
202 }; 186 };
203 187
204 struct DepthStencil { 188 struct DepthStencil {
205 constexpr DepthStencil(bool depth_test_enable, bool depth_write_enable, 189 template <std::size_t Position>
206 bool depth_bounds_enable, bool stencil_enable, 190 union StencilFace {
207 Maxwell::ComparisonOp depth_test_function, StencilFace front_stencil, 191 BitField<Position + 0, 3, u32> action_stencil_fail;
208 StencilFace back_stencil) 192 BitField<Position + 3, 3, u32> action_depth_fail;
209 : depth_test_enable{depth_test_enable}, depth_write_enable{depth_write_enable}, 193 BitField<Position + 6, 3, u32> action_depth_pass;
210 depth_bounds_enable{depth_bounds_enable}, stencil_enable{stencil_enable}, 194 BitField<Position + 9, 3, u32> test_func;
211 depth_test_function{depth_test_function}, front_stencil{front_stencil}, 195
212 back_stencil{back_stencil} {} 196 Maxwell::StencilOp ActionStencilFail() const noexcept {
213 DepthStencil() = default; 197 return UnpackStencilOp(action_stencil_fail);
214 198 }
215 bool depth_test_enable; 199
216 bool depth_write_enable; 200 Maxwell::StencilOp ActionDepthFail() const noexcept {
217 bool depth_bounds_enable; 201 return UnpackStencilOp(action_depth_fail);
218 bool stencil_enable; 202 }
219 Maxwell::ComparisonOp depth_test_function; 203
220 StencilFace front_stencil; 204 Maxwell::StencilOp ActionDepthPass() const noexcept {
221 StencilFace back_stencil; 205 return UnpackStencilOp(action_depth_pass);
206 }
207
208 Maxwell::ComparisonOp TestFunc() const noexcept {
209 return UnpackComparisonOp(test_func);
210 }
211 };
212
213 union {
214 u32 raw;
215 StencilFace<0> front;
216 StencilFace<12> back;
217 BitField<24, 1, u32> depth_test_enable;
218 BitField<25, 1, u32> depth_write_enable;
219 BitField<26, 1, u32> depth_bounds_enable;
220 BitField<27, 1, u32> stencil_enable;
221 BitField<28, 3, u32> depth_test_func;
222 };
223
224 void Fill(const Maxwell& regs) noexcept;
222 225
223 std::size_t Hash() const noexcept; 226 std::size_t Hash() const noexcept;
224 227
@@ -227,7 +230,12 @@ struct FixedPipelineState {
227 bool operator!=(const DepthStencil& rhs) const noexcept { 230 bool operator!=(const DepthStencil& rhs) const noexcept {
228 return !operator==(rhs); 231 return !operator==(rhs);
229 } 232 }
233
234 Maxwell::ComparisonOp DepthTestFunc() const noexcept {
235 return UnpackComparisonOp(depth_test_func);
236 }
230 }; 237 };
238 static_assert(IsHashable<DepthStencil>);
231 239
232 struct ColorBlending { 240 struct ColorBlending {
233 constexpr ColorBlending( 241 constexpr ColorBlending(
@@ -248,6 +256,13 @@ struct FixedPipelineState {
248 } 256 }
249 }; 257 };
250 258
259 VertexInput vertex_input;
260 InputAssembly input_assembly;
261 Tessellation tessellation;
262 Rasterizer rasterizer;
263 DepthStencil depth_stencil;
264 ColorBlending color_blending;
265
251 std::size_t Hash() const noexcept; 266 std::size_t Hash() const noexcept;
252 267
253 bool operator==(const FixedPipelineState& rhs) const noexcept; 268 bool operator==(const FixedPipelineState& rhs) const noexcept;
@@ -255,15 +270,7 @@ struct FixedPipelineState {
255 bool operator!=(const FixedPipelineState& rhs) const noexcept { 270 bool operator!=(const FixedPipelineState& rhs) const noexcept {
256 return !operator==(rhs); 271 return !operator==(rhs);
257 } 272 }
258
259 VertexInput vertex_input;
260 InputAssembly input_assembly;
261 Tessellation tessellation;
262 Rasterizer rasterizer;
263 DepthStencil depth_stencil;
264 ColorBlending color_blending;
265}; 273};
266static_assert(std::is_trivially_copyable_v<FixedPipelineState::StencilFace>);
267static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>); 274static_assert(std::is_trivially_copyable_v<FixedPipelineState::BlendingAttachment>);
268static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>); 275static_assert(std::is_trivially_copyable_v<FixedPipelineState::VertexInput>);
269static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>); 276static_assert(std::is_trivially_copyable_v<FixedPipelineState::InputAssembly>);
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 718feafbd..0dd3ea5bc 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -26,12 +26,13 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache);
26 26
27namespace { 27namespace {
28 28
29VkStencilOpState GetStencilFaceState(const FixedPipelineState::StencilFace& face) { 29template <class StencilFace>
30VkStencilOpState GetStencilFaceState(const StencilFace& face) {
30 VkStencilOpState state; 31 VkStencilOpState state;
31 state.failOp = MaxwellToVK::StencilOp(face.action_stencil_fail); 32 state.failOp = MaxwellToVK::StencilOp(face.ActionStencilFail());
32 state.passOp = MaxwellToVK::StencilOp(face.action_depth_pass); 33 state.passOp = MaxwellToVK::StencilOp(face.ActionDepthPass());
33 state.depthFailOp = MaxwellToVK::StencilOp(face.action_depth_fail); 34 state.depthFailOp = MaxwellToVK::StencilOp(face.ActionDepthFail());
34 state.compareOp = MaxwellToVK::ComparisonOp(face.test_func); 35 state.compareOp = MaxwellToVK::ComparisonOp(face.TestFunc());
35 state.compareMask = 0; 36 state.compareMask = 0;
36 state.writeMask = 0; 37 state.writeMask = 0;
37 state.reference = 0; 38 state.reference = 0;
@@ -277,13 +278,12 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
277 depth_stencil_ci.flags = 0; 278 depth_stencil_ci.flags = 0;
278 depth_stencil_ci.depthTestEnable = ds.depth_test_enable; 279 depth_stencil_ci.depthTestEnable = ds.depth_test_enable;
279 depth_stencil_ci.depthWriteEnable = ds.depth_write_enable; 280 depth_stencil_ci.depthWriteEnable = ds.depth_write_enable;
280 depth_stencil_ci.depthCompareOp = ds.depth_test_enable 281 depth_stencil_ci.depthCompareOp =
281 ? MaxwellToVK::ComparisonOp(ds.depth_test_function) 282 ds.depth_test_enable ? MaxwellToVK::ComparisonOp(ds.DepthTestFunc()) : VK_COMPARE_OP_ALWAYS;
282 : VK_COMPARE_OP_ALWAYS;
283 depth_stencil_ci.depthBoundsTestEnable = ds.depth_bounds_enable; 283 depth_stencil_ci.depthBoundsTestEnable = ds.depth_bounds_enable;
284 depth_stencil_ci.stencilTestEnable = ds.stencil_enable; 284 depth_stencil_ci.stencilTestEnable = ds.stencil_enable;
285 depth_stencil_ci.front = GetStencilFaceState(ds.front_stencil); 285 depth_stencil_ci.front = GetStencilFaceState(ds.front);
286 depth_stencil_ci.back = GetStencilFaceState(ds.back_stencil); 286 depth_stencil_ci.back = GetStencilFaceState(ds.back);
287 depth_stencil_ci.minDepthBounds = 0.0f; 287 depth_stencil_ci.minDepthBounds = 0.0f;
288 depth_stencil_ci.maxDepthBounds = 0.0f; 288 depth_stencil_ci.maxDepthBounds = 0.0f;
289 289