Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/rendering/shader_compiler.cpp
20884 views
1
/**************************************************************************/
2
/* shader_compiler.cpp */
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
#include "shader_compiler.h"
32
33
#include "servers/rendering/rendering_server_globals.h"
34
#include "servers/rendering/shader_types.h"
35
36
#define SL ShaderLanguage
37
38
static String _mktab(int p_level) {
39
return String("\t").repeat(p_level);
40
}
41
42
static String _typestr(SL::DataType p_type) {
43
String type = ShaderLanguage::get_datatype_name(p_type);
44
if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
45
type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
46
}
47
return type;
48
}
49
50
static int _get_datatype_alignment(SL::DataType p_type) {
51
switch (p_type) {
52
case SL::TYPE_VOID:
53
return 0;
54
case SL::TYPE_BOOL:
55
return 4;
56
case SL::TYPE_BVEC2:
57
return 8;
58
case SL::TYPE_BVEC3:
59
return 16;
60
case SL::TYPE_BVEC4:
61
return 16;
62
case SL::TYPE_INT:
63
return 4;
64
case SL::TYPE_IVEC2:
65
return 8;
66
case SL::TYPE_IVEC3:
67
return 16;
68
case SL::TYPE_IVEC4:
69
return 16;
70
case SL::TYPE_UINT:
71
return 4;
72
case SL::TYPE_UVEC2:
73
return 8;
74
case SL::TYPE_UVEC3:
75
return 16;
76
case SL::TYPE_UVEC4:
77
return 16;
78
case SL::TYPE_FLOAT:
79
return 4;
80
case SL::TYPE_VEC2:
81
return 8;
82
case SL::TYPE_VEC3:
83
return 16;
84
case SL::TYPE_VEC4:
85
return 16;
86
case SL::TYPE_MAT2:
87
return 16;
88
case SL::TYPE_MAT3:
89
return 16;
90
case SL::TYPE_MAT4:
91
return 16;
92
case SL::TYPE_SAMPLER2D:
93
return 16;
94
case SL::TYPE_ISAMPLER2D:
95
return 16;
96
case SL::TYPE_USAMPLER2D:
97
return 16;
98
case SL::TYPE_SAMPLER2DARRAY:
99
return 16;
100
case SL::TYPE_ISAMPLER2DARRAY:
101
return 16;
102
case SL::TYPE_USAMPLER2DARRAY:
103
return 16;
104
case SL::TYPE_SAMPLER3D:
105
return 16;
106
case SL::TYPE_ISAMPLER3D:
107
return 16;
108
case SL::TYPE_USAMPLER3D:
109
return 16;
110
case SL::TYPE_SAMPLERCUBE:
111
return 16;
112
case SL::TYPE_SAMPLERCUBEARRAY:
113
return 16;
114
case SL::TYPE_SAMPLEREXT:
115
return 16;
116
case SL::TYPE_STRUCT:
117
return 0;
118
case SL::TYPE_MAX: {
119
ERR_FAIL_V(0);
120
}
121
}
122
123
ERR_FAIL_V(0);
124
}
125
126
static String _interpstr(SL::DataInterpolation p_interp) {
127
switch (p_interp) {
128
case SL::INTERPOLATION_FLAT:
129
return "flat ";
130
case SL::INTERPOLATION_SMOOTH:
131
return "";
132
case SL::INTERPOLATION_DEFAULT:
133
return "";
134
}
135
return "";
136
}
137
138
static String _prestr(SL::DataPrecision p_pres, bool p_force_highp = false) {
139
switch (p_pres) {
140
case SL::PRECISION_LOWP:
141
return "lowp ";
142
case SL::PRECISION_MEDIUMP:
143
return "mediump ";
144
case SL::PRECISION_HIGHP:
145
return "highp ";
146
case SL::PRECISION_DEFAULT:
147
return p_force_highp ? "highp " : "";
148
}
149
return "";
150
}
151
152
static String _constr(bool p_is_const) {
153
if (p_is_const) {
154
return "const ";
155
}
156
return "";
157
}
158
159
static String _qualstr(SL::ArgumentQualifier p_qual) {
160
switch (p_qual) {
161
case SL::ARGUMENT_QUALIFIER_IN:
162
return "";
163
case SL::ARGUMENT_QUALIFIER_OUT:
164
return "out ";
165
case SL::ARGUMENT_QUALIFIER_INOUT:
166
return "inout ";
167
}
168
return "";
169
}
170
171
static String _opstr(SL::Operator p_op) {
172
return SL::get_operator_text(p_op);
173
}
174
175
static String _mkid(const String &p_id) {
176
String id = "m_" + p_id.replace("__", "_dus_");
177
return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl
178
}
179
180
static String f2sp0(float p_float) {
181
String num = rtos(p_float);
182
if (!num.contains_char('.') && !num.contains_char('e')) {
183
num += ".0";
184
}
185
return num;
186
}
187
188
static String get_constant_text(SL::DataType p_type, const Vector<SL::Scalar> &p_values) {
189
switch (p_type) {
190
case SL::TYPE_BOOL:
191
return p_values[0].boolean ? "true" : "false";
192
case SL::TYPE_BVEC2:
193
case SL::TYPE_BVEC3:
194
case SL::TYPE_BVEC4: {
195
String text = "bvec" + itos(p_type - SL::TYPE_BOOL + 1) + "(";
196
for (int i = 0; i < p_values.size(); i++) {
197
if (i > 0) {
198
text += ",";
199
}
200
201
text += p_values[i].boolean ? "true" : "false";
202
}
203
text += ")";
204
return text;
205
}
206
207
case SL::TYPE_INT:
208
return itos(p_values[0].sint);
209
case SL::TYPE_IVEC2:
210
case SL::TYPE_IVEC3:
211
case SL::TYPE_IVEC4: {
212
String text = "ivec" + itos(p_type - SL::TYPE_INT + 1) + "(";
213
for (int i = 0; i < p_values.size(); i++) {
214
if (i > 0) {
215
text += ",";
216
}
217
218
text += itos(p_values[i].sint);
219
}
220
text += ")";
221
return text;
222
223
} break;
224
case SL::TYPE_UINT:
225
return itos(p_values[0].uint) + "u";
226
case SL::TYPE_UVEC2:
227
case SL::TYPE_UVEC3:
228
case SL::TYPE_UVEC4: {
229
String text = "uvec" + itos(p_type - SL::TYPE_UINT + 1) + "(";
230
for (int i = 0; i < p_values.size(); i++) {
231
if (i > 0) {
232
text += ",";
233
}
234
235
text += itos(p_values[i].uint) + "u";
236
}
237
text += ")";
238
return text;
239
} break;
240
case SL::TYPE_FLOAT:
241
return f2sp0(p_values[0].real);
242
case SL::TYPE_VEC2:
243
case SL::TYPE_VEC3:
244
case SL::TYPE_VEC4: {
245
String text = "vec" + itos(p_type - SL::TYPE_FLOAT + 1) + "(";
246
for (int i = 0; i < p_values.size(); i++) {
247
if (i > 0) {
248
text += ",";
249
}
250
251
text += f2sp0(p_values[i].real);
252
}
253
text += ")";
254
return text;
255
256
} break;
257
case SL::TYPE_MAT2:
258
case SL::TYPE_MAT3:
259
case SL::TYPE_MAT4: {
260
String text = "mat" + itos(p_type - SL::TYPE_MAT2 + 2) + "(";
261
for (int i = 0; i < p_values.size(); i++) {
262
if (i > 0) {
263
text += ",";
264
}
265
266
text += f2sp0(p_values[i].real);
267
}
268
text += ")";
269
return text;
270
271
} break;
272
default:
273
ERR_FAIL_V(String());
274
}
275
}
276
277
String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat) {
278
if (p_filter == ShaderLanguage::FILTER_DEFAULT) {
279
ERR_FAIL_COND_V(actions.default_filter == ShaderLanguage::FILTER_DEFAULT, String());
280
p_filter = actions.default_filter;
281
}
282
if (p_repeat == ShaderLanguage::REPEAT_DEFAULT) {
283
ERR_FAIL_COND_V(actions.default_repeat == ShaderLanguage::REPEAT_DEFAULT, String());
284
p_repeat = actions.default_repeat;
285
}
286
constexpr const char *name_mapping[] = {
287
"SAMPLER_NEAREST_CLAMP",
288
"SAMPLER_LINEAR_CLAMP",
289
"SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP",
290
"SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP",
291
"SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP",
292
"SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP",
293
"SAMPLER_NEAREST_REPEAT",
294
"SAMPLER_LINEAR_REPEAT",
295
"SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT",
296
"SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT",
297
"SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT",
298
"SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT"
299
};
300
return String(name_mapping[p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)]);
301
}
302
303
void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, HashSet<StringName> &added) {
304
int fidx = -1;
305
306
for (int i = 0; i < p_node->vfunctions.size(); i++) {
307
if (p_node->vfunctions[i].name == p_for_func) {
308
fidx = i;
309
break;
310
}
311
}
312
313
ERR_FAIL_COND(fidx == -1);
314
315
Vector<StringName> uses_functions;
316
317
for (const StringName &E : p_node->vfunctions[fidx].uses_function) {
318
uses_functions.push_back(E);
319
}
320
uses_functions.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
321
322
for (int k = 0; k < uses_functions.size(); k++) {
323
if (added.has(uses_functions[k])) {
324
continue; //was added already
325
}
326
327
_dump_function_deps(p_node, uses_functions[k], p_func_code, r_to_add, added);
328
329
SL::FunctionNode *fnode = nullptr;
330
331
for (int i = 0; i < p_node->vfunctions.size(); i++) {
332
if (p_node->vfunctions[i].name == uses_functions[k]) {
333
fnode = p_node->vfunctions[i].function;
334
break;
335
}
336
}
337
338
ERR_FAIL_NULL(fnode);
339
340
r_to_add += "\n";
341
342
String header;
343
if (fnode->return_type == SL::TYPE_STRUCT) {
344
header = _mkid(fnode->return_struct_name);
345
} else {
346
header = _typestr(fnode->return_type);
347
}
348
349
if (fnode->return_array_size > 0) {
350
header += "[";
351
header += itos(fnode->return_array_size);
352
header += "]";
353
}
354
355
header += " ";
356
header += _mkid(fnode->rname);
357
header += "(";
358
359
for (int i = 0; i < fnode->arguments.size(); i++) {
360
if (i > 0) {
361
header += ", ";
362
}
363
header += _constr(fnode->arguments[i].is_const);
364
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
365
header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].struct_name) + " " + _mkid(fnode->arguments[i].name);
366
} else {
367
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
368
}
369
if (fnode->arguments[i].array_size > 0) {
370
header += "[";
371
header += itos(fnode->arguments[i].array_size);
372
header += "]";
373
}
374
}
375
376
header += ")\n";
377
r_to_add += header;
378
r_to_add += p_func_code[uses_functions[k]];
379
380
added.insert(uses_functions[k]);
381
}
382
}
383
384
static String _get_global_shader_uniform_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
385
switch (p_type) {
386
case ShaderLanguage::TYPE_BOOL: {
387
return "bool(floatBitsToUint(" + p_buffer + "[" + p_index + "].x))";
388
}
389
case ShaderLanguage::TYPE_BVEC2: {
390
return "bvec2(floatBitsToUint(" + p_buffer + "[" + p_index + "].xy))";
391
}
392
case ShaderLanguage::TYPE_BVEC3: {
393
return "bvec3(floatBitsToUint(" + p_buffer + "[" + p_index + "].xyz))";
394
}
395
case ShaderLanguage::TYPE_BVEC4: {
396
return "bvec4(floatBitsToUint(" + p_buffer + "[" + p_index + "].xyzw))";
397
}
398
case ShaderLanguage::TYPE_INT: {
399
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].x)";
400
}
401
case ShaderLanguage::TYPE_IVEC2: {
402
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xy)";
403
}
404
case ShaderLanguage::TYPE_IVEC3: {
405
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyz)";
406
}
407
case ShaderLanguage::TYPE_IVEC4: {
408
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyzw)";
409
}
410
case ShaderLanguage::TYPE_UINT: {
411
return "floatBitsToUint(" + p_buffer + "[" + p_index + "].x)";
412
}
413
case ShaderLanguage::TYPE_UVEC2: {
414
return "floatBitsToUint(" + p_buffer + "[" + p_index + "].xy)";
415
}
416
case ShaderLanguage::TYPE_UVEC3: {
417
return "floatBitsToUint(" + p_buffer + "[" + p_index + "].xyz)";
418
}
419
case ShaderLanguage::TYPE_UVEC4: {
420
return "floatBitsToUint(" + p_buffer + "[" + p_index + "].xyzw)";
421
}
422
case ShaderLanguage::TYPE_FLOAT: {
423
return "(" + p_buffer + "[" + p_index + "].x)";
424
}
425
case ShaderLanguage::TYPE_VEC2: {
426
return "(" + p_buffer + "[" + p_index + "].xy)";
427
}
428
case ShaderLanguage::TYPE_VEC3: {
429
return "(" + p_buffer + "[" + p_index + "].xyz)";
430
}
431
case ShaderLanguage::TYPE_VEC4: {
432
return "(" + p_buffer + "[" + p_index + "].xyzw)";
433
}
434
case ShaderLanguage::TYPE_MAT2: {
435
return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1u].xy)";
436
}
437
case ShaderLanguage::TYPE_MAT3: {
438
return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1u].xyz," + p_buffer + "[" + p_index + "+2u].xyz)";
439
}
440
case ShaderLanguage::TYPE_MAT4: {
441
return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1u].xyzw," + p_buffer + "[" + p_index + "+2u].xyzw," + p_buffer + "[" + p_index + "+3u].xyzw)";
442
}
443
default: {
444
ERR_FAIL_V("void");
445
}
446
}
447
}
448
449
String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
450
String code;
451
452
switch (p_node->type) {
453
case SL::Node::NODE_TYPE_SHADER: {
454
SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
455
456
// Render modes.
457
458
for (int i = 0; i < pnode->render_modes.size(); i++) {
459
if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) {
460
r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]]);
461
used_rmode_defines.insert(pnode->render_modes[i]);
462
}
463
464
if (p_actions.render_mode_flags.has(pnode->render_modes[i])) {
465
*p_actions.render_mode_flags[pnode->render_modes[i]] = true;
466
}
467
468
if (p_actions.render_mode_values.has(pnode->render_modes[i])) {
469
Pair<int *, int> &p = p_actions.render_mode_values[pnode->render_modes[i]];
470
*p.first = p.second;
471
}
472
}
473
474
// Stencil modes.
475
476
for (int i = 0; i < pnode->stencil_modes.size(); i++) {
477
if (p_actions.stencil_mode_values.has(pnode->stencil_modes[i])) {
478
Pair<int *, int> &p = p_actions.stencil_mode_values[pnode->stencil_modes[i]];
479
*p.first = p.second;
480
}
481
}
482
483
// Stencil reference value.
484
485
if (p_actions.stencil_reference && pnode->stencil_reference != -1) {
486
*p_actions.stencil_reference = pnode->stencil_reference;
487
}
488
489
// structs
490
491
for (int i = 0; i < pnode->vstructs.size(); i++) {
492
SL::StructNode *st = pnode->vstructs[i].shader_struct;
493
String struct_code;
494
495
struct_code += "struct ";
496
struct_code += _mkid(pnode->vstructs[i].name);
497
struct_code += " ";
498
struct_code += "{\n";
499
for (SL::MemberNode *m : st->members) {
500
if (m->datatype == SL::TYPE_STRUCT) {
501
struct_code += _mkid(m->struct_name);
502
} else {
503
struct_code += _prestr(m->precision);
504
struct_code += _typestr(m->datatype);
505
}
506
struct_code += " ";
507
struct_code += _mkid(m->name);
508
if (m->array_size > 0) {
509
struct_code += "[";
510
struct_code += itos(m->array_size);
511
struct_code += "]";
512
}
513
struct_code += ";\n";
514
}
515
struct_code += "}";
516
struct_code += ";\n";
517
518
for (int j = 0; j < STAGE_MAX; j++) {
519
r_gen_code.stage_globals[j] += struct_code;
520
}
521
}
522
523
int max_texture_uniforms = 0;
524
int max_uniforms = 0;
525
526
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
527
if (SL::is_sampler_type(E.value.type)) {
528
if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
529
E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
530
E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE ||
531
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE0 ||
532
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE1 ||
533
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE2 ||
534
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE3) {
535
continue; // Don't create uniforms in the generated code for these.
536
}
537
max_texture_uniforms++;
538
} else {
539
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
540
continue; // Instances are indexed directly, don't need index uniforms.
541
}
542
543
max_uniforms++;
544
}
545
}
546
547
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
548
549
Vector<int> uniform_sizes;
550
Vector<int> uniform_alignments;
551
Vector<StringName> uniform_defines;
552
uniform_sizes.resize(max_uniforms);
553
uniform_alignments.resize(max_uniforms);
554
uniform_defines.resize(max_uniforms);
555
bool uses_uniforms = false;
556
557
Vector<StringName> uniform_names;
558
559
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
560
uniform_names.push_back(E.key);
561
}
562
563
uniform_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
564
565
for (int k = 0; k < uniform_names.size(); k++) {
566
const StringName &uniform_name = uniform_names[k];
567
const SL::ShaderNode::Uniform &uniform = pnode->uniforms[uniform_name];
568
569
String ucode;
570
571
if (uniform.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
572
//insert, but don't generate any code.
573
p_actions.uniforms->insert(uniform_name, uniform);
574
continue; // Instances are indexed directly, don't need index uniforms.
575
}
576
577
if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
578
uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
579
uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE ||
580
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE0 ||
581
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE1 ||
582
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE2 ||
583
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE3) {
584
continue; // Don't create uniforms in the generated code for these.
585
}
586
587
if (SL::is_sampler_type(uniform.type)) {
588
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
589
if (!RS::get_singleton()->is_low_end()) {
590
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
591
}
592
ucode += "uniform ";
593
}
594
595
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
596
597
if (is_buffer_global) {
598
//this is an integer to index the global table
599
ucode += _typestr(ShaderLanguage::TYPE_UINT);
600
} else {
601
ucode += _prestr(uniform.precision, ShaderLanguage::is_float_type(uniform.type));
602
ucode += _typestr(uniform.type);
603
}
604
605
ucode += " " + _mkid(uniform_name);
606
if (uniform.array_size > 0) {
607
ucode += "[";
608
ucode += itos(uniform.array_size);
609
ucode += "]";
610
}
611
ucode += ";\n";
612
if (SL::is_sampler_type(uniform.type)) {
613
for (int j = 0; j < STAGE_MAX; j++) {
614
r_gen_code.stage_globals[j] += ucode;
615
}
616
617
GeneratedCode::Texture texture;
618
texture.name = uniform_name;
619
texture.hint = uniform.hint;
620
texture.type = uniform.type;
621
texture.use_color = uniform.use_color;
622
texture.filter = uniform.filter;
623
texture.repeat = uniform.repeat;
624
texture.global = uniform.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
625
texture.array_size = uniform.array_size;
626
if (texture.global) {
627
r_gen_code.uses_global_textures = true;
628
}
629
630
r_gen_code.texture_uniforms.write[uniform.texture_order] = texture;
631
} else {
632
if (!uses_uniforms) {
633
uses_uniforms = true;
634
}
635
uniform_defines.write[uniform.order] = ucode;
636
if (is_buffer_global) {
637
//globals are indices into the global table
638
uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(ShaderLanguage::TYPE_UINT);
639
uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
640
} else {
641
// The following code enforces a 16-byte alignment of uniform arrays.
642
if (uniform.array_size > 0) {
643
int size = ShaderLanguage::get_datatype_size(uniform.type) * uniform.array_size;
644
int m = (16 * uniform.array_size);
645
if ((size % m) != 0) {
646
size += m - (size % m);
647
}
648
uniform_sizes.write[uniform.order] = size;
649
uniform_alignments.write[uniform.order] = 16;
650
} else {
651
uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(uniform.type);
652
uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
653
}
654
}
655
}
656
657
p_actions.uniforms->insert(uniform_name, uniform);
658
}
659
660
for (int i = 0; i < max_uniforms; i++) {
661
r_gen_code.uniforms += uniform_defines[i];
662
}
663
664
// add up
665
int offset = 0;
666
for (int i = 0; i < uniform_sizes.size(); i++) {
667
int align = offset % uniform_alignments[i];
668
669
if (align != 0) {
670
offset += uniform_alignments[i] - align;
671
}
672
673
r_gen_code.uniform_offsets.push_back(offset);
674
675
offset += uniform_sizes[i];
676
}
677
678
r_gen_code.uniform_total_size = offset;
679
680
if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16
681
r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16);
682
}
683
684
uint32_t index = p_default_actions.base_varying_index;
685
686
List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
687
688
Vector<StringName> varying_names;
689
690
for (const KeyValue<StringName, SL::ShaderNode::Varying> &E : pnode->varyings) {
691
varying_names.push_back(E.key);
692
}
693
694
varying_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
695
696
for (int k = 0; k < varying_names.size(); k++) {
697
const StringName &varying_name = varying_names[k];
698
const SL::ShaderNode::Varying &varying = pnode->varyings[varying_name];
699
700
if (varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
701
var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(varying_name, varying));
702
fragment_varyings.insert(varying_name);
703
continue;
704
}
705
if (varying.type < SL::TYPE_INT) {
706
continue; // Ignore boolean types to prevent crashing (if varying is just declared).
707
}
708
709
String vcode;
710
String interp_mode = _interpstr(varying.interpolation);
711
vcode += _prestr(varying.precision, ShaderLanguage::is_float_type(varying.type));
712
vcode += _typestr(varying.type);
713
vcode += " " + _mkid(varying_name);
714
uint32_t inc = varying.get_size();
715
716
if (varying.array_size > 0) {
717
vcode += "[";
718
vcode += itos(varying.array_size);
719
vcode += "]";
720
}
721
722
vcode += ";\n";
723
// GLSL ES 3.0 does not allow layout qualifiers for varyings
724
if (!RS::get_singleton()->is_low_end()) {
725
r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") ";
726
r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") ";
727
}
728
r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode;
729
r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;
730
731
index += inc;
732
}
733
734
if (var_frag_to_light.size() > 0) {
735
String gcode = "\n\nstruct {\n";
736
for (const Pair<StringName, SL::ShaderNode::Varying> &E : var_frag_to_light) {
737
gcode += "\t" + _prestr(E.second.precision) + _typestr(E.second.type) + " " + _mkid(E.first);
738
if (E.second.array_size > 0) {
739
gcode += "[";
740
gcode += itos(E.second.array_size);
741
gcode += "]";
742
}
743
gcode += ";\n";
744
}
745
gcode += "} frag_to_light;\n";
746
r_gen_code.stage_globals[STAGE_FRAGMENT] += gcode;
747
}
748
749
for (int i = 0; i < pnode->vconstants.size(); i++) {
750
const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
751
String gcode;
752
gcode += _constr(true);
753
gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type));
754
if (cnode.type == SL::TYPE_STRUCT) {
755
gcode += _mkid(cnode.struct_name);
756
} else {
757
gcode += _typestr(cnode.type);
758
}
759
gcode += " " + _mkid(String(cnode.name));
760
if (cnode.array_size > 0) {
761
gcode += "[";
762
gcode += itos(cnode.array_size);
763
gcode += "]";
764
}
765
gcode += "=";
766
gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
767
gcode += ";\n";
768
for (int j = 0; j < STAGE_MAX; j++) {
769
r_gen_code.stage_globals[j] += gcode;
770
}
771
}
772
773
HashMap<StringName, String> function_code;
774
775
//code for functions
776
for (int i = 0; i < pnode->vfunctions.size(); i++) {
777
SL::FunctionNode *fnode = pnode->vfunctions[i].function;
778
function = fnode;
779
current_func_name = fnode->name;
780
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
781
function = nullptr;
782
}
783
784
//place functions in actual code
785
786
HashSet<StringName> added_funcs_per_stage[STAGE_MAX];
787
788
for (int i = 0; i < pnode->vfunctions.size(); i++) {
789
SL::FunctionNode *fnode = pnode->vfunctions[i].function;
790
791
function = fnode;
792
793
current_func_name = fnode->name;
794
795
if (p_actions.entry_point_stages.has(fnode->name)) {
796
Stage stage = p_actions.entry_point_stages[fnode->name];
797
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.stage_globals[stage], added_funcs_per_stage[stage]);
798
r_gen_code.code[fnode->name] = function_code[fnode->name];
799
}
800
801
function = nullptr;
802
}
803
804
//code+=dump_node_code(pnode->body,p_level);
805
} break;
806
case SL::Node::NODE_TYPE_STRUCT: {
807
} break;
808
case SL::Node::NODE_TYPE_FUNCTION: {
809
} break;
810
case SL::Node::NODE_TYPE_BLOCK: {
811
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
812
813
//variables
814
if (!bnode->single_statement) {
815
code += _mktab(p_level - 1) + "{\n";
816
}
817
818
int i = 0;
819
for (List<ShaderLanguage::Node *>::ConstIterator itr = bnode->statements.begin(); itr != bnode->statements.end(); ++itr, ++i) {
820
String scode = _dump_node_code(*itr, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
821
822
if ((*itr)->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) {
823
code += scode; //use directly
824
if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) {
825
code += ",";
826
}
827
} else {
828
code += _mktab(p_level) + scode + ";\n";
829
}
830
}
831
if (!bnode->single_statement) {
832
code += _mktab(p_level - 1) + "}\n";
833
}
834
835
} break;
836
case SL::Node::NODE_TYPE_VARIABLE_DECLARATION: {
837
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
838
839
String declaration;
840
declaration += _constr(vdnode->is_const);
841
if (vdnode->datatype == SL::TYPE_STRUCT) {
842
declaration += _mkid(vdnode->struct_name);
843
} else {
844
declaration += _prestr(vdnode->precision) + _typestr(vdnode->datatype);
845
}
846
declaration += " ";
847
for (int i = 0; i < vdnode->declarations.size(); i++) {
848
bool is_array = vdnode->declarations[i].size > 0;
849
if (i > 0) {
850
declaration += ",";
851
}
852
declaration += _mkid(vdnode->declarations[i].name);
853
if (is_array) {
854
declaration += "[";
855
if (vdnode->declarations[i].size_expression != nullptr) {
856
declaration += _dump_node_code(vdnode->declarations[i].size_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
857
} else {
858
declaration += itos(vdnode->declarations[i].size);
859
}
860
declaration += "]";
861
}
862
863
if (!is_array || vdnode->declarations[i].single_expression) {
864
if (!vdnode->declarations[i].initializer.is_empty()) {
865
declaration += "=";
866
declaration += _dump_node_code(vdnode->declarations[i].initializer[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
867
}
868
} else {
869
int size = vdnode->declarations[i].initializer.size();
870
if (size > 0) {
871
declaration += "=";
872
if (vdnode->datatype == SL::TYPE_STRUCT) {
873
declaration += _mkid(vdnode->struct_name);
874
} else {
875
declaration += _typestr(vdnode->datatype);
876
}
877
declaration += "[";
878
declaration += itos(size);
879
declaration += "]";
880
declaration += "(";
881
for (int j = 0; j < size; j++) {
882
if (j > 0) {
883
declaration += ",";
884
}
885
declaration += _dump_node_code(vdnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
886
}
887
declaration += ")";
888
}
889
}
890
}
891
892
code += declaration;
893
} break;
894
case SL::Node::NODE_TYPE_VARIABLE: {
895
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
896
bool use_fragment_varying = false;
897
898
if (!vnode->is_local && !(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
899
if (p_assigning) {
900
if (shader->varyings.has(vnode->name)) {
901
use_fragment_varying = true;
902
}
903
} else {
904
if (fragment_varyings.has(vnode->name)) {
905
use_fragment_varying = true;
906
}
907
}
908
}
909
910
if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) {
911
*p_actions.write_flag_pointers[vnode->name] = true;
912
}
913
914
if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) {
915
String define = p_default_actions.usage_defines[vnode->name];
916
if (define.begins_with("@")) {
917
define = p_default_actions.usage_defines[define.substr(1)];
918
}
919
r_gen_code.defines.push_back(define);
920
used_name_defines.insert(vnode->name);
921
}
922
923
if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) {
924
*p_actions.usage_flag_pointers[vnode->name] = true;
925
used_flag_pointers.insert(vnode->name);
926
}
927
928
if (p_default_actions.renames.has(vnode->name)) {
929
code = p_default_actions.renames[vnode->name];
930
} else {
931
if (shader->uniforms.has(vnode->name)) {
932
//its a uniform!
933
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
934
if (u.is_texture()) {
935
StringName name;
936
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
937
name = "color_buffer";
938
if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
939
r_gen_code.uses_screen_texture_mipmaps = true;
940
}
941
r_gen_code.uses_screen_texture = true;
942
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
943
name = "normal_roughness_buffer";
944
r_gen_code.uses_normal_roughness_texture = true;
945
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
946
name = "depth_buffer";
947
r_gen_code.uses_depth_texture = true;
948
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE0) {
949
name = "source0";
950
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE1) {
951
name = "source1";
952
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE2) {
953
name = "source2";
954
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE3) {
955
name = "source3";
956
} else {
957
name = _mkid(vnode->name); //texture, use as is
958
}
959
960
code = name;
961
} else {
962
//a scalar or vector
963
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
964
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
965
//global variable, this means the code points to an index to the global table
966
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
967
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
968
//instance variable, index it as such
969
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + "u)";
970
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
971
} else {
972
//regular uniform, index from UBO
973
code = actions.base_uniform_string + _mkid(vnode->name);
974
}
975
}
976
977
} else {
978
if (use_fragment_varying) {
979
code = "frag_to_light.";
980
}
981
code += _mkid(vnode->name); //its something else (local var most likely) use as is
982
}
983
}
984
985
if (vnode->name == time_name) {
986
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX) {
987
r_gen_code.uses_vertex_time = true;
988
}
989
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_FRAGMENT) {
990
r_gen_code.uses_fragment_time = true;
991
}
992
}
993
994
} break;
995
case SL::Node::NODE_TYPE_ARRAY_CONSTRUCT: {
996
SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node;
997
int sz = acnode->initializer.size();
998
if (acnode->datatype == SL::TYPE_STRUCT) {
999
code += _mkid(acnode->struct_name);
1000
} else {
1001
code += _typestr(acnode->datatype);
1002
}
1003
code += "[";
1004
code += itos(acnode->initializer.size());
1005
code += "]";
1006
code += "(";
1007
for (int i = 0; i < sz; i++) {
1008
code += _dump_node_code(acnode->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1009
if (i != sz - 1) {
1010
code += ", ";
1011
}
1012
}
1013
code += ")";
1014
} break;
1015
case SL::Node::NODE_TYPE_ARRAY: {
1016
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
1017
bool use_fragment_varying = false;
1018
1019
if (!anode->is_local && !(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
1020
if (anode->assign_expression != nullptr && shader->varyings.has(anode->name)) {
1021
use_fragment_varying = true;
1022
} else {
1023
if (p_assigning) {
1024
if (shader->varyings.has(anode->name)) {
1025
use_fragment_varying = true;
1026
}
1027
} else {
1028
if (fragment_varyings.has(anode->name)) {
1029
use_fragment_varying = true;
1030
}
1031
}
1032
}
1033
}
1034
1035
if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) {
1036
*p_actions.write_flag_pointers[anode->name] = true;
1037
}
1038
1039
if (p_default_actions.usage_defines.has(anode->name) && !used_name_defines.has(anode->name)) {
1040
String define = p_default_actions.usage_defines[anode->name];
1041
if (define.begins_with("@")) {
1042
define = p_default_actions.usage_defines[define.substr(1)];
1043
}
1044
r_gen_code.defines.push_back(define);
1045
used_name_defines.insert(anode->name);
1046
}
1047
1048
if (p_actions.usage_flag_pointers.has(anode->name) && !used_flag_pointers.has(anode->name)) {
1049
*p_actions.usage_flag_pointers[anode->name] = true;
1050
used_flag_pointers.insert(anode->name);
1051
}
1052
1053
if (p_default_actions.renames.has(anode->name)) {
1054
code = p_default_actions.renames[anode->name];
1055
} else {
1056
if (shader->uniforms.has(anode->name)) {
1057
//its a uniform!
1058
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[anode->name];
1059
if (u.is_texture()) {
1060
code = _mkid(anode->name); //texture, use as is
1061
} else {
1062
//a scalar or vector
1063
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
1064
code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is
1065
//global variable, this means the code points to an index to the global table
1066
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
1067
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
1068
//instance variable, index it as such
1069
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + "u)";
1070
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
1071
} else {
1072
//regular uniform, index from UBO
1073
code = actions.base_uniform_string + _mkid(anode->name);
1074
}
1075
}
1076
} else {
1077
if (use_fragment_varying) {
1078
code = "frag_to_light.";
1079
}
1080
code += _mkid(anode->name);
1081
}
1082
}
1083
1084
if (anode->call_expression != nullptr) {
1085
code += ".";
1086
code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
1087
} else if (anode->index_expression != nullptr) {
1088
code += "[";
1089
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1090
code += "]";
1091
} else if (anode->assign_expression != nullptr) {
1092
code += "=";
1093
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
1094
}
1095
1096
if (anode->name == time_name) {
1097
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX) {
1098
r_gen_code.uses_vertex_time = true;
1099
}
1100
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_FRAGMENT) {
1101
r_gen_code.uses_fragment_time = true;
1102
}
1103
}
1104
1105
} break;
1106
case SL::Node::NODE_TYPE_CONSTANT: {
1107
SL::ConstantNode *cnode = (SL::ConstantNode *)p_node;
1108
1109
if (cnode->array_size == 0) {
1110
return get_constant_text(cnode->datatype, cnode->values);
1111
} else {
1112
if (cnode->get_datatype() == SL::TYPE_STRUCT) {
1113
code += _mkid(cnode->struct_name);
1114
} else {
1115
code += _typestr(cnode->datatype);
1116
}
1117
code += "[";
1118
code += itos(cnode->array_size);
1119
code += "]";
1120
code += "(";
1121
for (int i = 0; i < cnode->array_size; i++) {
1122
if (i > 0) {
1123
code += ",";
1124
} else {
1125
code += "";
1126
}
1127
code += _dump_node_code(cnode->array_declarations[0].initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1128
}
1129
code += ")";
1130
}
1131
1132
} break;
1133
case SL::Node::NODE_TYPE_OPERATOR: {
1134
SL::OperatorNode *onode = (SL::OperatorNode *)p_node;
1135
1136
switch (onode->op) {
1137
case SL::OP_ASSIGN:
1138
case SL::OP_ASSIGN_ADD:
1139
case SL::OP_ASSIGN_SUB:
1140
case SL::OP_ASSIGN_MUL:
1141
case SL::OP_ASSIGN_DIV:
1142
case SL::OP_ASSIGN_SHIFT_LEFT:
1143
case SL::OP_ASSIGN_SHIFT_RIGHT:
1144
case SL::OP_ASSIGN_MOD:
1145
case SL::OP_ASSIGN_BIT_AND:
1146
case SL::OP_ASSIGN_BIT_OR:
1147
case SL::OP_ASSIGN_BIT_XOR:
1148
code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1149
break;
1150
case SL::OP_BIT_INVERT:
1151
case SL::OP_NEGATE:
1152
case SL::OP_NOT:
1153
case SL::OP_DECREMENT:
1154
case SL::OP_INCREMENT: {
1155
const String node_code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1156
1157
if (onode->op == SL::OP_NEGATE && node_code.begins_with("-")) { // To prevent writing unary minus twice.
1158
code = node_code;
1159
} else {
1160
code = _opstr(onode->op) + node_code;
1161
}
1162
1163
} break;
1164
case SL::OP_POST_DECREMENT:
1165
case SL::OP_POST_INCREMENT:
1166
code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op);
1167
break;
1168
case SL::OP_CALL:
1169
case SL::OP_STRUCT:
1170
case SL::OP_CONSTRUCT: {
1171
ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::NODE_TYPE_VARIABLE, String());
1172
const SL::VariableNode *vnode = static_cast<const SL::VariableNode *>(onode->arguments[0]);
1173
const SL::FunctionNode *func = nullptr;
1174
const bool is_internal_func = internal_functions.has(vnode->name);
1175
1176
if (!is_internal_func) {
1177
for (int i = 0; i < shader->vfunctions.size(); i++) {
1178
if (shader->vfunctions[i].name == vnode->name) {
1179
func = shader->vfunctions[i].function;
1180
break;
1181
}
1182
}
1183
}
1184
1185
bool is_texture_func = false;
1186
bool is_screen_texture = false;
1187
bool is_radiance_texture = false;
1188
bool texture_func_no_uv = false;
1189
bool texture_func_returns_data = false;
1190
1191
if (onode->op == SL::OP_STRUCT) {
1192
code += _mkid(vnode->name);
1193
} else if (onode->op == SL::OP_CONSTRUCT) {
1194
code += String(vnode->name);
1195
} else {
1196
if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) {
1197
*p_actions.usage_flag_pointers[vnode->name] = true;
1198
used_flag_pointers.insert(vnode->name);
1199
}
1200
1201
if (is_internal_func) {
1202
code += vnode->name;
1203
is_texture_func = texture_functions.has(vnode->name);
1204
texture_func_no_uv = (vnode->name == "textureSize" || vnode->name == "textureQueryLevels");
1205
texture_func_returns_data = texture_func_no_uv || vnode->name == "textureQueryLod";
1206
} else if (p_default_actions.renames.has(vnode->name)) {
1207
code += p_default_actions.renames[vnode->name];
1208
} else {
1209
code += _mkid(vnode->rname);
1210
}
1211
}
1212
1213
code += "(";
1214
1215
// if color backbuffer, depth backbuffer or normal roughness texture is used,
1216
// we will add logic to automatically switch between
1217
// sampler2D and sampler2D array and vec2 UV and vec3 UV.
1218
bool multiview_uv_needed = false;
1219
bool is_normal_roughness_texture = false;
1220
1221
for (int i = 1; i < onode->arguments.size(); i++) {
1222
if (i > 1) {
1223
code += ", ";
1224
}
1225
1226
bool is_out_qualifier = false;
1227
if (is_internal_func) {
1228
is_out_qualifier = SL::is_builtin_func_out_parameter(vnode->name, i - 1);
1229
} else if (func != nullptr) {
1230
const SL::ArgumentQualifier qualifier = func->arguments[i - 1].qualifier;
1231
is_out_qualifier = qualifier == SL::ARGUMENT_QUALIFIER_OUT || qualifier == SL::ARGUMENT_QUALIFIER_INOUT;
1232
}
1233
1234
if (is_out_qualifier) {
1235
StringName name;
1236
bool found = false;
1237
{
1238
const SL::Node *node = onode->arguments[i];
1239
1240
bool done = false;
1241
do {
1242
switch (node->type) {
1243
case SL::Node::NODE_TYPE_VARIABLE: {
1244
name = static_cast<const SL::VariableNode *>(node)->name;
1245
done = true;
1246
found = true;
1247
} break;
1248
case SL::Node::NODE_TYPE_MEMBER: {
1249
node = static_cast<const SL::MemberNode *>(node)->owner;
1250
} break;
1251
default: {
1252
done = true;
1253
} break;
1254
}
1255
} while (!done);
1256
}
1257
1258
if (found && p_actions.write_flag_pointers.has(name)) {
1259
*p_actions.write_flag_pointers[name] = true;
1260
}
1261
}
1262
1263
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1264
if (is_texture_func && i == 1) {
1265
// If we're doing a texture lookup we need to check our texture argument
1266
StringName texture_uniform;
1267
bool correct_texture_uniform = false;
1268
1269
switch (onode->arguments[i]->type) {
1270
case SL::Node::NODE_TYPE_VARIABLE: {
1271
const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
1272
texture_uniform = varnode->name;
1273
correct_texture_uniform = true;
1274
} break;
1275
case SL::Node::NODE_TYPE_ARRAY: {
1276
const SL::ArrayNode *anode = static_cast<const SL::ArrayNode *>(onode->arguments[i]);
1277
texture_uniform = anode->name;
1278
correct_texture_uniform = true;
1279
} break;
1280
default:
1281
break;
1282
}
1283
1284
if (correct_texture_uniform && !RS::get_singleton()->is_low_end()) {
1285
// Need to map from texture to sampler in order to sample when using Vulkan GLSL.
1286
String sampler_name;
1287
bool is_depth_texture = false;
1288
1289
if (actions.custom_samplers.has(texture_uniform)) {
1290
sampler_name = actions.custom_samplers[texture_uniform];
1291
} else {
1292
if (shader->uniforms.has(texture_uniform)) {
1293
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
1294
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1295
is_screen_texture = true;
1296
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
1297
is_depth_texture = true;
1298
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
1299
is_normal_roughness_texture = true;
1300
}
1301
sampler_name = _get_sampler_name(u.filter, u.repeat);
1302
} else {
1303
bool found = false;
1304
1305
for (int j = 0; j < function->arguments.size(); j++) {
1306
if (function->arguments[j].name == texture_uniform) {
1307
if (function->arguments[j].tex_builtin_check) {
1308
ERR_CONTINUE(!actions.custom_samplers.has(function->arguments[j].tex_builtin));
1309
sampler_name = actions.custom_samplers[function->arguments[j].tex_builtin];
1310
found = true;
1311
break;
1312
}
1313
if (function->arguments[j].tex_argument_check) {
1314
if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1315
is_screen_texture = true;
1316
} else if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
1317
is_depth_texture = true;
1318
} else if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
1319
is_normal_roughness_texture = true;
1320
}
1321
sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat);
1322
found = true;
1323
break;
1324
}
1325
}
1326
}
1327
if (!found) {
1328
//function was most likely unused, so use anything (compiler will remove it anyway)
1329
sampler_name = _get_sampler_name(ShaderLanguage::FILTER_DEFAULT, ShaderLanguage::REPEAT_DEFAULT);
1330
}
1331
}
1332
}
1333
1334
if (texture_uniform == SNAME("RADIANCE")) {
1335
is_radiance_texture = true;
1336
}
1337
1338
String data_type_name = "";
1339
if (actions.check_multiview_samplers && (is_screen_texture || is_depth_texture || is_normal_roughness_texture)) {
1340
data_type_name = "multiviewSampler";
1341
multiview_uv_needed = true;
1342
} else if (is_radiance_texture) {
1343
data_type_name = "sampler2D";
1344
} else {
1345
data_type_name = ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype());
1346
}
1347
1348
code += data_type_name + "(" + node_code + ", " + sampler_name + ")";
1349
} else if (correct_texture_uniform && RS::get_singleton()->is_low_end()) {
1350
// Texture function on low end hardware (i.e. OpenGL).
1351
1352
if (shader->uniforms.has(texture_uniform)) {
1353
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
1354
if (actions.check_multiview_samplers) {
1355
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1356
multiview_uv_needed = true;
1357
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
1358
multiview_uv_needed = true;
1359
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
1360
multiview_uv_needed = true;
1361
}
1362
}
1363
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1364
is_screen_texture = true;
1365
}
1366
}
1367
1368
code += node_code;
1369
} else {
1370
code += node_code;
1371
}
1372
} else if (multiview_uv_needed && !texture_func_no_uv && i == 2) {
1373
// UV coordinate after using color, depth or normal roughness texture.
1374
node_code = "multiview_uv(" + node_code + ".xy)";
1375
1376
code += node_code;
1377
} else if (is_radiance_texture && !texture_func_no_uv && i == 2) {
1378
node_code = "vec3_to_oct_with_border(" + node_code + ", params.border_size)";
1379
1380
code += node_code;
1381
} else {
1382
code += node_code;
1383
}
1384
}
1385
code += ")";
1386
if (is_screen_texture && !texture_func_returns_data && actions.apply_luminance_multiplier) {
1387
if (RS::get_singleton()->is_low_end()) {
1388
code = "(" + code + " / vec4(vec3(scene_data_block.data.luminance_multiplier), 1.0))";
1389
} else {
1390
code = "(" + code + " * vec4(vec3(sc_luminance_multiplier()), 1.0))";
1391
}
1392
}
1393
if (is_normal_roughness_texture && !texture_func_returns_data) {
1394
code = "normal_roughness_compatibility(" + code + ")";
1395
}
1396
} break;
1397
case SL::OP_INDEX: {
1398
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1399
code += "[";
1400
code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1401
code += "]";
1402
1403
} break;
1404
case SL::OP_SELECT_IF: {
1405
code += "(";
1406
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1407
code += "?";
1408
code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1409
code += ":";
1410
code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1411
code += ")";
1412
1413
} break;
1414
case SL::OP_EMPTY: {
1415
// Semicolon (or empty statement) - ignored.
1416
} break;
1417
1418
default: {
1419
if (p_use_scope) {
1420
code += "(";
1421
}
1422
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + " " + _opstr(onode->op) + " " + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1423
if (p_use_scope) {
1424
code += ")";
1425
}
1426
break;
1427
}
1428
}
1429
1430
} break;
1431
case SL::Node::NODE_TYPE_CONTROL_FLOW: {
1432
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
1433
if (cfnode->flow_op == SL::FLOW_OP_IF) {
1434
code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
1435
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1436
if (cfnode->blocks.size() == 2) {
1437
code += _mktab(p_level) + "else\n";
1438
code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1439
}
1440
} else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) {
1441
code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
1442
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1443
} else if (cfnode->flow_op == SL::FLOW_OP_CASE) {
1444
code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n";
1445
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1446
} else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) {
1447
code += _mktab(p_level) + "default:\n";
1448
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1449
} else if (cfnode->flow_op == SL::FLOW_OP_DO) {
1450
code += _mktab(p_level) + "do";
1451
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1452
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");";
1453
} else if (cfnode->flow_op == SL::FLOW_OP_WHILE) {
1454
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
1455
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1456
} else if (cfnode->flow_op == SL::FLOW_OP_FOR) {
1457
String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1458
String middle = _dump_node_code(cfnode->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1459
String right = _dump_node_code(cfnode->blocks[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1460
code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n";
1461
code += _dump_node_code(cfnode->blocks[3], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1462
1463
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
1464
if (cfnode->expressions.size()) {
1465
code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ";";
1466
} else {
1467
code = "return;";
1468
}
1469
} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
1470
if (p_actions.usage_flag_pointers.has("DISCARD") && !used_flag_pointers.has("DISCARD")) {
1471
*p_actions.usage_flag_pointers["DISCARD"] = true;
1472
used_flag_pointers.insert("DISCARD");
1473
}
1474
1475
code = "discard;";
1476
} else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) {
1477
code = "continue;";
1478
} else if (cfnode->flow_op == SL::FLOW_OP_BREAK) {
1479
code = "break;";
1480
}
1481
1482
} break;
1483
case SL::Node::NODE_TYPE_MEMBER: {
1484
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
1485
String name;
1486
if (mnode->basetype == SL::TYPE_STRUCT) {
1487
name = _mkid(mnode->name);
1488
} else {
1489
name = mnode->name;
1490
}
1491
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + name;
1492
if (mnode->index_expression != nullptr) {
1493
code += "[";
1494
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1495
code += "]";
1496
} else if (mnode->assign_expression != nullptr) {
1497
code += "=";
1498
code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
1499
} else if (mnode->call_expression != nullptr) {
1500
code += ".";
1501
code += _dump_node_code(mnode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
1502
}
1503
} break;
1504
}
1505
1506
return code;
1507
}
1508
1509
ShaderLanguage::DataType ShaderCompiler::_get_global_shader_uniform_type(const StringName &p_name) {
1510
RS::GlobalShaderParameterType gvt = RSG::material_storage->global_shader_parameter_get_type(p_name);
1511
return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
1512
}
1513
1514
Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
1515
SL::ShaderCompileInfo info;
1516
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
1517
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
1518
info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(p_mode);
1519
info.shader_types = ShaderTypes::get_singleton()->get_types();
1520
info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
1521
info.base_varying_index = actions.base_varying_index;
1522
1523
Error err = parser.compile(p_code, info);
1524
1525
if (err != OK) {
1526
Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions();
1527
1528
String current;
1529
HashMap<String, Vector<String>> includes;
1530
includes[""] = Vector<String>();
1531
Vector<String> include_stack;
1532
Vector<String> shader_lines = p_code.split("\n");
1533
1534
// Reconstruct the files.
1535
for (int i = 0; i < shader_lines.size(); i++) {
1536
String l = shader_lines[i];
1537
if (l.begins_with("@@>")) {
1538
String inc_path = l.replace_first("@@>", "");
1539
1540
l = "#include \"" + inc_path + "\"";
1541
includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive
1542
include_stack.push_back(current);
1543
current = inc_path;
1544
includes[inc_path] = Vector<String>();
1545
1546
} else if (l.begins_with("@@<")) {
1547
if (include_stack.size()) {
1548
current = include_stack[include_stack.size() - 1];
1549
include_stack.resize(include_stack.size() - 1);
1550
}
1551
} else {
1552
includes[current].push_back(l);
1553
}
1554
}
1555
1556
// Print the files.
1557
for (const KeyValue<String, Vector<String>> &E : includes) {
1558
int err_line = -1;
1559
for (const ShaderLanguage::FilePosition &include_position : include_positions) {
1560
if (include_position.file == E.key) {
1561
err_line = include_position.line;
1562
}
1563
}
1564
if (err_line < 0) {
1565
// Skip files that don't contain errors.
1566
continue;
1567
}
1568
1569
if (E.key.is_empty()) {
1570
if (p_path == "") {
1571
print_line("--Main Shader--");
1572
} else {
1573
print_line("--" + p_path + "--");
1574
}
1575
} else {
1576
print_line("--" + E.key + "--");
1577
}
1578
const Vector<String> &V = E.value;
1579
for (int i = 0; i < V.size(); i++) {
1580
if (i == err_line - 1) {
1581
// Mark the error line to be visible without having to look at
1582
// the trace at the end.
1583
print_line(vformat("E%4d-> %s", i + 1, V[i]));
1584
} else if ((i == err_line - 3) || (i == err_line - 2) || (i == err_line) || (i == err_line + 1)) {
1585
// Print 4 lines around the error line.
1586
print_line(vformat("%5d | %s", i + 1, V[i]));
1587
}
1588
}
1589
}
1590
1591
String file;
1592
int line;
1593
if (include_positions.size() > 1) {
1594
file = include_positions[include_positions.size() - 1].file;
1595
line = include_positions[include_positions.size() - 1].line;
1596
} else {
1597
file = p_path;
1598
line = parser.get_error_line();
1599
}
1600
1601
_err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
1602
return err;
1603
}
1604
1605
r_gen_code.defines.clear();
1606
r_gen_code.code.clear();
1607
for (int i = 0; i < STAGE_MAX; i++) {
1608
r_gen_code.stage_globals[i] = String();
1609
}
1610
r_gen_code.uses_fragment_time = false;
1611
r_gen_code.uses_vertex_time = false;
1612
r_gen_code.uses_global_textures = false;
1613
r_gen_code.uses_screen_texture_mipmaps = false;
1614
r_gen_code.uses_screen_texture = false;
1615
r_gen_code.uses_depth_texture = false;
1616
r_gen_code.uses_normal_roughness_texture = false;
1617
1618
used_name_defines.clear();
1619
used_rmode_defines.clear();
1620
used_flag_pointers.clear();
1621
fragment_varyings.clear();
1622
1623
shader = parser.get_shader();
1624
function = nullptr;
1625
// Return value only relevant within nested calls.
1626
_ALLOW_DISCARD_ _dump_node_code(shader, 1, r_gen_code, *p_actions, actions, false);
1627
1628
return OK;
1629
}
1630
1631
void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) {
1632
actions = p_actions;
1633
1634
time_name = "TIME";
1635
1636
List<String> func_list;
1637
1638
ShaderLanguage::get_builtin_funcs(&func_list);
1639
1640
for (const String &E : func_list) {
1641
internal_functions.insert(E);
1642
}
1643
texture_functions.insert("texture");
1644
texture_functions.insert("textureProj");
1645
texture_functions.insert("textureLod");
1646
texture_functions.insert("textureProjLod");
1647
texture_functions.insert("textureGrad");
1648
texture_functions.insert("textureProjGrad");
1649
texture_functions.insert("textureGather");
1650
texture_functions.insert("textureSize");
1651
texture_functions.insert("textureQueryLod");
1652
texture_functions.insert("textureQueryLevels");
1653
texture_functions.insert("texelFetch");
1654
}
1655
1656
ShaderCompiler::ShaderCompiler() {
1657
}
1658
1659