CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/GPU/Common/ShaderId.h
Views: 1401
1
#pragma once
2
3
#include <string>
4
#include <cstring>
5
#include <cstdint>
6
7
#include "Common/CommonFuncs.h"
8
9
// VS_BIT_LIGHT_UBERSHADER indicates that some groups of these will be
10
// sent to the shader and processed there. This cuts down the number of shaders ("ubershader approach").
11
enum VShaderBit : uint8_t {
12
VS_BIT_LMODE = 0,
13
VS_BIT_IS_THROUGH = 1,
14
// bit 2 is free.
15
VS_BIT_HAS_COLOR = 3,
16
// bit 4 is free.
17
VS_BIT_VERTEX_RANGE_CULLING = 5,
18
VS_BIT_SIMPLE_STEREO = 6,
19
// 7 is free.
20
VS_BIT_USE_HW_TRANSFORM = 8,
21
VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform
22
VS_BIT_NORM_REVERSE = 10,
23
VS_BIT_HAS_TEXCOORD = 11,
24
VS_BIT_HAS_COLOR_TESS = 12, // 1 bit
25
VS_BIT_HAS_TEXCOORD_TESS = 13, // 1 bit
26
VS_BIT_NORM_REVERSE_TESS = 14, // 1 bit
27
VS_BIT_HAS_NORMAL_TESS = 15, // 1 bit
28
VS_BIT_UVGEN_MODE = 16,
29
VS_BIT_UVPROJ_MODE = 18, // 2, can overlap with LS0
30
VS_BIT_LS0 = 18, // 2
31
VS_BIT_LS1 = 20, // 2
32
VS_BIT_BONES = 22, // 3 should be enough, not 8
33
// 25 - 29 are free.
34
VS_BIT_ENABLE_BONES = 30,
35
36
// If this is set along with LIGHTING_ENABLE, all other lighting bits below
37
// are passed to the shader directly instead.
38
VS_BIT_LIGHT_UBERSHADER = 31,
39
40
VS_BIT_LIGHT0_COMP = 32, // 2 bits
41
VS_BIT_LIGHT0_TYPE = 34, // 2 bits
42
VS_BIT_LIGHT1_COMP = 36, // 2 bits
43
VS_BIT_LIGHT1_TYPE = 38, // 2 bits
44
VS_BIT_LIGHT2_COMP = 40, // 2 bits
45
VS_BIT_LIGHT2_TYPE = 42, // 2 bits
46
VS_BIT_LIGHT3_COMP = 44, // 2 bits
47
VS_BIT_LIGHT3_TYPE = 46, // 2 bits
48
VS_BIT_MATERIAL_UPDATE = 48, // 3 bits
49
VS_BIT_SPLINE = 51, // 1 bit
50
VS_BIT_LIGHT0_ENABLE = 52,
51
VS_BIT_LIGHT1_ENABLE = 53,
52
VS_BIT_LIGHT2_ENABLE = 54,
53
VS_BIT_LIGHT3_ENABLE = 55,
54
VS_BIT_LIGHTING_ENABLE = 56,
55
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits
56
// 59 - 61 are free.
57
VS_BIT_FLATSHADE = 62, // 1 bit
58
VS_BIT_BEZIER = 63, // 1 bit
59
// No more free
60
};
61
62
static inline VShaderBit operator +(VShaderBit bit, int i) {
63
return VShaderBit((int)bit + i);
64
}
65
66
// Local
67
enum FShaderBit : uint8_t {
68
FS_BIT_CLEARMODE = 0,
69
FS_BIT_DO_TEXTURE = 1,
70
FS_BIT_TEXFUNC = 2, // 3 bits
71
FS_BIT_DOUBLE_COLOR = 5, // Not used with FS_BIT_UBERSHADER
72
FS_BIT_3D_TEXTURE = 6,
73
FS_BIT_SHADER_TEX_CLAMP = 7,
74
FS_BIT_CLAMP_S = 8,
75
FS_BIT_CLAMP_T = 9,
76
FS_BIT_TEXALPHA = 10, // Not used with FS_BIT_UBERSHADER
77
FS_BIT_LMODE = 11,
78
FS_BIT_ALPHA_TEST = 12,
79
FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits
80
FS_BIT_ALPHA_AGAINST_ZERO = 16,
81
FS_BIT_COLOR_TEST = 17,
82
FS_BIT_COLOR_TEST_FUNC = 18, // 2 bits
83
FS_BIT_COLOR_AGAINST_ZERO = 20,
84
FS_BIT_ENABLE_FOG = 21, // Not used with FS_BIT_UBERSHADER
85
FS_BIT_DO_TEXTURE_PROJ = 22,
86
// 1 free bit
87
FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits
88
FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits (ReplaceAlphaType)
89
FS_BIT_SIMULATE_LOGIC_OP_TYPE = 30, // 2 bits
90
FS_BIT_REPLACE_BLEND = 32, // 3 bits (ReplaceBlendType)
91
FS_BIT_BLENDEQ = 35, // 3 bits
92
FS_BIT_BLENDFUNC_A = 38, // 4 bits
93
FS_BIT_BLENDFUNC_B = 42, // 4 bits
94
FS_BIT_FLATSHADE = 46,
95
FS_BIT_BGRA_TEXTURE = 47,
96
FS_BIT_TEST_DISCARD_TO_ZERO = 48,
97
FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL = 49,
98
FS_BIT_COLOR_WRITEMASK = 50,
99
FS_BIT_REPLACE_LOGIC_OP = 51, // 4 bits. GE_LOGIC_COPY means no-op/off.
100
FS_BIT_SHADER_DEPAL_MODE = 55, // 2 bits (ShaderDepalMode)
101
FS_BIT_SAMPLE_ARRAY_TEXTURE = 57, // For multiview, framebuffers are array textures and we need to sample the two layers correctly.
102
FS_BIT_STEREO = 58,
103
FS_BIT_USE_FRAMEBUFFER_FETCH = 59,
104
FS_BIT_UBERSHADER = 60,
105
FS_BIT_DEPTH_TEST_NEVER = 61, // Only used on Mali. Set when depth == NEVER. We forcibly avoid writing to depth in this case, since it crashes the driver.
106
};
107
108
static inline FShaderBit operator +(FShaderBit bit, int i) {
109
return FShaderBit((int)bit + i);
110
}
111
112
// Some of these bits are straight from FShaderBit, since they essentially enable attributes directly.
113
enum GShaderBit : uint8_t {
114
GS_BIT_ENABLED = 0, // If not set, we don't use a geo shader.
115
GS_BIT_DO_TEXTURE = 1, // presence of texcoords
116
GS_BIT_LMODE = 2,
117
GS_BIT_CURVE = 3, // curve, which means don't do range culling.
118
};
119
120
static inline GShaderBit operator +(GShaderBit bit, int i) {
121
return GShaderBit((int)bit + i);
122
}
123
124
struct ShaderID {
125
ShaderID() {
126
clear();
127
}
128
void clear() {
129
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
130
d[i] = 0;
131
}
132
}
133
void set_invalid() {
134
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
135
d[i] = 0xFFFFFFFF;
136
}
137
}
138
bool is_invalid() const {
139
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
140
if (d[i] != 0xFFFFFFFF)
141
return false;
142
}
143
return true;
144
}
145
146
uint32_t d[2];
147
bool operator < (const ShaderID &other) const {
148
for (size_t i = 0; i < sizeof(d) / sizeof(uint32_t); i++) {
149
if (d[i] < other.d[i])
150
return true;
151
if (d[i] > other.d[i])
152
return false;
153
}
154
return false;
155
}
156
bool operator == (const ShaderID &other) const {
157
for (size_t i = 0; i < sizeof(d) / sizeof(uint32_t); i++) {
158
if (d[i] != other.d[i])
159
return false;
160
}
161
return true;
162
}
163
bool operator != (const ShaderID &other) const {
164
return !(*this == other);
165
}
166
167
uint32_t Word(int word) const {
168
return d[word];
169
}
170
171
// Note: This is a binary copy to string-as-bytes, not a human-readable representation.
172
void ToString(std::string *dest) const {
173
dest->resize(sizeof(d));
174
memcpy(&(*dest)[0], d, sizeof(d));
175
}
176
// Note: This is a binary copy from string-as-bytes, not a human-readable representation.
177
void FromString(std::string src) {
178
memcpy(d, &(src)[0], sizeof(d));
179
}
180
181
protected:
182
bool Bit(int bit) const {
183
return (d[bit >> 5] >> (bit & 31)) & 1;
184
}
185
// Does not handle crossing 32-bit boundaries. count must be 30 or smaller.
186
int Bits(int bit, int count) const {
187
const int mask = (1 << count) - 1;
188
return (d[bit >> 5] >> (bit & 31)) & mask;
189
}
190
void SetBit(int bit, bool value = true) {
191
if (value) {
192
d[bit >> 5] |= 1 << (bit & 31);
193
} else {
194
d[bit >> 5] &= ~(1 << (bit & 31));
195
}
196
}
197
void SetBits(int bit, int count, int value) {
198
const int mask = (1 << count) - 1;
199
const int shifted_mask = mask << (bit & 31);
200
d[bit >> 5] = (d[bit >> 5] & ~shifted_mask) | ((value & mask) << (bit & 31));
201
}
202
};
203
204
struct VShaderID : ShaderID {
205
VShaderID() : ShaderID() {
206
}
207
208
explicit VShaderID(ShaderID &src) {
209
memcpy(d, src.d, sizeof(d));
210
}
211
212
bool Bit(VShaderBit bit) const {
213
return ShaderID::Bit((int)bit);
214
}
215
216
int Bits(VShaderBit bit, int count) const {
217
return ShaderID::Bits((int)bit, count);
218
}
219
220
void SetBit(VShaderBit bit, bool value = true) {
221
ShaderID::SetBit((int)bit, value);
222
}
223
224
void SetBits(VShaderBit bit, int count, int value) {
225
ShaderID::SetBits((int)bit, count, value);
226
}
227
};
228
229
struct FShaderID : ShaderID {
230
FShaderID() : ShaderID() {
231
}
232
233
explicit FShaderID(ShaderID &src) {
234
memcpy(d, src.d, sizeof(d));
235
}
236
237
bool Bit(FShaderBit bit) const {
238
return ShaderID::Bit((int)bit);
239
}
240
241
int Bits(FShaderBit bit, int count) const {
242
return ShaderID::Bits((int)bit, count);
243
}
244
245
void SetBit(FShaderBit bit, bool value = true) {
246
ShaderID::SetBit((int)bit, value);
247
}
248
249
void SetBits(FShaderBit bit, int count, int value) {
250
ShaderID::SetBits((int)bit, count, value);
251
}
252
};
253
254
struct GShaderID : ShaderID {
255
GShaderID() : ShaderID() {
256
}
257
258
explicit GShaderID(ShaderID &src) {
259
memcpy(d, src.d, sizeof(d));
260
}
261
262
bool Bit(GShaderBit bit) const {
263
return ShaderID::Bit((int)bit);
264
}
265
266
int Bits(GShaderBit bit, int count) const {
267
return ShaderID::Bits((int)bit, count);
268
}
269
270
void SetBit(GShaderBit bit, bool value = true) {
271
ShaderID::SetBit((int)bit, value);
272
}
273
274
void SetBits(GShaderBit bit, int count, int value) {
275
ShaderID::SetBits((int)bit, count, value);
276
}
277
};
278
279
namespace Draw {
280
class Bugs;
281
}
282
283
class VertexDecoder;
284
285
void ComputeVertexShaderID(VShaderID *id, VertexDecoder *vertexDecoder, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode);
286
// Generates a compact string that describes the shader. Useful in a list to get an overview
287
// of the current flora of shaders.
288
std::string VertexShaderDesc(const VShaderID &id);
289
290
struct ComputedPipelineState;
291
void ComputeFragmentShaderID(FShaderID *id, const ComputedPipelineState &pipelineState, const Draw::Bugs &bugs);
292
std::string FragmentShaderDesc(const FShaderID &id);
293
294
void ComputeGeometryShaderID(GShaderID *id, const Draw::Bugs &bugs, int prim);
295
std::string GeometryShaderDesc(const GShaderID &id);
296
297
// For sanity checking.
298
bool FragmentIdNeedsFramebufferRead(const FShaderID &id);
299
300