Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/drivers/gles3/shader_gles3.h
9973 views
1
/**************************************************************************/
2
/* shader_gles3.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/math/projection.h"
34
#include "core/os/mutex.h"
35
#include "core/string/string_builder.h"
36
#include "core/templates/hash_map.h"
37
#include "core/templates/local_vector.h"
38
#include "core/templates/rid_owner.h"
39
#include "servers/rendering_server.h"
40
41
#ifdef GLES3_ENABLED
42
43
#include "platform_gl.h"
44
45
class ShaderGLES3 {
46
public:
47
struct TextureUniformData {
48
StringName name;
49
int array_size;
50
};
51
52
protected:
53
struct TexUnitPair {
54
const char *name;
55
int index;
56
};
57
58
struct UBOPair {
59
const char *name;
60
int index;
61
};
62
63
struct Specialization {
64
const char *name;
65
bool default_value = false;
66
};
67
68
struct Feedback {
69
const char *name;
70
uint64_t specialization;
71
};
72
73
private:
74
//versions
75
CharString general_defines;
76
77
// A version is a high-level construct which is a combination of built-in and user-defined shader code, Each user-created Shader makes one version
78
// Variants use #ifdefs to toggle behavior on and off to change behavior of the shader
79
// All variants are compiled each time a new version is created
80
// Specializations use #ifdefs to toggle behavior on and off for performance, on supporting hardware, they will compile a version with everything enabled, and then compile more copies to improve performance
81
// Use specializations to enable and disabled advanced features, use variants to toggle behavior when different data may be used (e.g. using a samplerArray vs a sampler, or doing a depth prepass vs a color pass)
82
struct Version {
83
LocalVector<TextureUniformData> texture_uniforms;
84
CharString uniforms;
85
CharString vertex_globals;
86
CharString fragment_globals;
87
HashMap<StringName, CharString> code_sections;
88
Vector<CharString> custom_defines;
89
90
struct Specialization {
91
GLuint id;
92
GLuint vert_id;
93
GLuint frag_id;
94
LocalVector<GLint> uniform_location;
95
LocalVector<GLint> texture_uniform_locations;
96
bool build_queued = false;
97
bool ok = false;
98
Specialization() {
99
id = 0;
100
vert_id = 0;
101
frag_id = 0;
102
}
103
};
104
105
LocalVector<AHashMap<uint64_t, Specialization>> variants;
106
};
107
108
Mutex variant_set_mutex;
109
110
void _get_uniform_locations(Version::Specialization &spec, Version *p_version);
111
void _compile_specialization(Version::Specialization &spec, uint32_t p_variant, Version *p_version, uint64_t p_specialization);
112
113
void _clear_version(Version *p_version);
114
void _initialize_version(Version *p_version);
115
116
RID_Owner<Version, true> version_owner;
117
118
struct StageTemplate {
119
struct Chunk {
120
enum Type {
121
TYPE_MATERIAL_UNIFORMS,
122
TYPE_VERTEX_GLOBALS,
123
TYPE_FRAGMENT_GLOBALS,
124
TYPE_CODE,
125
TYPE_TEXT
126
};
127
128
Type type;
129
StringName code;
130
CharString text;
131
};
132
LocalVector<Chunk> chunks;
133
};
134
135
String name;
136
137
String base_sha256;
138
139
static String shader_cache_dir;
140
static bool shader_cache_cleanup_on_start;
141
static bool shader_cache_save_compressed;
142
static bool shader_cache_save_compressed_zstd;
143
static bool shader_cache_save_debug;
144
bool shader_cache_dir_valid = false;
145
146
GLint max_image_units = 0;
147
148
enum StageType {
149
STAGE_TYPE_VERTEX,
150
STAGE_TYPE_FRAGMENT,
151
STAGE_TYPE_MAX,
152
};
153
154
StageTemplate stage_templates[STAGE_TYPE_MAX];
155
156
void _build_variant_code(StringBuilder &p_builder, uint32_t p_variant, const Version *p_version, StageType p_stage_type, uint64_t p_specialization);
157
158
void _add_stage(const char *p_code, StageType p_stage_type);
159
160
String _version_get_sha1(Version *p_version) const;
161
bool _load_from_cache(Version *p_version);
162
void _save_to_cache(Version *p_version);
163
164
const char **uniform_names = nullptr;
165
int uniform_count = 0;
166
const UBOPair *ubo_pairs = nullptr;
167
int ubo_count = 0;
168
const Feedback *feedbacks;
169
int feedback_count = 0;
170
const TexUnitPair *texunit_pairs = nullptr;
171
int texunit_pair_count = 0;
172
int specialization_count = 0;
173
const Specialization *specializations = nullptr;
174
uint64_t specialization_default_mask = 0;
175
const char **variant_defines = nullptr;
176
int variant_count = 0;
177
178
int base_texture_index = 0;
179
Version::Specialization *current_shader = nullptr;
180
181
protected:
182
ShaderGLES3();
183
void _setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name, int p_uniform_count, const char **p_uniform_names, int p_ubo_count, const UBOPair *p_ubos, int p_feedback_count, const Feedback *p_feedback, int p_texture_count, const TexUnitPair *p_tex_units, int p_specialization_count, const Specialization *p_specializations, int p_variant_count, const char **p_variants);
184
185
_FORCE_INLINE_ bool _version_bind_shader(RID p_version, int p_variant, uint64_t p_specialization) {
186
ERR_FAIL_INDEX_V(p_variant, variant_count, false);
187
188
Version *version = version_owner.get_or_null(p_version);
189
ERR_FAIL_NULL_V(version, false);
190
191
if (version->variants.is_empty()) {
192
_initialize_version(version); //may lack initialization
193
}
194
195
Version::Specialization *spec = version->variants[p_variant].getptr(p_specialization);
196
if (!spec) {
197
if (false) {
198
// Queue load this specialization and use defaults in the meantime (TODO)
199
200
spec = version->variants[p_variant].getptr(specialization_default_mask);
201
} else {
202
// Compile on the spot
203
Version::Specialization s;
204
_compile_specialization(s, p_variant, version, p_specialization);
205
version->variants[p_variant].insert(p_specialization, s);
206
spec = version->variants[p_variant].getptr(p_specialization);
207
if (shader_cache_dir_valid) {
208
_save_to_cache(version);
209
}
210
}
211
} else if (spec->build_queued) {
212
// Still queued, wait
213
spec = version->variants[p_variant].getptr(specialization_default_mask);
214
}
215
216
if (!spec || !spec->ok) {
217
WARN_PRINT_ONCE("shader failed to compile, unable to bind shader.");
218
return false;
219
}
220
221
glUseProgram(spec->id);
222
current_shader = spec;
223
return true;
224
}
225
226
_FORCE_INLINE_ int _version_get_uniform(int p_which, RID p_version, int p_variant, uint64_t p_specialization) {
227
ERR_FAIL_INDEX_V(p_which, uniform_count, -1);
228
Version *version = version_owner.get_or_null(p_version);
229
ERR_FAIL_NULL_V(version, -1);
230
ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1);
231
Version::Specialization *spec = version->variants[p_variant].getptr(p_specialization);
232
ERR_FAIL_NULL_V(spec, -1);
233
ERR_FAIL_INDEX_V(p_which, int(spec->uniform_location.size()), -1);
234
return spec->uniform_location[p_which];
235
}
236
237
virtual void _init() = 0;
238
239
public:
240
RID version_create();
241
242
void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines, const LocalVector<ShaderGLES3::TextureUniformData> &p_texture_uniforms, bool p_initialize = false);
243
244
bool version_is_valid(RID p_version);
245
246
bool version_free(RID p_version);
247
248
static void set_shader_cache_dir(const String &p_dir);
249
static void set_shader_cache_save_compressed(bool p_enable);
250
static void set_shader_cache_save_compressed_zstd(bool p_enable);
251
static void set_shader_cache_save_debug(bool p_enable);
252
253
RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version);
254
255
void initialize(const String &p_general_defines = "", int p_base_texture_index = 0);
256
virtual ~ShaderGLES3();
257
};
258
259
#endif // GLES3_ENABLED
260
261