Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/rendering/shader_compiler.cpp
10277 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
continue; // Don't create uniforms in the generated code for these.
532
}
533
max_texture_uniforms++;
534
} else {
535
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
536
continue; // Instances are indexed directly, don't need index uniforms.
537
}
538
539
max_uniforms++;
540
}
541
}
542
543
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
544
545
Vector<int> uniform_sizes;
546
Vector<int> uniform_alignments;
547
Vector<StringName> uniform_defines;
548
uniform_sizes.resize(max_uniforms);
549
uniform_alignments.resize(max_uniforms);
550
uniform_defines.resize(max_uniforms);
551
bool uses_uniforms = false;
552
553
Vector<StringName> uniform_names;
554
555
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
556
uniform_names.push_back(E.key);
557
}
558
559
uniform_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
560
561
for (int k = 0; k < uniform_names.size(); k++) {
562
const StringName &uniform_name = uniform_names[k];
563
const SL::ShaderNode::Uniform &uniform = pnode->uniforms[uniform_name];
564
565
String ucode;
566
567
if (uniform.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
568
//insert, but don't generate any code.
569
p_actions.uniforms->insert(uniform_name, uniform);
570
continue; // Instances are indexed directly, don't need index uniforms.
571
}
572
573
if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
574
uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
575
uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
576
continue; // Don't create uniforms in the generated code for these.
577
}
578
579
if (SL::is_sampler_type(uniform.type)) {
580
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
581
if (!RS::get_singleton()->is_low_end()) {
582
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
583
}
584
ucode += "uniform ";
585
}
586
587
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
588
589
if (is_buffer_global) {
590
//this is an integer to index the global table
591
ucode += _typestr(ShaderLanguage::TYPE_UINT);
592
} else {
593
ucode += _prestr(uniform.precision, ShaderLanguage::is_float_type(uniform.type));
594
ucode += _typestr(uniform.type);
595
}
596
597
ucode += " " + _mkid(uniform_name);
598
if (uniform.array_size > 0) {
599
ucode += "[";
600
ucode += itos(uniform.array_size);
601
ucode += "]";
602
}
603
ucode += ";\n";
604
if (SL::is_sampler_type(uniform.type)) {
605
for (int j = 0; j < STAGE_MAX; j++) {
606
r_gen_code.stage_globals[j] += ucode;
607
}
608
609
GeneratedCode::Texture texture;
610
texture.name = uniform_name;
611
texture.hint = uniform.hint;
612
texture.type = uniform.type;
613
texture.use_color = uniform.use_color;
614
texture.filter = uniform.filter;
615
texture.repeat = uniform.repeat;
616
texture.global = uniform.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
617
texture.array_size = uniform.array_size;
618
if (texture.global) {
619
r_gen_code.uses_global_textures = true;
620
}
621
622
r_gen_code.texture_uniforms.write[uniform.texture_order] = texture;
623
} else {
624
if (!uses_uniforms) {
625
uses_uniforms = true;
626
}
627
uniform_defines.write[uniform.order] = ucode;
628
if (is_buffer_global) {
629
//globals are indices into the global table
630
uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(ShaderLanguage::TYPE_UINT);
631
uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
632
} else {
633
// The following code enforces a 16-byte alignment of uniform arrays.
634
if (uniform.array_size > 0) {
635
int size = ShaderLanguage::get_datatype_size(uniform.type) * uniform.array_size;
636
int m = (16 * uniform.array_size);
637
if ((size % m) != 0) {
638
size += m - (size % m);
639
}
640
uniform_sizes.write[uniform.order] = size;
641
uniform_alignments.write[uniform.order] = 16;
642
} else {
643
uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(uniform.type);
644
uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
645
}
646
}
647
}
648
649
p_actions.uniforms->insert(uniform_name, uniform);
650
}
651
652
for (int i = 0; i < max_uniforms; i++) {
653
r_gen_code.uniforms += uniform_defines[i];
654
}
655
656
// add up
657
int offset = 0;
658
for (int i = 0; i < uniform_sizes.size(); i++) {
659
int align = offset % uniform_alignments[i];
660
661
if (align != 0) {
662
offset += uniform_alignments[i] - align;
663
}
664
665
r_gen_code.uniform_offsets.push_back(offset);
666
667
offset += uniform_sizes[i];
668
}
669
670
r_gen_code.uniform_total_size = offset;
671
672
if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16
673
r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16);
674
}
675
676
uint32_t index = p_default_actions.base_varying_index;
677
678
List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
679
680
Vector<StringName> varying_names;
681
682
for (const KeyValue<StringName, SL::ShaderNode::Varying> &E : pnode->varyings) {
683
varying_names.push_back(E.key);
684
}
685
686
varying_names.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
687
688
for (int k = 0; k < varying_names.size(); k++) {
689
const StringName &varying_name = varying_names[k];
690
const SL::ShaderNode::Varying &varying = pnode->varyings[varying_name];
691
692
if (varying.stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
693
var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(varying_name, varying));
694
fragment_varyings.insert(varying_name);
695
continue;
696
}
697
if (varying.type < SL::TYPE_INT) {
698
continue; // Ignore boolean types to prevent crashing (if varying is just declared).
699
}
700
701
String vcode;
702
String interp_mode = _interpstr(varying.interpolation);
703
vcode += _prestr(varying.precision, ShaderLanguage::is_float_type(varying.type));
704
vcode += _typestr(varying.type);
705
vcode += " " + _mkid(varying_name);
706
uint32_t inc = varying.get_size();
707
708
if (varying.array_size > 0) {
709
vcode += "[";
710
vcode += itos(varying.array_size);
711
vcode += "]";
712
}
713
714
vcode += ";\n";
715
// GLSL ES 3.0 does not allow layout qualifiers for varyings
716
if (!RS::get_singleton()->is_low_end()) {
717
r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") ";
718
r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") ";
719
}
720
r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode;
721
r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;
722
723
index += inc;
724
}
725
726
if (var_frag_to_light.size() > 0) {
727
String gcode = "\n\nstruct {\n";
728
for (const Pair<StringName, SL::ShaderNode::Varying> &E : var_frag_to_light) {
729
gcode += "\t" + _prestr(E.second.precision) + _typestr(E.second.type) + " " + _mkid(E.first);
730
if (E.second.array_size > 0) {
731
gcode += "[";
732
gcode += itos(E.second.array_size);
733
gcode += "]";
734
}
735
gcode += ";\n";
736
}
737
gcode += "} frag_to_light;\n";
738
r_gen_code.stage_globals[STAGE_FRAGMENT] += gcode;
739
}
740
741
for (int i = 0; i < pnode->vconstants.size(); i++) {
742
const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
743
String gcode;
744
gcode += _constr(true);
745
gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type));
746
if (cnode.type == SL::TYPE_STRUCT) {
747
gcode += _mkid(cnode.struct_name);
748
} else {
749
gcode += _typestr(cnode.type);
750
}
751
gcode += " " + _mkid(String(cnode.name));
752
if (cnode.array_size > 0) {
753
gcode += "[";
754
gcode += itos(cnode.array_size);
755
gcode += "]";
756
}
757
gcode += "=";
758
gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
759
gcode += ";\n";
760
for (int j = 0; j < STAGE_MAX; j++) {
761
r_gen_code.stage_globals[j] += gcode;
762
}
763
}
764
765
HashMap<StringName, String> function_code;
766
767
//code for functions
768
for (int i = 0; i < pnode->vfunctions.size(); i++) {
769
SL::FunctionNode *fnode = pnode->vfunctions[i].function;
770
function = fnode;
771
current_func_name = fnode->name;
772
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
773
function = nullptr;
774
}
775
776
//place functions in actual code
777
778
HashSet<StringName> added_funcs_per_stage[STAGE_MAX];
779
780
for (int i = 0; i < pnode->vfunctions.size(); i++) {
781
SL::FunctionNode *fnode = pnode->vfunctions[i].function;
782
783
function = fnode;
784
785
current_func_name = fnode->name;
786
787
if (p_actions.entry_point_stages.has(fnode->name)) {
788
Stage stage = p_actions.entry_point_stages[fnode->name];
789
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.stage_globals[stage], added_funcs_per_stage[stage]);
790
r_gen_code.code[fnode->name] = function_code[fnode->name];
791
}
792
793
function = nullptr;
794
}
795
796
//code+=dump_node_code(pnode->body,p_level);
797
} break;
798
case SL::Node::NODE_TYPE_STRUCT: {
799
} break;
800
case SL::Node::NODE_TYPE_FUNCTION: {
801
} break;
802
case SL::Node::NODE_TYPE_BLOCK: {
803
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
804
805
//variables
806
if (!bnode->single_statement) {
807
code += _mktab(p_level - 1) + "{\n";
808
}
809
810
int i = 0;
811
for (List<ShaderLanguage::Node *>::ConstIterator itr = bnode->statements.begin(); itr != bnode->statements.end(); ++itr, ++i) {
812
String scode = _dump_node_code(*itr, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
813
814
if ((*itr)->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) {
815
code += scode; //use directly
816
if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) {
817
code += ",";
818
}
819
} else {
820
code += _mktab(p_level) + scode + ";\n";
821
}
822
}
823
if (!bnode->single_statement) {
824
code += _mktab(p_level - 1) + "}\n";
825
}
826
827
} break;
828
case SL::Node::NODE_TYPE_VARIABLE_DECLARATION: {
829
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
830
831
String declaration;
832
declaration += _constr(vdnode->is_const);
833
if (vdnode->datatype == SL::TYPE_STRUCT) {
834
declaration += _mkid(vdnode->struct_name);
835
} else {
836
declaration += _prestr(vdnode->precision) + _typestr(vdnode->datatype);
837
}
838
declaration += " ";
839
for (int i = 0; i < vdnode->declarations.size(); i++) {
840
bool is_array = vdnode->declarations[i].size > 0;
841
if (i > 0) {
842
declaration += ",";
843
}
844
declaration += _mkid(vdnode->declarations[i].name);
845
if (is_array) {
846
declaration += "[";
847
if (vdnode->declarations[i].size_expression != nullptr) {
848
declaration += _dump_node_code(vdnode->declarations[i].size_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
849
} else {
850
declaration += itos(vdnode->declarations[i].size);
851
}
852
declaration += "]";
853
}
854
855
if (!is_array || vdnode->declarations[i].single_expression) {
856
if (!vdnode->declarations[i].initializer.is_empty()) {
857
declaration += "=";
858
declaration += _dump_node_code(vdnode->declarations[i].initializer[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
859
}
860
} else {
861
int size = vdnode->declarations[i].initializer.size();
862
if (size > 0) {
863
declaration += "=";
864
if (vdnode->datatype == SL::TYPE_STRUCT) {
865
declaration += _mkid(vdnode->struct_name);
866
} else {
867
declaration += _typestr(vdnode->datatype);
868
}
869
declaration += "[";
870
declaration += itos(size);
871
declaration += "]";
872
declaration += "(";
873
for (int j = 0; j < size; j++) {
874
if (j > 0) {
875
declaration += ",";
876
}
877
declaration += _dump_node_code(vdnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
878
}
879
declaration += ")";
880
}
881
}
882
}
883
884
code += declaration;
885
} break;
886
case SL::Node::NODE_TYPE_VARIABLE: {
887
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
888
bool use_fragment_varying = false;
889
890
if (!vnode->is_local && !(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
891
if (p_assigning) {
892
if (shader->varyings.has(vnode->name)) {
893
use_fragment_varying = true;
894
}
895
} else {
896
if (fragment_varyings.has(vnode->name)) {
897
use_fragment_varying = true;
898
}
899
}
900
}
901
902
if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) {
903
*p_actions.write_flag_pointers[vnode->name] = true;
904
}
905
906
if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) {
907
String define = p_default_actions.usage_defines[vnode->name];
908
if (define.begins_with("@")) {
909
define = p_default_actions.usage_defines[define.substr(1)];
910
}
911
r_gen_code.defines.push_back(define);
912
used_name_defines.insert(vnode->name);
913
}
914
915
if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) {
916
*p_actions.usage_flag_pointers[vnode->name] = true;
917
used_flag_pointers.insert(vnode->name);
918
}
919
920
if (p_default_actions.renames.has(vnode->name)) {
921
code = p_default_actions.renames[vnode->name];
922
} else {
923
if (shader->uniforms.has(vnode->name)) {
924
//its a uniform!
925
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
926
if (u.is_texture()) {
927
StringName name;
928
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
929
name = "color_buffer";
930
if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
931
r_gen_code.uses_screen_texture_mipmaps = true;
932
}
933
r_gen_code.uses_screen_texture = true;
934
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
935
name = "normal_roughness_buffer";
936
r_gen_code.uses_normal_roughness_texture = true;
937
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
938
name = "depth_buffer";
939
r_gen_code.uses_depth_texture = true;
940
} else {
941
name = _mkid(vnode->name); //texture, use as is
942
}
943
944
code = name;
945
} else {
946
//a scalar or vector
947
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
948
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
949
//global variable, this means the code points to an index to the global table
950
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
951
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
952
//instance variable, index it as such
953
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + "u)";
954
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
955
} else {
956
//regular uniform, index from UBO
957
code = actions.base_uniform_string + _mkid(vnode->name);
958
}
959
}
960
961
} else {
962
if (use_fragment_varying) {
963
code = "frag_to_light.";
964
}
965
code += _mkid(vnode->name); //its something else (local var most likely) use as is
966
}
967
}
968
969
if (vnode->name == time_name) {
970
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX) {
971
r_gen_code.uses_vertex_time = true;
972
}
973
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_FRAGMENT) {
974
r_gen_code.uses_fragment_time = true;
975
}
976
}
977
978
} break;
979
case SL::Node::NODE_TYPE_ARRAY_CONSTRUCT: {
980
SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node;
981
int sz = acnode->initializer.size();
982
if (acnode->datatype == SL::TYPE_STRUCT) {
983
code += _mkid(acnode->struct_name);
984
} else {
985
code += _typestr(acnode->datatype);
986
}
987
code += "[";
988
code += itos(acnode->initializer.size());
989
code += "]";
990
code += "(";
991
for (int i = 0; i < sz; i++) {
992
code += _dump_node_code(acnode->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
993
if (i != sz - 1) {
994
code += ", ";
995
}
996
}
997
code += ")";
998
} break;
999
case SL::Node::NODE_TYPE_ARRAY: {
1000
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
1001
bool use_fragment_varying = false;
1002
1003
if (!anode->is_local && !(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
1004
if (anode->assign_expression != nullptr && shader->varyings.has(anode->name)) {
1005
use_fragment_varying = true;
1006
} else {
1007
if (p_assigning) {
1008
if (shader->varyings.has(anode->name)) {
1009
use_fragment_varying = true;
1010
}
1011
} else {
1012
if (fragment_varyings.has(anode->name)) {
1013
use_fragment_varying = true;
1014
}
1015
}
1016
}
1017
}
1018
1019
if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) {
1020
*p_actions.write_flag_pointers[anode->name] = true;
1021
}
1022
1023
if (p_default_actions.usage_defines.has(anode->name) && !used_name_defines.has(anode->name)) {
1024
String define = p_default_actions.usage_defines[anode->name];
1025
if (define.begins_with("@")) {
1026
define = p_default_actions.usage_defines[define.substr(1)];
1027
}
1028
r_gen_code.defines.push_back(define);
1029
used_name_defines.insert(anode->name);
1030
}
1031
1032
if (p_actions.usage_flag_pointers.has(anode->name) && !used_flag_pointers.has(anode->name)) {
1033
*p_actions.usage_flag_pointers[anode->name] = true;
1034
used_flag_pointers.insert(anode->name);
1035
}
1036
1037
if (p_default_actions.renames.has(anode->name)) {
1038
code = p_default_actions.renames[anode->name];
1039
} else {
1040
if (shader->uniforms.has(anode->name)) {
1041
//its a uniform!
1042
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[anode->name];
1043
if (u.is_texture()) {
1044
code = _mkid(anode->name); //texture, use as is
1045
} else {
1046
//a scalar or vector
1047
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
1048
code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is
1049
//global variable, this means the code points to an index to the global table
1050
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
1051
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
1052
//instance variable, index it as such
1053
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + "u)";
1054
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
1055
} else {
1056
//regular uniform, index from UBO
1057
code = actions.base_uniform_string + _mkid(anode->name);
1058
}
1059
}
1060
} else {
1061
if (use_fragment_varying) {
1062
code = "frag_to_light.";
1063
}
1064
code += _mkid(anode->name);
1065
}
1066
}
1067
1068
if (anode->call_expression != nullptr) {
1069
code += ".";
1070
code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
1071
} else if (anode->index_expression != nullptr) {
1072
code += "[";
1073
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1074
code += "]";
1075
} else if (anode->assign_expression != nullptr) {
1076
code += "=";
1077
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
1078
}
1079
1080
if (anode->name == time_name) {
1081
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX) {
1082
r_gen_code.uses_vertex_time = true;
1083
}
1084
if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_FRAGMENT) {
1085
r_gen_code.uses_fragment_time = true;
1086
}
1087
}
1088
1089
} break;
1090
case SL::Node::NODE_TYPE_CONSTANT: {
1091
SL::ConstantNode *cnode = (SL::ConstantNode *)p_node;
1092
1093
if (cnode->array_size == 0) {
1094
return get_constant_text(cnode->datatype, cnode->values);
1095
} else {
1096
if (cnode->get_datatype() == SL::TYPE_STRUCT) {
1097
code += _mkid(cnode->struct_name);
1098
} else {
1099
code += _typestr(cnode->datatype);
1100
}
1101
code += "[";
1102
code += itos(cnode->array_size);
1103
code += "]";
1104
code += "(";
1105
for (int i = 0; i < cnode->array_size; i++) {
1106
if (i > 0) {
1107
code += ",";
1108
} else {
1109
code += "";
1110
}
1111
code += _dump_node_code(cnode->array_declarations[0].initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1112
}
1113
code += ")";
1114
}
1115
1116
} break;
1117
case SL::Node::NODE_TYPE_OPERATOR: {
1118
SL::OperatorNode *onode = (SL::OperatorNode *)p_node;
1119
1120
switch (onode->op) {
1121
case SL::OP_ASSIGN:
1122
case SL::OP_ASSIGN_ADD:
1123
case SL::OP_ASSIGN_SUB:
1124
case SL::OP_ASSIGN_MUL:
1125
case SL::OP_ASSIGN_DIV:
1126
case SL::OP_ASSIGN_SHIFT_LEFT:
1127
case SL::OP_ASSIGN_SHIFT_RIGHT:
1128
case SL::OP_ASSIGN_MOD:
1129
case SL::OP_ASSIGN_BIT_AND:
1130
case SL::OP_ASSIGN_BIT_OR:
1131
case SL::OP_ASSIGN_BIT_XOR:
1132
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);
1133
break;
1134
case SL::OP_BIT_INVERT:
1135
case SL::OP_NEGATE:
1136
case SL::OP_NOT:
1137
case SL::OP_DECREMENT:
1138
case SL::OP_INCREMENT: {
1139
const String node_code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1140
1141
if (onode->op == SL::OP_NEGATE && node_code.begins_with("-")) { // To prevent writing unary minus twice.
1142
code = node_code;
1143
} else {
1144
code = _opstr(onode->op) + node_code;
1145
}
1146
1147
} break;
1148
case SL::OP_POST_DECREMENT:
1149
case SL::OP_POST_INCREMENT:
1150
code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op);
1151
break;
1152
case SL::OP_CALL:
1153
case SL::OP_STRUCT:
1154
case SL::OP_CONSTRUCT: {
1155
ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::NODE_TYPE_VARIABLE, String());
1156
const SL::VariableNode *vnode = static_cast<const SL::VariableNode *>(onode->arguments[0]);
1157
const SL::FunctionNode *func = nullptr;
1158
const bool is_internal_func = internal_functions.has(vnode->name);
1159
1160
if (!is_internal_func) {
1161
for (int i = 0; i < shader->vfunctions.size(); i++) {
1162
if (shader->vfunctions[i].name == vnode->name) {
1163
func = shader->vfunctions[i].function;
1164
break;
1165
}
1166
}
1167
}
1168
1169
bool is_texture_func = false;
1170
bool is_screen_texture = false;
1171
bool texture_func_no_uv = false;
1172
bool texture_func_returns_data = false;
1173
1174
if (onode->op == SL::OP_STRUCT) {
1175
code += _mkid(vnode->name);
1176
} else if (onode->op == SL::OP_CONSTRUCT) {
1177
code += String(vnode->name);
1178
} else {
1179
if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) {
1180
*p_actions.usage_flag_pointers[vnode->name] = true;
1181
used_flag_pointers.insert(vnode->name);
1182
}
1183
1184
if (is_internal_func) {
1185
code += vnode->name;
1186
is_texture_func = texture_functions.has(vnode->name);
1187
texture_func_no_uv = (vnode->name == "textureSize" || vnode->name == "textureQueryLevels");
1188
texture_func_returns_data = texture_func_no_uv || vnode->name == "textureQueryLod";
1189
} else if (p_default_actions.renames.has(vnode->name)) {
1190
code += p_default_actions.renames[vnode->name];
1191
} else {
1192
code += _mkid(vnode->rname);
1193
}
1194
}
1195
1196
code += "(";
1197
1198
// if color backbuffer, depth backbuffer or normal roughness texture is used,
1199
// we will add logic to automatically switch between
1200
// sampler2D and sampler2D array and vec2 UV and vec3 UV.
1201
bool multiview_uv_needed = false;
1202
bool is_normal_roughness_texture = false;
1203
1204
for (int i = 1; i < onode->arguments.size(); i++) {
1205
if (i > 1) {
1206
code += ", ";
1207
}
1208
1209
bool is_out_qualifier = false;
1210
if (is_internal_func) {
1211
is_out_qualifier = SL::is_builtin_func_out_parameter(vnode->name, i - 1);
1212
} else if (func != nullptr) {
1213
const SL::ArgumentQualifier qualifier = func->arguments[i - 1].qualifier;
1214
is_out_qualifier = qualifier == SL::ARGUMENT_QUALIFIER_OUT || qualifier == SL::ARGUMENT_QUALIFIER_INOUT;
1215
}
1216
1217
if (is_out_qualifier) {
1218
StringName name;
1219
bool found = false;
1220
{
1221
const SL::Node *node = onode->arguments[i];
1222
1223
bool done = false;
1224
do {
1225
switch (node->type) {
1226
case SL::Node::NODE_TYPE_VARIABLE: {
1227
name = static_cast<const SL::VariableNode *>(node)->name;
1228
done = true;
1229
found = true;
1230
} break;
1231
case SL::Node::NODE_TYPE_MEMBER: {
1232
node = static_cast<const SL::MemberNode *>(node)->owner;
1233
} break;
1234
default: {
1235
done = true;
1236
} break;
1237
}
1238
} while (!done);
1239
}
1240
1241
if (found && p_actions.write_flag_pointers.has(name)) {
1242
*p_actions.write_flag_pointers[name] = true;
1243
}
1244
}
1245
1246
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1247
if (is_texture_func && i == 1) {
1248
// If we're doing a texture lookup we need to check our texture argument
1249
StringName texture_uniform;
1250
bool correct_texture_uniform = false;
1251
1252
switch (onode->arguments[i]->type) {
1253
case SL::Node::NODE_TYPE_VARIABLE: {
1254
const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
1255
texture_uniform = varnode->name;
1256
correct_texture_uniform = true;
1257
} break;
1258
case SL::Node::NODE_TYPE_ARRAY: {
1259
const SL::ArrayNode *anode = static_cast<const SL::ArrayNode *>(onode->arguments[i]);
1260
texture_uniform = anode->name;
1261
correct_texture_uniform = true;
1262
} break;
1263
default:
1264
break;
1265
}
1266
1267
if (correct_texture_uniform && !RS::get_singleton()->is_low_end()) {
1268
// Need to map from texture to sampler in order to sample when using Vulkan GLSL.
1269
String sampler_name;
1270
bool is_depth_texture = false;
1271
1272
if (actions.custom_samplers.has(texture_uniform)) {
1273
sampler_name = actions.custom_samplers[texture_uniform];
1274
} else {
1275
if (shader->uniforms.has(texture_uniform)) {
1276
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
1277
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1278
is_screen_texture = true;
1279
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
1280
is_depth_texture = true;
1281
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
1282
is_normal_roughness_texture = true;
1283
}
1284
sampler_name = _get_sampler_name(u.filter, u.repeat);
1285
} else {
1286
bool found = false;
1287
1288
for (int j = 0; j < function->arguments.size(); j++) {
1289
if (function->arguments[j].name == texture_uniform) {
1290
if (function->arguments[j].tex_builtin_check) {
1291
ERR_CONTINUE(!actions.custom_samplers.has(function->arguments[j].tex_builtin));
1292
sampler_name = actions.custom_samplers[function->arguments[j].tex_builtin];
1293
found = true;
1294
break;
1295
}
1296
if (function->arguments[j].tex_argument_check) {
1297
if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1298
is_screen_texture = true;
1299
} else if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
1300
is_depth_texture = true;
1301
} else if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
1302
is_normal_roughness_texture = true;
1303
}
1304
sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat);
1305
found = true;
1306
break;
1307
}
1308
}
1309
}
1310
if (!found) {
1311
//function was most likely unused, so use anything (compiler will remove it anyway)
1312
sampler_name = _get_sampler_name(ShaderLanguage::FILTER_DEFAULT, ShaderLanguage::REPEAT_DEFAULT);
1313
}
1314
}
1315
}
1316
1317
String data_type_name = "";
1318
if (actions.check_multiview_samplers && (is_screen_texture || is_depth_texture || is_normal_roughness_texture)) {
1319
data_type_name = "multiviewSampler";
1320
multiview_uv_needed = true;
1321
} else {
1322
data_type_name = ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype());
1323
}
1324
1325
code += data_type_name + "(" + node_code + ", " + sampler_name + ")";
1326
} else if (actions.check_multiview_samplers && correct_texture_uniform && RS::get_singleton()->is_low_end()) {
1327
// Texture function on low end hardware (i.e. OpenGL).
1328
// We just need to know if the texture supports multiview.
1329
1330
if (shader->uniforms.has(texture_uniform)) {
1331
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
1332
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
1333
multiview_uv_needed = true;
1334
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
1335
multiview_uv_needed = true;
1336
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
1337
multiview_uv_needed = true;
1338
}
1339
}
1340
1341
code += node_code;
1342
} else {
1343
code += node_code;
1344
}
1345
} else if (multiview_uv_needed && !texture_func_no_uv && i == 2) {
1346
// UV coordinate after using color, depth or normal roughness texture.
1347
node_code = "multiview_uv(" + node_code + ".xy)";
1348
1349
code += node_code;
1350
} else {
1351
code += node_code;
1352
}
1353
}
1354
code += ")";
1355
if (is_screen_texture && !texture_func_returns_data && actions.apply_luminance_multiplier) {
1356
code = "(" + code + " * vec4(vec3(sc_luminance_multiplier()), 1.0))";
1357
}
1358
if (is_normal_roughness_texture && !texture_func_returns_data) {
1359
code = "normal_roughness_compatibility(" + code + ")";
1360
}
1361
} break;
1362
case SL::OP_INDEX: {
1363
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1364
code += "[";
1365
code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1366
code += "]";
1367
1368
} break;
1369
case SL::OP_SELECT_IF: {
1370
code += "(";
1371
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1372
code += "?";
1373
code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1374
code += ":";
1375
code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1376
code += ")";
1377
1378
} break;
1379
case SL::OP_EMPTY: {
1380
// Semicolon (or empty statement) - ignored.
1381
} break;
1382
1383
default: {
1384
if (p_use_scope) {
1385
code += "(";
1386
}
1387
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);
1388
if (p_use_scope) {
1389
code += ")";
1390
}
1391
break;
1392
}
1393
}
1394
1395
} break;
1396
case SL::Node::NODE_TYPE_CONTROL_FLOW: {
1397
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
1398
if (cfnode->flow_op == SL::FLOW_OP_IF) {
1399
code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
1400
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1401
if (cfnode->blocks.size() == 2) {
1402
code += _mktab(p_level) + "else\n";
1403
code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1404
}
1405
} else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) {
1406
code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
1407
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1408
} else if (cfnode->flow_op == SL::FLOW_OP_CASE) {
1409
code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n";
1410
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1411
} else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) {
1412
code += _mktab(p_level) + "default:\n";
1413
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1414
} else if (cfnode->flow_op == SL::FLOW_OP_DO) {
1415
code += _mktab(p_level) + "do";
1416
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1417
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");";
1418
} else if (cfnode->flow_op == SL::FLOW_OP_WHILE) {
1419
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
1420
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1421
} else if (cfnode->flow_op == SL::FLOW_OP_FOR) {
1422
String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1423
String middle = _dump_node_code(cfnode->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1424
String right = _dump_node_code(cfnode->blocks[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1425
code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n";
1426
code += _dump_node_code(cfnode->blocks[3], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
1427
1428
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
1429
if (cfnode->expressions.size()) {
1430
code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ";";
1431
} else {
1432
code = "return;";
1433
}
1434
} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
1435
if (p_actions.usage_flag_pointers.has("DISCARD") && !used_flag_pointers.has("DISCARD")) {
1436
*p_actions.usage_flag_pointers["DISCARD"] = true;
1437
used_flag_pointers.insert("DISCARD");
1438
}
1439
1440
code = "discard;";
1441
} else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) {
1442
code = "continue;";
1443
} else if (cfnode->flow_op == SL::FLOW_OP_BREAK) {
1444
code = "break;";
1445
}
1446
1447
} break;
1448
case SL::Node::NODE_TYPE_MEMBER: {
1449
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
1450
String name;
1451
if (mnode->basetype == SL::TYPE_STRUCT) {
1452
name = _mkid(mnode->name);
1453
} else {
1454
name = mnode->name;
1455
}
1456
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + name;
1457
if (mnode->index_expression != nullptr) {
1458
code += "[";
1459
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
1460
code += "]";
1461
} else if (mnode->assign_expression != nullptr) {
1462
code += "=";
1463
code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
1464
} else if (mnode->call_expression != nullptr) {
1465
code += ".";
1466
code += _dump_node_code(mnode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
1467
}
1468
} break;
1469
}
1470
1471
return code;
1472
}
1473
1474
ShaderLanguage::DataType ShaderCompiler::_get_global_shader_uniform_type(const StringName &p_name) {
1475
RS::GlobalShaderParameterType gvt = RSG::material_storage->global_shader_parameter_get_type(p_name);
1476
return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
1477
}
1478
1479
Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
1480
SL::ShaderCompileInfo info;
1481
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
1482
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
1483
info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(p_mode);
1484
info.shader_types = ShaderTypes::get_singleton()->get_types();
1485
info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
1486
info.base_varying_index = actions.base_varying_index;
1487
1488
Error err = parser.compile(p_code, info);
1489
1490
if (err != OK) {
1491
Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions();
1492
1493
String current;
1494
HashMap<String, Vector<String>> includes;
1495
includes[""] = Vector<String>();
1496
Vector<String> include_stack;
1497
Vector<String> shader_lines = p_code.split("\n");
1498
1499
// Reconstruct the files.
1500
for (int i = 0; i < shader_lines.size(); i++) {
1501
String l = shader_lines[i];
1502
if (l.begins_with("@@>")) {
1503
String inc_path = l.replace_first("@@>", "");
1504
1505
l = "#include \"" + inc_path + "\"";
1506
includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive
1507
include_stack.push_back(current);
1508
current = inc_path;
1509
includes[inc_path] = Vector<String>();
1510
1511
} else if (l.begins_with("@@<")) {
1512
if (include_stack.size()) {
1513
current = include_stack[include_stack.size() - 1];
1514
include_stack.resize(include_stack.size() - 1);
1515
}
1516
} else {
1517
includes[current].push_back(l);
1518
}
1519
}
1520
1521
// Print the files.
1522
for (const KeyValue<String, Vector<String>> &E : includes) {
1523
if (E.key.is_empty()) {
1524
if (p_path == "") {
1525
print_line("--Main Shader--");
1526
} else {
1527
print_line("--" + p_path + "--");
1528
}
1529
} else {
1530
print_line("--" + E.key + "--");
1531
}
1532
int err_line = -1;
1533
for (int i = 0; i < include_positions.size(); i++) {
1534
if (include_positions[i].file == E.key) {
1535
err_line = include_positions[i].line;
1536
}
1537
}
1538
const Vector<String> &V = E.value;
1539
for (int i = 0; i < V.size(); i++) {
1540
if (i == err_line - 1) {
1541
// Mark the error line to be visible without having to look at
1542
// the trace at the end.
1543
print_line(vformat("E%4d-> %s", i + 1, V[i]));
1544
} else {
1545
print_line(vformat("%5d | %s", i + 1, V[i]));
1546
}
1547
}
1548
}
1549
1550
String file;
1551
int line;
1552
if (include_positions.size() > 1) {
1553
file = include_positions[include_positions.size() - 1].file;
1554
line = include_positions[include_positions.size() - 1].line;
1555
} else {
1556
file = p_path;
1557
line = parser.get_error_line();
1558
}
1559
1560
_err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
1561
return err;
1562
}
1563
1564
r_gen_code.defines.clear();
1565
r_gen_code.code.clear();
1566
for (int i = 0; i < STAGE_MAX; i++) {
1567
r_gen_code.stage_globals[i] = String();
1568
}
1569
r_gen_code.uses_fragment_time = false;
1570
r_gen_code.uses_vertex_time = false;
1571
r_gen_code.uses_global_textures = false;
1572
r_gen_code.uses_screen_texture_mipmaps = false;
1573
r_gen_code.uses_screen_texture = false;
1574
r_gen_code.uses_depth_texture = false;
1575
r_gen_code.uses_normal_roughness_texture = false;
1576
1577
used_name_defines.clear();
1578
used_rmode_defines.clear();
1579
used_flag_pointers.clear();
1580
fragment_varyings.clear();
1581
1582
shader = parser.get_shader();
1583
function = nullptr;
1584
// Return value only relevant within nested calls.
1585
_ALLOW_DISCARD_ _dump_node_code(shader, 1, r_gen_code, *p_actions, actions, false);
1586
1587
return OK;
1588
}
1589
1590
void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) {
1591
actions = p_actions;
1592
1593
time_name = "TIME";
1594
1595
List<String> func_list;
1596
1597
ShaderLanguage::get_builtin_funcs(&func_list);
1598
1599
for (const String &E : func_list) {
1600
internal_functions.insert(E);
1601
}
1602
texture_functions.insert("texture");
1603
texture_functions.insert("textureProj");
1604
texture_functions.insert("textureLod");
1605
texture_functions.insert("textureProjLod");
1606
texture_functions.insert("textureGrad");
1607
texture_functions.insert("textureProjGrad");
1608
texture_functions.insert("textureGather");
1609
texture_functions.insert("textureSize");
1610
texture_functions.insert("textureQueryLod");
1611
texture_functions.insert("textureQueryLevels");
1612
texture_functions.insert("texelFetch");
1613
}
1614
1615
ShaderCompiler::ShaderCompiler() {
1616
}
1617
1618