1 // Copyright 2020 yuzu Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #include <algorithm>
6 #include <cstddef>
7 #include <iterator>
8 
9 #include "common/common_types.h"
10 #include "core/core.h"
11 #include "video_core/dirty_flags.h"
12 #include "video_core/engines/maxwell_3d.h"
13 #include "video_core/gpu.h"
14 #include "video_core/renderer_vulkan/vk_state_tracker.h"
15 
16 #define OFF(field_name) MAXWELL3D_REG_INDEX(field_name)
17 #define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / (sizeof(u32)))
18 
19 namespace Vulkan {
20 
21 namespace {
22 
23 using namespace Dirty;
24 using namespace VideoCommon::Dirty;
25 using Tegra::Engines::Maxwell3D;
26 using Regs = Maxwell3D::Regs;
27 using Tables = Maxwell3D::DirtyState::Tables;
28 using Table = Maxwell3D::DirtyState::Table;
29 using Flags = Maxwell3D::DirtyState::Flags;
30 
MakeInvalidationFlags()31 Flags MakeInvalidationFlags() {
32     Flags flags{};
33     flags[Viewports] = true;
34     flags[Scissors] = true;
35     flags[DepthBias] = true;
36     flags[BlendConstants] = true;
37     flags[DepthBounds] = true;
38     flags[StencilProperties] = true;
39     flags[CullMode] = true;
40     flags[DepthBoundsEnable] = true;
41     flags[DepthTestEnable] = true;
42     flags[DepthWriteEnable] = true;
43     flags[DepthCompareOp] = true;
44     flags[FrontFace] = true;
45     flags[StencilOp] = true;
46     flags[StencilTestEnable] = true;
47     return flags;
48 }
49 
SetupDirtyViewports(Tables & tables)50 void SetupDirtyViewports(Tables& tables) {
51     FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
52     FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
53     tables[0][OFF(viewport_transform_enabled)] = Viewports;
54 }
55 
SetupDirtyScissors(Tables & tables)56 void SetupDirtyScissors(Tables& tables) {
57     FillBlock(tables[0], OFF(scissor_test), NUM(scissor_test), Scissors);
58 }
59 
SetupDirtyDepthBias(Tables & tables)60 void SetupDirtyDepthBias(Tables& tables) {
61     auto& table = tables[0];
62     table[OFF(polygon_offset_units)] = DepthBias;
63     table[OFF(polygon_offset_clamp)] = DepthBias;
64     table[OFF(polygon_offset_factor)] = DepthBias;
65 }
66 
SetupDirtyBlendConstants(Tables & tables)67 void SetupDirtyBlendConstants(Tables& tables) {
68     FillBlock(tables[0], OFF(blend_color), NUM(blend_color), BlendConstants);
69 }
70 
SetupDirtyDepthBounds(Tables & tables)71 void SetupDirtyDepthBounds(Tables& tables) {
72     FillBlock(tables[0], OFF(depth_bounds), NUM(depth_bounds), DepthBounds);
73 }
74 
SetupDirtyStencilProperties(Tables & tables)75 void SetupDirtyStencilProperties(Tables& tables) {
76     auto& table = tables[0];
77     table[OFF(stencil_two_side_enable)] = StencilProperties;
78     table[OFF(stencil_front_func_ref)] = StencilProperties;
79     table[OFF(stencil_front_mask)] = StencilProperties;
80     table[OFF(stencil_front_func_mask)] = StencilProperties;
81     table[OFF(stencil_back_func_ref)] = StencilProperties;
82     table[OFF(stencil_back_mask)] = StencilProperties;
83     table[OFF(stencil_back_func_mask)] = StencilProperties;
84 }
85 
SetupDirtyCullMode(Tables & tables)86 void SetupDirtyCullMode(Tables& tables) {
87     auto& table = tables[0];
88     table[OFF(cull_face)] = CullMode;
89     table[OFF(cull_test_enabled)] = CullMode;
90 }
91 
SetupDirtyDepthBoundsEnable(Tables & tables)92 void SetupDirtyDepthBoundsEnable(Tables& tables) {
93     tables[0][OFF(depth_bounds_enable)] = DepthBoundsEnable;
94 }
95 
SetupDirtyDepthTestEnable(Tables & tables)96 void SetupDirtyDepthTestEnable(Tables& tables) {
97     tables[0][OFF(depth_test_enable)] = DepthTestEnable;
98 }
99 
SetupDirtyDepthWriteEnable(Tables & tables)100 void SetupDirtyDepthWriteEnable(Tables& tables) {
101     tables[0][OFF(depth_write_enabled)] = DepthWriteEnable;
102 }
103 
SetupDirtyDepthCompareOp(Tables & tables)104 void SetupDirtyDepthCompareOp(Tables& tables) {
105     tables[0][OFF(depth_test_func)] = DepthCompareOp;
106 }
107 
SetupDirtyFrontFace(Tables & tables)108 void SetupDirtyFrontFace(Tables& tables) {
109     auto& table = tables[0];
110     table[OFF(front_face)] = FrontFace;
111     table[OFF(screen_y_control)] = FrontFace;
112 }
113 
SetupDirtyStencilOp(Tables & tables)114 void SetupDirtyStencilOp(Tables& tables) {
115     auto& table = tables[0];
116     table[OFF(stencil_front_op_fail)] = StencilOp;
117     table[OFF(stencil_front_op_zfail)] = StencilOp;
118     table[OFF(stencil_front_op_zpass)] = StencilOp;
119     table[OFF(stencil_front_func_func)] = StencilOp;
120     table[OFF(stencil_back_op_fail)] = StencilOp;
121     table[OFF(stencil_back_op_zfail)] = StencilOp;
122     table[OFF(stencil_back_op_zpass)] = StencilOp;
123     table[OFF(stencil_back_func_func)] = StencilOp;
124 
125     // Table 0 is used by StencilProperties
126     tables[1][OFF(stencil_two_side_enable)] = StencilOp;
127 }
128 
SetupDirtyStencilTestEnable(Tables & tables)129 void SetupDirtyStencilTestEnable(Tables& tables) {
130     tables[0][OFF(stencil_enable)] = StencilTestEnable;
131 }
132 
133 } // Anonymous namespace
134 
StateTracker(Tegra::GPU & gpu)135 StateTracker::StateTracker(Tegra::GPU& gpu)
136     : flags{gpu.Maxwell3D().dirty.flags}, invalidation_flags{MakeInvalidationFlags()} {
137     auto& tables = gpu.Maxwell3D().dirty.tables;
138     SetupDirtyRenderTargets(tables);
139     SetupDirtyViewports(tables);
140     SetupDirtyScissors(tables);
141     SetupDirtyDepthBias(tables);
142     SetupDirtyBlendConstants(tables);
143     SetupDirtyDepthBounds(tables);
144     SetupDirtyStencilProperties(tables);
145     SetupDirtyCullMode(tables);
146     SetupDirtyDepthBoundsEnable(tables);
147     SetupDirtyDepthTestEnable(tables);
148     SetupDirtyDepthWriteEnable(tables);
149     SetupDirtyDepthCompareOp(tables);
150     SetupDirtyFrontFace(tables);
151     SetupDirtyStencilOp(tables);
152     SetupDirtyStencilTestEnable(tables);
153 }
154 
155 } // namespace Vulkan
156