1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright 2020, Blender Foundation.
17 */
18
19 /** \file
20 * \ingroup gpu
21 */
22
23 #pragma once
24
25 #include "BLI_utildefines.h"
26
27 #include "GPU_state.h"
28
29 #include "gpu_texture_private.hh"
30
31 #include <cstring>
32
33 namespace blender {
34 namespace gpu {
35
36 /* Encapsulate all pipeline state that we need to track.
37 * Try to keep small to reduce validation time. */
38 union GPUState {
39 struct {
40 /** eGPUWriteMask */
41 uint32_t write_mask : 13;
42 /** eGPUBlend */
43 uint32_t blend : 4;
44 /** eGPUFaceCullTest */
45 uint32_t culling_test : 2;
46 /** eGPUDepthTest */
47 uint32_t depth_test : 3;
48 /** eGPUStencilTest */
49 uint32_t stencil_test : 3;
50 /** eGPUStencilOp */
51 uint32_t stencil_op : 3;
52 /** eGPUProvokingVertex */
53 uint32_t provoking_vert : 1;
54 /** Enable bits. */
55 uint32_t logic_op_xor : 1;
56 uint32_t invert_facing : 1;
57 uint32_t shadow_bias : 1;
58 /** Number of clip distances enabled. */
59 /* TODO(fclem): This should be a shader property. */
60 uint32_t clip_distances : 3;
61 /* TODO(fclem): remove, old opengl features. */
62 uint32_t polygon_smooth : 1;
63 uint32_t line_smooth : 1;
64 };
65 /* Here to allow fast bitwise ops. */
66 uint64_t data;
67 };
68
69 BLI_STATIC_ASSERT(sizeof(GPUState) == sizeof(uint64_t), "GPUState is too big.");
70
operator ==(const GPUState & a,const GPUState & b)71 inline bool operator==(const GPUState &a, const GPUState &b)
72 {
73 return a.data == b.data;
74 }
75
operator !=(const GPUState & a,const GPUState & b)76 inline bool operator!=(const GPUState &a, const GPUState &b)
77 {
78 return !(a == b);
79 }
80
operator ^(const GPUState & a,const GPUState & b)81 inline GPUState operator^(const GPUState &a, const GPUState &b)
82 {
83 GPUState r;
84 r.data = a.data ^ b.data;
85 return r;
86 }
87
operator ~(const GPUState & a)88 inline GPUState operator~(const GPUState &a)
89 {
90 GPUState r;
91 r.data = ~a.data;
92 return r;
93 }
94
95 /* Mutable state that does not require pipeline change. */
96 union GPUStateMutable {
97 struct {
98 /* Viewport State */
99 /** TODO remove */
100 float depth_range[2];
101 /** Positive if using program point size. */
102 /* TODO(fclem): should be passed as uniform to all shaders. */
103 float point_size;
104 /** Not supported on every platform. Prefer using wideline shader. */
105 float line_width;
106 /** Mutable stencil states. */
107 uint8_t stencil_write_mask;
108 uint8_t stencil_compare_mask;
109 uint8_t stencil_reference;
110 uint8_t _pad0;
111 /* IMPORTANT: ensure x64 stuct alignment. */
112 };
113 /* Here to allow fast bitwise ops. */
114 uint64_t data[9];
115 };
116
117 BLI_STATIC_ASSERT(sizeof(GPUStateMutable) == sizeof(GPUStateMutable::data),
118 "GPUStateMutable is too big.");
119
operator ==(const GPUStateMutable & a,const GPUStateMutable & b)120 inline bool operator==(const GPUStateMutable &a, const GPUStateMutable &b)
121 {
122 return memcmp(&a, &b, sizeof(GPUStateMutable)) == 0;
123 }
124
operator !=(const GPUStateMutable & a,const GPUStateMutable & b)125 inline bool operator!=(const GPUStateMutable &a, const GPUStateMutable &b)
126 {
127 return !(a == b);
128 }
129
operator ^(const GPUStateMutable & a,const GPUStateMutable & b)130 inline GPUStateMutable operator^(const GPUStateMutable &a, const GPUStateMutable &b)
131 {
132 GPUStateMutable r;
133 for (int i = 0; i < ARRAY_SIZE(a.data); i++) {
134 r.data[i] = a.data[i] ^ b.data[i];
135 }
136 return r;
137 }
138
operator ~(const GPUStateMutable & a)139 inline GPUStateMutable operator~(const GPUStateMutable &a)
140 {
141 GPUStateMutable r;
142 for (int i = 0; i < ARRAY_SIZE(a.data); i++) {
143 r.data[i] = ~a.data[i];
144 }
145 return r;
146 }
147
148 /**
149 * State manager keeping track of the draw state and applying it before drawing.
150 * Base class which is then specialized for each implementation (GL, VK, ...).
151 **/
152 class StateManager {
153 public:
154 GPUState state;
155 GPUStateMutable mutable_state;
156 bool use_bgl = false;
157
158 public:
159 StateManager();
~StateManager()160 virtual ~StateManager(){};
161
162 virtual void apply_state(void) = 0;
163 virtual void force_state(void) = 0;
164
165 virtual void issue_barrier(eGPUBarrier barrier_bits) = 0;
166
167 virtual void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) = 0;
168 virtual void texture_unbind(Texture *tex) = 0;
169 virtual void texture_unbind_all(void) = 0;
170
171 virtual void image_bind(Texture *tex, int unit) = 0;
172 virtual void image_unbind(Texture *tex) = 0;
173 virtual void image_unbind_all(void) = 0;
174
175 virtual void texture_unpack_row_length_set(uint len) = 0;
176 };
177
178 } // namespace gpu
179 } // namespace blender
180