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