1/**************************************************************************/
2/* material_storage.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 "material_storage.h"
32#include "core/config/engine.h"
33#include "core/config/project_settings.h"
34#include "core/io/resource_loader.h"
35#include "servers/rendering/storage/variant_converters.h"
36#include "texture_storage.h"
37
38using namespace RendererRD;
39
40///////////////////////////////////////////////////////////////////////////
41// UBI helper functions
42
43static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
44 switch (type) {
45 case ShaderLanguage::TYPE_BOOL: {
46 uint32_t *gui = (uint32_t *)data;
47
48 if (p_array_size > 0) {
49 PackedInt32Array ba = value;
50 for (int i = 0; i < ba.size(); i++) {
51 ba.set(i, ba[i] ? 1 : 0);
52 }
53 write_array_std140<int32_t>(ba, gui, p_array_size, 4);
54 } else {
55 bool v = value;
56 gui[0] = v ? 1 : 0;
57 }
58 } break;
59 case ShaderLanguage::TYPE_BVEC2: {
60 uint32_t *gui = (uint32_t *)data;
61
62 if (p_array_size > 0) {
63 PackedInt32Array ba = convert_array_std140<Vector2i, int32_t>(value);
64 for (int i = 0; i < ba.size(); i++) {
65 ba.set(i, ba[i] ? 1 : 0);
66 }
67 write_array_std140<Vector2i>(ba, gui, p_array_size, 4);
68 } else {
69 uint32_t v = value;
70 gui[0] = v & 1 ? 1 : 0;
71 gui[1] = v & 2 ? 1 : 0;
72 }
73 } break;
74 case ShaderLanguage::TYPE_BVEC3: {
75 uint32_t *gui = (uint32_t *)data;
76
77 if (p_array_size > 0) {
78 PackedInt32Array ba = convert_array_std140<Vector3i, int32_t>(value);
79 for (int i = 0; i < ba.size(); i++) {
80 ba.set(i, ba[i] ? 1 : 0);
81 }
82 write_array_std140<Vector3i>(ba, gui, p_array_size, 4);
83 } else {
84 uint32_t v = value;
85 gui[0] = (v & 1) ? 1 : 0;
86 gui[1] = (v & 2) ? 1 : 0;
87 gui[2] = (v & 4) ? 1 : 0;
88 }
89 } break;
90 case ShaderLanguage::TYPE_BVEC4: {
91 uint32_t *gui = (uint32_t *)data;
92
93 if (p_array_size > 0) {
94 PackedInt32Array ba = convert_array_std140<Vector4i, int32_t>(value);
95 for (int i = 0; i < ba.size(); i++) {
96 ba.set(i, ba[i] ? 1 : 0);
97 }
98 write_array_std140<Vector4i>(ba, gui, p_array_size, 4);
99 } else {
100 uint32_t v = value;
101 gui[0] = (v & 1) ? 1 : 0;
102 gui[1] = (v & 2) ? 1 : 0;
103 gui[2] = (v & 4) ? 1 : 0;
104 gui[3] = (v & 8) ? 1 : 0;
105 }
106 } break;
107 case ShaderLanguage::TYPE_INT: {
108 int32_t *gui = (int32_t *)data;
109
110 if (p_array_size > 0) {
111 const PackedInt32Array &iv = value;
112 write_array_std140<int32_t>(iv, gui, p_array_size, 4);
113 } else {
114 int v = value;
115 gui[0] = v;
116 }
117 } break;
118 case ShaderLanguage::TYPE_IVEC2: {
119 int32_t *gui = (int32_t *)data;
120
121 if (p_array_size > 0) {
122 const PackedInt32Array &iv = convert_array_std140<Vector2i, int32_t>(value);
123 write_array_std140<Vector2i>(iv, gui, p_array_size, 4);
124 } else {
125 Vector2i v = convert_to_vector<Vector2i>(value);
126 gui[0] = v.x;
127 gui[1] = v.y;
128 }
129 } break;
130 case ShaderLanguage::TYPE_IVEC3: {
131 int32_t *gui = (int32_t *)data;
132
133 if (p_array_size > 0) {
134 const PackedInt32Array &iv = convert_array_std140<Vector3i, int32_t>(value);
135 write_array_std140<Vector3i>(iv, gui, p_array_size, 4);
136 } else {
137 Vector3i v = convert_to_vector<Vector3i>(value);
138 gui[0] = v.x;
139 gui[1] = v.y;
140 gui[2] = v.z;
141 }
142 } break;
143 case ShaderLanguage::TYPE_IVEC4: {
144 int32_t *gui = (int32_t *)data;
145
146 if (p_array_size > 0) {
147 const PackedInt32Array &iv = convert_array_std140<Vector4i, int32_t>(value);
148 write_array_std140<Vector4i>(iv, gui, p_array_size, 4);
149 } else {
150 Vector4i v = convert_to_vector<Vector4i>(value);
151 gui[0] = v.x;
152 gui[1] = v.y;
153 gui[2] = v.z;
154 gui[3] = v.w;
155 }
156 } break;
157 case ShaderLanguage::TYPE_UINT: {
158 uint32_t *gui = (uint32_t *)data;
159
160 if (p_array_size > 0) {
161 const PackedInt32Array &iv = value;
162 write_array_std140<uint32_t>(iv, gui, p_array_size, 4);
163 } else {
164 int v = value;
165 gui[0] = v;
166 }
167 } break;
168 case ShaderLanguage::TYPE_UVEC2: {
169 uint32_t *gui = (uint32_t *)data;
170
171 if (p_array_size > 0) {
172 const PackedInt32Array &iv = convert_array_std140<Vector2i, int32_t>(value);
173 write_array_std140<Vector2i>(iv, gui, p_array_size, 4);
174 } else {
175 Vector2i v = convert_to_vector<Vector2i>(value);
176 gui[0] = v.x;
177 gui[1] = v.y;
178 }
179 } break;
180 case ShaderLanguage::TYPE_UVEC3: {
181 uint32_t *gui = (uint32_t *)data;
182
183 if (p_array_size > 0) {
184 const PackedInt32Array &iv = convert_array_std140<Vector3i, int32_t>(value);
185 write_array_std140<Vector3i>(iv, gui, p_array_size, 4);
186 } else {
187 Vector3i v = convert_to_vector<Vector3i>(value);
188 gui[0] = v.x;
189 gui[1] = v.y;
190 gui[2] = v.z;
191 }
192 } break;
193 case ShaderLanguage::TYPE_UVEC4: {
194 uint32_t *gui = (uint32_t *)data;
195
196 if (p_array_size > 0) {
197 const PackedInt32Array &iv = convert_array_std140<Vector4i, int32_t>(value);
198 write_array_std140<Vector4i>(iv, gui, p_array_size, 4);
199 } else {
200 Vector4i v = convert_to_vector<Vector4i>(value);
201 gui[0] = v.x;
202 gui[1] = v.y;
203 gui[2] = v.z;
204 gui[3] = v.w;
205 }
206 } break;
207 case ShaderLanguage::TYPE_FLOAT: {
208 float *gui = reinterpret_cast<float *>(data);
209
210 if (p_array_size > 0) {
211 const PackedFloat32Array &a = value;
212 write_array_std140<float>(a, gui, p_array_size, 4);
213 } else {
214 float v = value;
215 gui[0] = v;
216 }
217 } break;
218 case ShaderLanguage::TYPE_VEC2: {
219 float *gui = reinterpret_cast<float *>(data);
220
221 if (p_array_size > 0) {
222 const PackedFloat32Array &a = convert_array_std140<Vector2, float>(value);
223 write_array_std140<Vector2>(a, gui, p_array_size, 4);
224 } else {
225 Vector2 v = convert_to_vector<Vector2>(value);
226 gui[0] = v.x;
227 gui[1] = v.y;
228 }
229 } break;
230 case ShaderLanguage::TYPE_VEC3: {
231 float *gui = reinterpret_cast<float *>(data);
232
233 if (p_array_size > 0) {
234 const PackedFloat32Array &a = convert_array_std140<Vector3, float>(value, p_linear_color);
235 write_array_std140<Vector3>(a, gui, p_array_size, 4);
236 } else {
237 Vector3 v = convert_to_vector<Vector3>(value, p_linear_color);
238 gui[0] = v.x;
239 gui[1] = v.y;
240 gui[2] = v.z;
241 }
242 } break;
243 case ShaderLanguage::TYPE_VEC4: {
244 float *gui = reinterpret_cast<float *>(data);
245
246 if (p_array_size > 0) {
247 const PackedFloat32Array &a = convert_array_std140<Vector4, float>(value, p_linear_color);
248 write_array_std140<Vector4>(a, gui, p_array_size, 4);
249 } else {
250 Vector4 v = convert_to_vector<Vector4>(value, p_linear_color);
251 gui[0] = v.x;
252 gui[1] = v.y;
253 gui[2] = v.z;
254 gui[3] = v.w;
255 }
256 } break;
257 case ShaderLanguage::TYPE_MAT2: {
258 float *gui = reinterpret_cast<float *>(data);
259
260 if (p_array_size > 0) {
261 const PackedFloat32Array &a = value;
262 int s = a.size();
263
264 for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
265 if (i + 3 < s) {
266 gui[j] = a[i];
267 gui[j + 1] = a[i + 1];
268
269 gui[j + 4] = a[i + 2];
270 gui[j + 5] = a[i + 3];
271 } else {
272 gui[j] = 1;
273 gui[j + 1] = 0;
274
275 gui[j + 4] = 0;
276 gui[j + 5] = 1;
277 }
278 gui[j + 2] = 0; // ignored
279 gui[j + 3] = 0; // ignored
280 gui[j + 6] = 0; // ignored
281 gui[j + 7] = 0; // ignored
282 }
283 } else {
284 Transform2D v = value;
285
286 //in std140 members of mat2 are treated as vec4s
287 gui[0] = v.columns[0][0];
288 gui[1] = v.columns[0][1];
289 gui[2] = 0; // ignored
290 gui[3] = 0; // ignored
291
292 gui[4] = v.columns[1][0];
293 gui[5] = v.columns[1][1];
294 gui[6] = 0; // ignored
295 gui[7] = 0; // ignored
296 }
297 } break;
298 case ShaderLanguage::TYPE_MAT3: {
299 float *gui = reinterpret_cast<float *>(data);
300
301 if (p_array_size > 0) {
302 const PackedFloat32Array &a = convert_array_std140<Basis, float>(value);
303 const Basis default_basis;
304 const int s = a.size();
305
306 for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
307 if (i + 8 < s) {
308 gui[j] = a[i];
309 gui[j + 1] = a[i + 1];
310 gui[j + 2] = a[i + 2];
311 gui[j + 3] = 0; // Ignored.
312
313 gui[j + 4] = a[i + 3];
314 gui[j + 5] = a[i + 4];
315 gui[j + 6] = a[i + 5];
316 gui[j + 7] = 0; // Ignored.
317
318 gui[j + 8] = a[i + 6];
319 gui[j + 9] = a[i + 7];
320 gui[j + 10] = a[i + 8];
321 gui[j + 11] = 0; // Ignored.
322 } else {
323 convert_item_std140(default_basis, gui + j);
324 }
325 }
326 } else {
327 convert_item_std140<Basis>(value, gui);
328 }
329 } break;
330 case ShaderLanguage::TYPE_MAT4: {
331 float *gui = reinterpret_cast<float *>(data);
332
333 if (p_array_size > 0) {
334 const PackedFloat32Array &a = convert_array_std140<Projection, float>(value);
335 write_array_std140<Projection>(a, gui, p_array_size, 16);
336 } else {
337 convert_item_std140<Projection>(value, gui);
338 }
339 } break;
340 default: {
341 }
342 }
343}
344
345_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
346 switch (type) {
347 case ShaderLanguage::TYPE_BOOL: {
348 uint32_t *gui = (uint32_t *)data;
349 gui[0] = value[0].boolean ? 1 : 0;
350 } break;
351 case ShaderLanguage::TYPE_BVEC2: {
352 uint32_t *gui = (uint32_t *)data;
353 gui[0] = value[0].boolean ? 1 : 0;
354 gui[1] = value[1].boolean ? 1 : 0;
355
356 } break;
357 case ShaderLanguage::TYPE_BVEC3: {
358 uint32_t *gui = (uint32_t *)data;
359 gui[0] = value[0].boolean ? 1 : 0;
360 gui[1] = value[1].boolean ? 1 : 0;
361 gui[2] = value[2].boolean ? 1 : 0;
362
363 } break;
364 case ShaderLanguage::TYPE_BVEC4: {
365 uint32_t *gui = (uint32_t *)data;
366 gui[0] = value[0].boolean ? 1 : 0;
367 gui[1] = value[1].boolean ? 1 : 0;
368 gui[2] = value[2].boolean ? 1 : 0;
369 gui[3] = value[3].boolean ? 1 : 0;
370
371 } break;
372 case ShaderLanguage::TYPE_INT: {
373 int32_t *gui = (int32_t *)data;
374 gui[0] = value[0].sint;
375
376 } break;
377 case ShaderLanguage::TYPE_IVEC2: {
378 int32_t *gui = (int32_t *)data;
379
380 for (int i = 0; i < 2; i++) {
381 gui[i] = value[i].sint;
382 }
383
384 } break;
385 case ShaderLanguage::TYPE_IVEC3: {
386 int32_t *gui = (int32_t *)data;
387
388 for (int i = 0; i < 3; i++) {
389 gui[i] = value[i].sint;
390 }
391
392 } break;
393 case ShaderLanguage::TYPE_IVEC4: {
394 int32_t *gui = (int32_t *)data;
395
396 for (int i = 0; i < 4; i++) {
397 gui[i] = value[i].sint;
398 }
399
400 } break;
401 case ShaderLanguage::TYPE_UINT: {
402 uint32_t *gui = (uint32_t *)data;
403 gui[0] = value[0].uint;
404
405 } break;
406 case ShaderLanguage::TYPE_UVEC2: {
407 int32_t *gui = (int32_t *)data;
408
409 for (int i = 0; i < 2; i++) {
410 gui[i] = value[i].uint;
411 }
412 } break;
413 case ShaderLanguage::TYPE_UVEC3: {
414 int32_t *gui = (int32_t *)data;
415
416 for (int i = 0; i < 3; i++) {
417 gui[i] = value[i].uint;
418 }
419
420 } break;
421 case ShaderLanguage::TYPE_UVEC4: {
422 int32_t *gui = (int32_t *)data;
423
424 for (int i = 0; i < 4; i++) {
425 gui[i] = value[i].uint;
426 }
427 } break;
428 case ShaderLanguage::TYPE_FLOAT: {
429 float *gui = reinterpret_cast<float *>(data);
430 gui[0] = value[0].real;
431
432 } break;
433 case ShaderLanguage::TYPE_VEC2: {
434 float *gui = reinterpret_cast<float *>(data);
435
436 for (int i = 0; i < 2; i++) {
437 gui[i] = value[i].real;
438 }
439
440 } break;
441 case ShaderLanguage::TYPE_VEC3: {
442 float *gui = reinterpret_cast<float *>(data);
443
444 for (int i = 0; i < 3; i++) {
445 gui[i] = value[i].real;
446 }
447
448 } break;
449 case ShaderLanguage::TYPE_VEC4: {
450 float *gui = reinterpret_cast<float *>(data);
451
452 for (int i = 0; i < 4; i++) {
453 gui[i] = value[i].real;
454 }
455 } break;
456 case ShaderLanguage::TYPE_MAT2: {
457 float *gui = reinterpret_cast<float *>(data);
458
459 //in std140 members of mat2 are treated as vec4s
460 gui[0] = value[0].real;
461 gui[1] = value[1].real;
462 gui[2] = 0;
463 gui[3] = 0;
464 gui[4] = value[2].real;
465 gui[5] = value[3].real;
466 gui[6] = 0;
467 gui[7] = 0;
468 } break;
469 case ShaderLanguage::TYPE_MAT3: {
470 float *gui = reinterpret_cast<float *>(data);
471
472 gui[0] = value[0].real;
473 gui[1] = value[1].real;
474 gui[2] = value[2].real;
475 gui[3] = 0;
476 gui[4] = value[3].real;
477 gui[5] = value[4].real;
478 gui[6] = value[5].real;
479 gui[7] = 0;
480 gui[8] = value[6].real;
481 gui[9] = value[7].real;
482 gui[10] = value[8].real;
483 gui[11] = 0;
484 } break;
485 case ShaderLanguage::TYPE_MAT4: {
486 float *gui = reinterpret_cast<float *>(data);
487
488 for (int i = 0; i < 16; i++) {
489 gui[i] = value[i].real;
490 }
491 } break;
492 default: {
493 }
494 }
495}
496
497_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
498 if (p_array_size <= 0) {
499 p_array_size = 1;
500 }
501
502 switch (type) {
503 case ShaderLanguage::TYPE_BOOL:
504 case ShaderLanguage::TYPE_INT:
505 case ShaderLanguage::TYPE_UINT:
506 case ShaderLanguage::TYPE_FLOAT: {
507 memset(data, 0, 4 * p_array_size);
508 } break;
509 case ShaderLanguage::TYPE_BVEC2:
510 case ShaderLanguage::TYPE_IVEC2:
511 case ShaderLanguage::TYPE_UVEC2:
512 case ShaderLanguage::TYPE_VEC2: {
513 memset(data, 0, 8 * p_array_size);
514 } break;
515 case ShaderLanguage::TYPE_BVEC3:
516 case ShaderLanguage::TYPE_IVEC3:
517 case ShaderLanguage::TYPE_UVEC3:
518 case ShaderLanguage::TYPE_VEC3: {
519 memset(data, 0, 12 * p_array_size);
520 } break;
521 case ShaderLanguage::TYPE_BVEC4:
522 case ShaderLanguage::TYPE_IVEC4:
523 case ShaderLanguage::TYPE_UVEC4:
524 case ShaderLanguage::TYPE_VEC4: {
525 memset(data, 0, 16 * p_array_size);
526 } break;
527 case ShaderLanguage::TYPE_MAT2: {
528 memset(data, 0, 32 * p_array_size);
529 } break;
530 case ShaderLanguage::TYPE_MAT3: {
531 memset(data, 0, 48 * p_array_size);
532 } break;
533 case ShaderLanguage::TYPE_MAT4: {
534 memset(data, 0, 64 * p_array_size);
535 } break;
536
537 default: {
538 }
539 }
540}
541
542///////////////////////////////////////////////////////////////////////////
543// MaterialStorage::ShaderData
544
545void MaterialStorage::ShaderData::set_path_hint(const String &p_hint) {
546 path = p_hint;
547}
548
549void MaterialStorage::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
550 if (!p_texture.is_valid()) {
551 if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
552 default_texture_params[p_name].erase(p_index);
553
554 if (default_texture_params[p_name].is_empty()) {
555 default_texture_params.erase(p_name);
556 }
557 }
558 } else {
559 if (!default_texture_params.has(p_name)) {
560 default_texture_params[p_name] = HashMap<int, RID>();
561 }
562 default_texture_params[p_name][p_index] = p_texture;
563 }
564}
565
566Variant MaterialStorage::ShaderData::get_default_parameter(const StringName &p_parameter) const {
567 if (uniforms.has(p_parameter)) {
568 ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
569 Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
570 return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
571 }
572 return Variant();
573}
574
575void MaterialStorage::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
576 SortArray<Pair<StringName, int>, ShaderLanguage::UniformOrderComparator> sorter;
577 LocalVector<Pair<StringName, int>> filtered_uniforms;
578
579 for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
580 if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
581 continue;
582 }
583 if (E.value.texture_order >= 0) {
584 filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.texture_order + 100000));
585 } else {
586 filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.order));
587 }
588 }
589 int uniform_count = filtered_uniforms.size();
590 sorter.sort(filtered_uniforms.ptr(), uniform_count);
591
592 String last_group;
593 for (int i = 0; i < uniform_count; i++) {
594 const StringName &uniform_name = filtered_uniforms[i].first;
595 const ShaderLanguage::ShaderNode::Uniform &uniform = uniforms[uniform_name];
596
597 String group = uniform.group;
598 if (!uniform.subgroup.is_empty()) {
599 group += "::" + uniform.subgroup;
600 }
601
602 if (group != last_group) {
603 PropertyInfo pi;
604 pi.usage = PROPERTY_USAGE_GROUP;
605 pi.name = group;
606 p_param_list->push_back(pi);
607
608 last_group = group;
609 }
610
611 PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniform);
612 pi.name = uniform_name;
613 p_param_list->push_back(pi);
614 }
615}
616
617void MaterialStorage::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
618 for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
619 if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
620 continue;
621 }
622
623 RendererMaterialStorage::InstanceShaderParam p;
624 p.info = ShaderLanguage::uniform_to_property_info(E.value);
625 p.info.name = E.key; //supply name
626 p.index = E.value.instance_index;
627 p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
628 p_param_list->push_back(p);
629 }
630}
631
632bool MaterialStorage::ShaderData::is_parameter_texture(const StringName &p_param) const {
633 if (!uniforms.has(p_param)) {
634 return false;
635 }
636
637 return uniforms[p_param].texture_order >= 0;
638}
639
640///////////////////////////////////////////////////////////////////////////
641// MaterialStorage::MaterialData
642
643void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
644 MaterialStorage *material_storage = MaterialStorage::get_singleton();
645 bool uses_global_buffer = false;
646
647 for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
648 if (E.value.order < 0) {
649 continue; // texture, does not go here
650 }
651
652 if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
653 continue; //instance uniforms don't appear in the buffer
654 }
655
656 if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
657 E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
658 E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
659 continue;
660 }
661
662 if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
663 //this is a global variable, get the index to it
664 GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
665 uint32_t index = 0;
666 if (gv) {
667 index = gv->buffer_index;
668 } else {
669 WARN_PRINT("Shader uses global parameter '" + E.key + "', but it was removed at some point. Material will not display correctly.");
670 }
671
672 uint32_t offset = p_uniform_offsets[E.value.order];
673 uint32_t *intptr = (uint32_t *)&p_buffer[offset];
674 *intptr = index;
675 uses_global_buffer = true;
676 continue;
677 }
678
679 //regular uniform
680 uint32_t offset = p_uniform_offsets[E.value.order];
681#ifdef DEBUG_ENABLED
682 uint32_t size = 0U;
683 // The following code enforces a 16-byte alignment of uniform arrays.
684 if (E.value.array_size > 0) {
685 size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
686 int m = (16 * E.value.array_size);
687 if ((size % m) != 0U) {
688 size += m - (size % m);
689 }
690 } else {
691 size = ShaderLanguage::get_datatype_size(E.value.type);
692 }
693 ERR_CONTINUE(offset + size > p_buffer_size);
694#endif
695 uint8_t *data = &p_buffer[offset];
696 HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(E.key);
697
698 if (V) {
699 //user provided
700 _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data, p_use_linear_color);
701
702 } else if (E.value.default_value.size()) {
703 //default value
704 _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
705 //value=E.value.default_value;
706 } else {
707 //zero because it was not provided
708 if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
709 //colors must be set as black, with alpha as 1.0
710 _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
711 } else {
712 //else just zero it out
713 _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
714 }
715 }
716 }
717
718 if (uses_global_buffer != (global_buffer_E != nullptr)) {
719 if (uses_global_buffer) {
720 global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self);
721 } else {
722 material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
723 global_buffer_E = nullptr;
724 }
725 }
726}
727
728MaterialStorage::MaterialData::~MaterialData() {
729 MaterialStorage *material_storage = MaterialStorage::get_singleton();
730
731 if (global_buffer_E) {
732 //unregister global buffers
733 material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
734 }
735
736 if (global_texture_E) {
737 //unregister global textures
738
739 for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
740 GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
741 if (v) {
742 v->texture_materials.erase(self);
743 }
744 }
745 //unregister material from those using global textures
746 material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
747 }
748
749 if (uniform_buffer.is_valid()) {
750 RD::get_singleton()->free(uniform_buffer);
751 }
752}
753
754void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color, bool p_3d_material) {
755 TextureStorage *texture_storage = TextureStorage::get_singleton();
756 MaterialStorage *material_storage = MaterialStorage::get_singleton();
757
758#ifdef TOOLS_ENABLED
759 TextureStorage::Texture *roughness_detect_texture = nullptr;
760 RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
761 TextureStorage::Texture *normal_detect_texture = nullptr;
762#endif
763
764 bool uses_global_textures = false;
765 global_textures_pass++;
766
767 for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
768 const StringName &uniform_name = p_texture_uniforms[i].name;
769 int uniform_array_size = p_texture_uniforms[i].array_size;
770
771 Vector<RID> textures;
772
773 if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
774 p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
775 p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
776 continue;
777 }
778
779 if (p_texture_uniforms[i].global) {
780 uses_global_textures = true;
781
782 GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name);
783 if (v) {
784 if (v->buffer_index >= 0) {
785 WARN_PRINT("Shader uses global parameter texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
786
787 } else {
788 HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name);
789 if (!E) {
790 E = used_global_textures.insert(uniform_name, global_textures_pass);
791 v->texture_materials.insert(self);
792 } else {
793 E->value = global_textures_pass;
794 }
795
796 textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
797 }
798
799 } else {
800 WARN_PRINT("Shader uses global parameter texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
801 }
802 } else {
803 HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name);
804 if (V) {
805 if (V->value.is_array()) {
806 Array array = (Array)V->value;
807 if (uniform_array_size > 0) {
808 for (int j = 0; j < array.size(); j++) {
809 textures.push_back(array[j]);
810 }
811 } else {
812 if (array.size() > 0) {
813 textures.push_back(array[0]);
814 }
815 }
816 } else {
817 textures.push_back(V->value);
818 }
819 }
820
821 if (uniform_array_size > 0) {
822 if (textures.size() < uniform_array_size) {
823 HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name);
824 for (int j = textures.size(); j < uniform_array_size; j++) {
825 if (W && W->value.has(j)) {
826 textures.push_back(W->value[j]);
827 } else {
828 textures.push_back(RID());
829 }
830 }
831 }
832 } else if (textures.is_empty()) {
833 HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name);
834 if (W && W->value.has(0)) {
835 textures.push_back(W->value[0]);
836 }
837 }
838 }
839
840 RID rd_texture;
841
842 if (textures.is_empty()) {
843 //check default usage
844 switch (p_texture_uniforms[i].type) {
845 case ShaderLanguage::TYPE_ISAMPLER2D:
846 case ShaderLanguage::TYPE_USAMPLER2D:
847 case ShaderLanguage::TYPE_SAMPLER2D: {
848 switch (p_texture_uniforms[i].hint) {
849 case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
850 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
851 } break;
852 case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
853 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_TRANSPARENT);
854 } break;
855 case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
856 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_ANISO);
857 } break;
858 case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
859 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
860 } break;
861 case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
862 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
863 } break;
864 default: {
865 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
866 } break;
867 }
868 } break;
869
870 case ShaderLanguage::TYPE_SAMPLERCUBE: {
871 switch (p_texture_uniforms[i].hint) {
872 case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
873 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
874 } break;
875 default: {
876 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
877 } break;
878 }
879 } break;
880 case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
881 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
882 } break;
883
884 case ShaderLanguage::TYPE_ISAMPLER3D:
885 case ShaderLanguage::TYPE_USAMPLER3D:
886 case ShaderLanguage::TYPE_SAMPLER3D: {
887 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
888 } break;
889
890 case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
891 case ShaderLanguage::TYPE_USAMPLER2DARRAY:
892 case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
893 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
894 } break;
895
896 default: {
897 }
898 }
899#ifdef TOOLS_ENABLED
900 if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
901 roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
902 }
903#endif
904 if (uniform_array_size > 0) {
905 for (int j = 0; j < uniform_array_size; j++) {
906 p_textures[k++] = rd_texture;
907 }
908 } else {
909 p_textures[k++] = rd_texture;
910 }
911 } else {
912 bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color;
913
914 for (int j = 0; j < textures.size(); j++) {
915 TextureStorage::Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
916
917 if (tex) {
918 rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
919#ifdef TOOLS_ENABLED
920 if (tex->detect_3d_callback && p_3d_material) {
921 tex->detect_3d_callback(tex->detect_3d_callback_ud);
922 }
923 if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
924 if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
925 normal_detect_texture = tex;
926 }
927 tex->detect_normal_callback(tex->detect_normal_callback_ud);
928 }
929 if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) {
930 //find the normal texture
931 roughness_detect_texture = tex;
932 roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
933 }
934 if (tex->render_target) {
935 tex->render_target->was_used = true;
936 render_target_cache.push_back(tex->render_target);
937 }
938#endif
939 }
940 if (rd_texture.is_null()) {
941 rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
942 }
943#ifdef TOOLS_ENABLED
944 if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
945 roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
946 }
947#endif
948 p_textures[k++] = rd_texture;
949 }
950 }
951 }
952 {
953 //for textures no longer used, unregister them
954 List<StringName> to_delete;
955 for (KeyValue<StringName, uint64_t> &E : used_global_textures) {
956 if (E.value != global_textures_pass) {
957 to_delete.push_back(E.key);
958
959 GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
960 if (v) {
961 v->texture_materials.erase(self);
962 }
963 }
964 }
965
966 while (to_delete.front()) {
967 used_global_textures.erase(to_delete.front()->get());
968 to_delete.pop_front();
969 }
970 //handle registering/unregistering global textures
971 if (uses_global_textures != (global_texture_E != nullptr)) {
972 if (uses_global_textures) {
973 global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self);
974 } else {
975 material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
976 global_texture_E = nullptr;
977 }
978 }
979 }
980}
981
982void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
983 if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
984 RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
985 RD::get_singleton()->free(p_uniform_set);
986 }
987}
988
989bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier) {
990 if ((uint32_t)ubo_data.size() != p_ubo_size) {
991 p_uniform_dirty = true;
992 if (uniform_buffer.is_valid()) {
993 RD::get_singleton()->free(uniform_buffer);
994 uniform_buffer = RID();
995 }
996
997 ubo_data.resize(p_ubo_size);
998 if (ubo_data.size()) {
999 uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
1000 memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
1001 }
1002
1003 //clear previous uniform set
1004 if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
1005 RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
1006 RD::get_singleton()->free(uniform_set);
1007 uniform_set = RID();
1008 }
1009 }
1010
1011 //check whether buffer changed
1012 if (p_uniform_dirty && ubo_data.size()) {
1013 update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), p_use_linear_color);
1014 RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
1015 }
1016
1017 uint32_t tex_uniform_count = 0U;
1018 for (int i = 0; i < p_texture_uniforms.size(); i++) {
1019 tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
1020 }
1021
1022 if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
1023 texture_cache.resize(tex_uniform_count);
1024 render_target_cache.clear();
1025 p_textures_dirty = true;
1026
1027 //clear previous uniform set
1028 if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
1029 RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
1030 RD::get_singleton()->free(uniform_set);
1031 uniform_set = RID();
1032 }
1033 }
1034
1035 if (p_textures_dirty && tex_uniform_count) {
1036 update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), p_use_linear_color, p_3d_material);
1037 }
1038
1039 if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) {
1040 // This material does not require an uniform set, so don't create it.
1041 return false;
1042 }
1043
1044 if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
1045 //no reason to update uniform set, only UBO (or nothing) was needed to update
1046 return false;
1047 }
1048
1049 Vector<RD::Uniform> uniforms;
1050
1051 {
1052 if (p_ubo_size) {
1053 RD::Uniform u;
1054 u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
1055 u.binding = 0;
1056 u.append_id(uniform_buffer);
1057 uniforms.push_back(u);
1058 }
1059
1060 const RID *textures = texture_cache.ptrw();
1061 for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
1062 const int array_size = p_texture_uniforms[i].array_size;
1063
1064 RD::Uniform u;
1065 u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
1066 u.binding = 1 + k;
1067 if (array_size > 0) {
1068 for (int j = 0; j < array_size; j++) {
1069 u.append_id(textures[k++]);
1070 }
1071 } else {
1072 u.append_id(textures[k++]);
1073 }
1074 uniforms.push_back(u);
1075 }
1076 }
1077
1078 uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
1079
1080 RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self);
1081
1082 return true;
1083}
1084
1085void MaterialStorage::MaterialData::set_as_used() {
1086 for (int i = 0; i < render_target_cache.size(); i++) {
1087 render_target_cache[i]->was_used = true;
1088 }
1089}
1090
1091///////////////////////////////////////////////////////////////////////////
1092// MaterialStorage
1093
1094MaterialStorage *MaterialStorage::singleton = nullptr;
1095
1096MaterialStorage *MaterialStorage::get_singleton() {
1097 return singleton;
1098}
1099
1100MaterialStorage::MaterialStorage() {
1101 singleton = this;
1102
1103 //default samplers
1104 for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
1105 for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
1106 RD::SamplerState sampler_state;
1107 switch (i) {
1108 case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
1109 sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1110 sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
1111 sampler_state.max_lod = 0;
1112 } break;
1113 case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
1114 sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1115 sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1116 sampler_state.max_lod = 0;
1117 } break;
1118 case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
1119 sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1120 sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
1121 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1122 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1123 } else {
1124 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1125 }
1126 } break;
1127 case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
1128 sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1129 sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1130 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1131 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1132 } else {
1133 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1134 }
1135
1136 } break;
1137 case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
1138 sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1139 sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
1140 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1141 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1142 } else {
1143 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1144 }
1145 sampler_state.use_anisotropy = true;
1146 sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
1147 } break;
1148 case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
1149 sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1150 sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1151 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1152 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1153 } else {
1154 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1155 }
1156 sampler_state.use_anisotropy = true;
1157 sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
1158
1159 } break;
1160 default: {
1161 }
1162 }
1163 switch (j) {
1164 case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
1165 sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
1166 sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
1167 sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
1168
1169 } break;
1170 case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
1171 sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
1172 sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
1173 sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
1174 } break;
1175 case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
1176 sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
1177 sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
1178 sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
1179 } break;
1180 default: {
1181 }
1182 }
1183
1184 default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
1185 }
1186 }
1187
1188 //custom sampler
1189 sampler_rd_configure_custom(0.0f);
1190
1191 // buffers
1192 { //create index array for copy shaders
1193 Vector<uint8_t> pv;
1194 pv.resize(6 * 2);
1195 {
1196 uint8_t *w = pv.ptrw();
1197 uint16_t *p16 = (uint16_t *)w;
1198 p16[0] = 0;
1199 p16[1] = 1;
1200 p16[2] = 2;
1201 p16[3] = 0;
1202 p16[4] = 2;
1203 p16[5] = 3;
1204 }
1205 quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT16, pv);
1206 quad_index_array = RD::get_singleton()->index_array_create(quad_index_buffer, 0, 6);
1207 }
1208
1209 // Shaders
1210 for (int i = 0; i < SHADER_TYPE_MAX; i++) {
1211 shader_data_request_func[i] = nullptr;
1212 }
1213
1214 static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
1215
1216 global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
1217 global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
1218 memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
1219 global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size);
1220 global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
1221 memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
1222 global_shader_uniforms.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
1223}
1224
1225MaterialStorage::~MaterialStorage() {
1226 memdelete_arr(global_shader_uniforms.buffer_values);
1227 memdelete_arr(global_shader_uniforms.buffer_usage);
1228 memdelete_arr(global_shader_uniforms.buffer_dirty_regions);
1229 RD::get_singleton()->free(global_shader_uniforms.buffer);
1230
1231 // buffers
1232
1233 RD::get_singleton()->free(quad_index_buffer); //array gets freed as dependency
1234
1235 //def samplers
1236 for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
1237 for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
1238 RD::get_singleton()->free(default_rd_samplers[i][j]);
1239 }
1240 }
1241
1242 //custom samplers
1243 for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
1244 for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
1245 if (custom_rd_samplers[i][j].is_valid()) {
1246 RD::get_singleton()->free(custom_rd_samplers[i][j]);
1247 }
1248 }
1249 }
1250
1251 singleton = nullptr;
1252}
1253
1254bool MaterialStorage::free(RID p_rid) {
1255 if (owns_shader(p_rid)) {
1256 shader_free(p_rid);
1257 return true;
1258 } else if (owns_material(p_rid)) {
1259 material_free(p_rid);
1260 return true;
1261 }
1262
1263 return false;
1264}
1265
1266/* Samplers */
1267
1268void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
1269 for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
1270 for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
1271 RD::SamplerState sampler_state;
1272 switch (i) {
1273 case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
1274 sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1275 sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
1276 sampler_state.max_lod = 0;
1277 } break;
1278 case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
1279 sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1280 sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1281 sampler_state.max_lod = 0;
1282 } break;
1283 case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
1284 sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1285 sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
1286 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1287 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1288 } else {
1289 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1290 }
1291 sampler_state.lod_bias = p_mipmap_bias;
1292 } break;
1293 case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
1294 sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1295 sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1296 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1297 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1298 } else {
1299 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1300 }
1301 sampler_state.lod_bias = p_mipmap_bias;
1302
1303 } break;
1304 case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
1305 sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1306 sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
1307 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1308 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1309 } else {
1310 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1311 }
1312 sampler_state.lod_bias = p_mipmap_bias;
1313 sampler_state.use_anisotropy = true;
1314 sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
1315 } break;
1316 case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
1317 sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1318 sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1319 if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
1320 sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
1321 } else {
1322 sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
1323 }
1324 sampler_state.lod_bias = p_mipmap_bias;
1325 sampler_state.use_anisotropy = true;
1326 sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
1327
1328 } break;
1329 default: {
1330 }
1331 }
1332 switch (j) {
1333 case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
1334 sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
1335 sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
1336 sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
1337
1338 } break;
1339 case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
1340 sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
1341 sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
1342 sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
1343 } break;
1344 case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
1345 sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
1346 sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
1347 sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
1348 } break;
1349 default: {
1350 }
1351 }
1352
1353 if (custom_rd_samplers[i][j].is_valid()) {
1354 RD::get_singleton()->free(custom_rd_samplers[i][j]);
1355 }
1356
1357 custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
1358 }
1359 }
1360}
1361
1362/* GLOBAL SHADER UNIFORM API */
1363
1364int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) {
1365 int32_t idx = 0;
1366 while (idx + p_elements <= global_shader_uniforms.buffer_size) {
1367 if (global_shader_uniforms.buffer_usage[idx].elements == 0) {
1368 bool valid = true;
1369 for (uint32_t i = 1; i < p_elements; i++) {
1370 if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) {
1371 valid = false;
1372 idx += i + global_shader_uniforms.buffer_usage[idx + i].elements;
1373 break;
1374 }
1375 }
1376
1377 if (!valid) {
1378 continue; //if not valid, idx is in new position
1379 }
1380
1381 return idx;
1382 } else {
1383 idx += global_shader_uniforms.buffer_usage[idx].elements;
1384 }
1385 }
1386
1387 return -1;
1388}
1389
1390void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value) {
1391 switch (p_type) {
1392 case RS::GLOBAL_VAR_TYPE_BOOL: {
1393 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1394 bool b = p_value;
1395 bv.x = b ? 1.0 : 0.0;
1396 bv.y = 0.0;
1397 bv.z = 0.0;
1398 bv.w = 0.0;
1399
1400 } break;
1401 case RS::GLOBAL_VAR_TYPE_BVEC2: {
1402 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1403 uint32_t bvec = p_value;
1404 bv.x = (bvec & 1) ? 1.0 : 0.0;
1405 bv.y = (bvec & 2) ? 1.0 : 0.0;
1406 bv.z = 0.0;
1407 bv.w = 0.0;
1408 } break;
1409 case RS::GLOBAL_VAR_TYPE_BVEC3: {
1410 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1411 uint32_t bvec = p_value;
1412 bv.x = (bvec & 1) ? 1.0 : 0.0;
1413 bv.y = (bvec & 2) ? 1.0 : 0.0;
1414 bv.z = (bvec & 4) ? 1.0 : 0.0;
1415 bv.w = 0.0;
1416 } break;
1417 case RS::GLOBAL_VAR_TYPE_BVEC4: {
1418 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1419 uint32_t bvec = p_value;
1420 bv.x = (bvec & 1) ? 1.0 : 0.0;
1421 bv.y = (bvec & 2) ? 1.0 : 0.0;
1422 bv.z = (bvec & 4) ? 1.0 : 0.0;
1423 bv.w = (bvec & 8) ? 1.0 : 0.0;
1424 } break;
1425 case RS::GLOBAL_VAR_TYPE_INT: {
1426 GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
1427 int32_t v = p_value;
1428 bv.x = v;
1429 bv.y = 0;
1430 bv.z = 0;
1431 bv.w = 0;
1432 } break;
1433 case RS::GLOBAL_VAR_TYPE_IVEC2: {
1434 GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
1435 Vector2i v = convert_to_vector<Vector2i>(p_value);
1436 bv.x = v.x;
1437 bv.y = v.y;
1438 bv.z = 0;
1439 bv.w = 0;
1440 } break;
1441 case RS::GLOBAL_VAR_TYPE_IVEC3: {
1442 GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
1443 Vector3i v = convert_to_vector<Vector3i>(p_value);
1444 bv.x = v.x;
1445 bv.y = v.y;
1446 bv.z = v.z;
1447 bv.w = 0;
1448 } break;
1449 case RS::GLOBAL_VAR_TYPE_IVEC4: {
1450 GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
1451 Vector4i v = convert_to_vector<Vector4i>(p_value);
1452 bv.x = v.x;
1453 bv.y = v.y;
1454 bv.z = v.z;
1455 bv.w = v.w;
1456 } break;
1457 case RS::GLOBAL_VAR_TYPE_RECT2I: {
1458 GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
1459 Rect2i v = p_value;
1460 bv.x = v.position.x;
1461 bv.y = v.position.y;
1462 bv.z = v.size.x;
1463 bv.w = v.size.y;
1464 } break;
1465 case RS::GLOBAL_VAR_TYPE_UINT: {
1466 GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
1467 uint32_t v = p_value;
1468 bv.x = v;
1469 bv.y = 0;
1470 bv.z = 0;
1471 bv.w = 0;
1472 } break;
1473 case RS::GLOBAL_VAR_TYPE_UVEC2: {
1474 GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
1475 Vector2i v = convert_to_vector<Vector2i>(p_value);
1476 bv.x = v.x;
1477 bv.y = v.y;
1478 bv.z = 0;
1479 bv.w = 0;
1480 } break;
1481 case RS::GLOBAL_VAR_TYPE_UVEC3: {
1482 GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
1483 Vector3i v = convert_to_vector<Vector3i>(p_value);
1484 bv.x = v.x;
1485 bv.y = v.y;
1486 bv.z = v.z;
1487 bv.w = 0;
1488 } break;
1489 case RS::GLOBAL_VAR_TYPE_UVEC4: {
1490 GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
1491 Vector4i v = convert_to_vector<Vector4i>(p_value);
1492 bv.x = v.x;
1493 bv.y = v.y;
1494 bv.z = v.z;
1495 bv.w = v.w;
1496 } break;
1497 case RS::GLOBAL_VAR_TYPE_FLOAT: {
1498 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1499 float v = p_value;
1500 bv.x = v;
1501 bv.y = 0;
1502 bv.z = 0;
1503 bv.w = 0;
1504 } break;
1505 case RS::GLOBAL_VAR_TYPE_VEC2: {
1506 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1507 Vector2 v = convert_to_vector<Vector2>(p_value);
1508 bv.x = v.x;
1509 bv.y = v.y;
1510 bv.z = 0;
1511 bv.w = 0;
1512 } break;
1513 case RS::GLOBAL_VAR_TYPE_VEC3: {
1514 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1515 Vector3 v = convert_to_vector<Vector3>(p_value);
1516 bv.x = v.x;
1517 bv.y = v.y;
1518 bv.z = v.z;
1519 bv.w = 0;
1520 } break;
1521 case RS::GLOBAL_VAR_TYPE_VEC4: {
1522 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1523 Vector4 v = convert_to_vector<Vector4>(p_value);
1524 bv.x = v.x;
1525 bv.y = v.y;
1526 bv.z = v.z;
1527 bv.w = v.w;
1528 } break;
1529 case RS::GLOBAL_VAR_TYPE_COLOR: {
1530 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1531 Color v = p_value;
1532 bv.x = v.r;
1533 bv.y = v.g;
1534 bv.z = v.b;
1535 bv.w = v.a;
1536
1537 GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1];
1538 v = v.srgb_to_linear();
1539 bv_linear.x = v.r;
1540 bv_linear.y = v.g;
1541 bv_linear.z = v.b;
1542 bv_linear.w = v.a;
1543
1544 } break;
1545 case RS::GLOBAL_VAR_TYPE_RECT2: {
1546 GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
1547 Rect2 v = p_value;
1548 bv.x = v.position.x;
1549 bv.y = v.position.y;
1550 bv.z = v.size.x;
1551 bv.w = v.size.y;
1552 } break;
1553 case RS::GLOBAL_VAR_TYPE_MAT2: {
1554 GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
1555 Vector<float> m2 = p_value;
1556 if (m2.size() < 4) {
1557 m2.resize(4);
1558 }
1559 bv[0].x = m2[0];
1560 bv[0].y = m2[1];
1561 bv[0].z = 0;
1562 bv[0].w = 0;
1563
1564 bv[1].x = m2[2];
1565 bv[1].y = m2[3];
1566 bv[1].z = 0;
1567 bv[1].w = 0;
1568
1569 } break;
1570 case RS::GLOBAL_VAR_TYPE_MAT3: {
1571 GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
1572 Basis v = p_value;
1573 convert_item_std140<Basis>(v, &bv->x);
1574
1575 } break;
1576 case RS::GLOBAL_VAR_TYPE_MAT4: {
1577 GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
1578 Projection m = p_value;
1579 convert_item_std140<Projection>(m, &bv->x);
1580
1581 } break;
1582 case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
1583 GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
1584 Transform2D v = p_value;
1585 convert_item_std140<Transform2D>(v, &bv->x);
1586
1587 } break;
1588 case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
1589 GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
1590 Transform3D v = p_value;
1591 convert_item_std140<Transform3D>(v, &bv->x);
1592
1593 } break;
1594 default: {
1595 ERR_FAIL();
1596 }
1597 }
1598}
1599
1600void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
1601 int32_t prev_chunk = -1;
1602
1603 for (int32_t i = 0; i < p_elements; i++) {
1604 int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
1605 if (chunk != prev_chunk) {
1606 if (!global_shader_uniforms.buffer_dirty_regions[chunk]) {
1607 global_shader_uniforms.buffer_dirty_regions[chunk] = true;
1608 global_shader_uniforms.buffer_dirty_region_count++;
1609 }
1610 }
1611
1612 prev_chunk = chunk;
1613 }
1614}
1615
1616void MaterialStorage::global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) {
1617 ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name));
1618 GlobalShaderUniforms::Variable gv;
1619 gv.type = p_type;
1620 gv.value = p_value;
1621 gv.buffer_index = -1;
1622
1623 if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
1624 //is texture
1625 global_shader_uniforms.must_update_texture_materials = true; //normally there are none
1626 } else {
1627 gv.buffer_elements = 1;
1628 if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
1629 //color needs to elements to store srgb and linear
1630 gv.buffer_elements = 2;
1631 }
1632 if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
1633 //color needs to elements to store srgb and linear
1634 gv.buffer_elements = 3;
1635 }
1636 if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
1637 //color needs to elements to store srgb and linear
1638 gv.buffer_elements = 4;
1639 }
1640
1641 //is vector, allocate in buffer and update index
1642 gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements);
1643 ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
1644 global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
1645 _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
1646 _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
1647
1648 global_shader_uniforms.must_update_buffer_materials = true; //normally there are none
1649 }
1650
1651 global_shader_uniforms.variables[p_name] = gv;
1652}
1653
1654void MaterialStorage::global_shader_parameter_remove(const StringName &p_name) {
1655 if (!global_shader_uniforms.variables.has(p_name)) {
1656 return;
1657 }
1658 const GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
1659
1660 if (gv.buffer_index >= 0) {
1661 global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0;
1662 global_shader_uniforms.must_update_buffer_materials = true;
1663 } else {
1664 global_shader_uniforms.must_update_texture_materials = true;
1665 }
1666
1667 global_shader_uniforms.variables.erase(p_name);
1668}
1669
1670Vector<StringName> MaterialStorage::global_shader_parameter_get_list() const {
1671 if (!Engine::get_singleton()->is_editor_hint()) {
1672 ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
1673 }
1674
1675 Vector<StringName> names;
1676 for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) {
1677 names.push_back(E.key);
1678 }
1679 names.sort_custom<StringName::AlphCompare>();
1680 return names;
1681}
1682
1683void MaterialStorage::global_shader_parameter_set(const StringName &p_name, const Variant &p_value) {
1684 ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name));
1685 GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
1686 gv.value = p_value;
1687 if (gv.override.get_type() == Variant::NIL) {
1688 if (gv.buffer_index >= 0) {
1689 //buffer
1690 _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
1691 _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
1692 } else {
1693 //texture
1694 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1695 for (const RID &E : gv.texture_materials) {
1696 Material *material = material_storage->get_material(E);
1697 ERR_CONTINUE(!material);
1698 material_storage->_material_queue_update(material, false, true);
1699 }
1700 }
1701 }
1702}
1703
1704void MaterialStorage::global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) {
1705 if (!global_shader_uniforms.variables.has(p_name)) {
1706 return; //variable may not exist
1707 }
1708
1709 ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
1710
1711 GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
1712
1713 gv.override = p_value;
1714
1715 if (gv.buffer_index >= 0) {
1716 //buffer
1717 if (gv.override.get_type() == Variant::NIL) {
1718 _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
1719 } else {
1720 _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override);
1721 }
1722
1723 _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
1724 } else {
1725 //texture
1726 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1727 for (const RID &E : gv.texture_materials) {
1728 Material *material = material_storage->get_material(E);
1729 ERR_CONTINUE(!material);
1730 material_storage->_material_queue_update(material, false, true);
1731 }
1732 }
1733}
1734
1735Variant MaterialStorage::global_shader_parameter_get(const StringName &p_name) const {
1736 if (!Engine::get_singleton()->is_editor_hint()) {
1737 ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
1738 }
1739
1740 if (!global_shader_uniforms.variables.has(p_name)) {
1741 return Variant();
1742 }
1743
1744 return global_shader_uniforms.variables[p_name].value;
1745}
1746
1747RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type_internal(const StringName &p_name) const {
1748 if (!global_shader_uniforms.variables.has(p_name)) {
1749 return RS::GLOBAL_VAR_TYPE_MAX;
1750 }
1751
1752 return global_shader_uniforms.variables[p_name].type;
1753}
1754
1755RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type(const StringName &p_name) const {
1756 if (!Engine::get_singleton()->is_editor_hint()) {
1757 ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
1758 }
1759
1760 return global_shader_parameter_get_type_internal(p_name);
1761}
1762
1763void MaterialStorage::global_shader_parameters_load_settings(bool p_load_textures) {
1764 List<PropertyInfo> settings;
1765 ProjectSettings::get_singleton()->get_property_list(&settings);
1766
1767 for (const PropertyInfo &E : settings) {
1768 if (E.name.begins_with("shader_globals/")) {
1769 StringName name = E.name.get_slice("/", 1);
1770 Dictionary d = GLOBAL_GET(E.name);
1771
1772 ERR_CONTINUE(!d.has("type"));
1773 ERR_CONTINUE(!d.has("value"));
1774
1775 String type = d["type"];
1776
1777 static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
1778 "bool",
1779 "bvec2",
1780 "bvec3",
1781 "bvec4",
1782 "int",
1783 "ivec2",
1784 "ivec3",
1785 "ivec4",
1786 "rect2i",
1787 "uint",
1788 "uvec2",
1789 "uvec3",
1790 "uvec4",
1791 "float",
1792 "vec2",
1793 "vec3",
1794 "vec4",
1795 "color",
1796 "rect2",
1797 "mat2",
1798 "mat3",
1799 "mat4",
1800 "transform_2d",
1801 "transform",
1802 "sampler2D",
1803 "sampler2DArray",
1804 "sampler3D",
1805 "samplerCube",
1806 };
1807
1808 RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
1809
1810 for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
1811 if (global_var_type_names[i] == type) {
1812 gvtype = RS::GlobalShaderParameterType(i);
1813 break;
1814 }
1815 }
1816
1817 ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
1818
1819 Variant value = d["value"];
1820
1821 if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
1822 //textire
1823 if (!p_load_textures) {
1824 continue;
1825 }
1826
1827 String path = value;
1828 if (path.is_empty()) {
1829 value = RID();
1830 } else {
1831 Ref<Resource> resource = ResourceLoader::load(path);
1832 value = resource;
1833 }
1834 }
1835
1836 if (global_shader_uniforms.variables.has(name)) {
1837 //has it, update it
1838 global_shader_parameter_set(name, value);
1839 } else {
1840 global_shader_parameter_add(name, gvtype, value);
1841 }
1842 }
1843 }
1844}
1845
1846void MaterialStorage::global_shader_parameters_clear() {
1847 global_shader_uniforms.variables.clear(); //not right but for now enough
1848}
1849
1850RID MaterialStorage::global_shader_uniforms_get_storage_buffer() const {
1851 return global_shader_uniforms.buffer;
1852}
1853
1854int32_t MaterialStorage::global_shader_parameters_instance_allocate(RID p_instance) {
1855 ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
1856 int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
1857 global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway
1858 ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
1859 global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
1860 return pos;
1861}
1862
1863void MaterialStorage::global_shader_parameters_instance_free(RID p_instance) {
1864 ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance));
1865 int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
1866 if (pos >= 0) {
1867 global_shader_uniforms.buffer_usage[pos].elements = 0;
1868 }
1869 global_shader_uniforms.instance_buffer_pos.erase(p_instance);
1870}
1871
1872void MaterialStorage::global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count) {
1873 if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) {
1874 return; //just not allocated, ignore
1875 }
1876 int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
1877
1878 if (pos < 0) {
1879 return; //again, not allocated, ignore
1880 }
1881 ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
1882
1883 Variant::Type value_type = p_value.get_type();
1884 ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(value_type)); //anything greater not supported
1885
1886 const ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
1887 ShaderLanguage::TYPE_MAX, //nil
1888 ShaderLanguage::TYPE_BOOL, //bool
1889 ShaderLanguage::TYPE_INT, //int
1890 ShaderLanguage::TYPE_FLOAT, //float
1891 ShaderLanguage::TYPE_MAX, //string
1892 ShaderLanguage::TYPE_VEC2, //vec2
1893 ShaderLanguage::TYPE_IVEC2, //vec2i
1894 ShaderLanguage::TYPE_VEC4, //rect2
1895 ShaderLanguage::TYPE_IVEC4, //rect2i
1896 ShaderLanguage::TYPE_VEC3, // vec3
1897 ShaderLanguage::TYPE_IVEC3, //vec3i
1898 ShaderLanguage::TYPE_MAX, //xform2d not supported here
1899 ShaderLanguage::TYPE_VEC4, //vec4
1900 ShaderLanguage::TYPE_IVEC4, //vec4i
1901 ShaderLanguage::TYPE_VEC4, //plane
1902 ShaderLanguage::TYPE_VEC4, //quat
1903 ShaderLanguage::TYPE_MAX, //aabb not supported here
1904 ShaderLanguage::TYPE_MAX, //basis not supported here
1905 ShaderLanguage::TYPE_MAX, //xform not supported here
1906 ShaderLanguage::TYPE_MAX, //projection not supported here
1907 ShaderLanguage::TYPE_VEC4 //color
1908 };
1909
1910 ShaderLanguage::DataType datatype = ShaderLanguage::TYPE_MAX;
1911 if (value_type == Variant::INT && p_flags_count > 0) {
1912 switch (p_flags_count) {
1913 case 1:
1914 datatype = ShaderLanguage::TYPE_BVEC2;
1915 break;
1916 case 2:
1917 datatype = ShaderLanguage::TYPE_BVEC3;
1918 break;
1919 case 3:
1920 datatype = ShaderLanguage::TYPE_BVEC4;
1921 break;
1922 }
1923 } else {
1924 datatype = datatype_from_value[value_type];
1925 }
1926 ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(value_type)); //anything greater not supported
1927
1928 pos += p_index;
1929
1930 _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos], true); //instances always use linear color in this renderer
1931 _global_shader_uniform_mark_buffer_dirty(pos, 1);
1932}
1933
1934void MaterialStorage::_update_global_shader_uniforms() {
1935 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1936 if (global_shader_uniforms.buffer_dirty_region_count > 0) {
1937 uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
1938 if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) {
1939 // 25% of regions dirty, just update all buffer
1940 RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values);
1941 memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
1942 } else {
1943 uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
1944
1945 for (uint32_t i = 0; i < total_regions; i++) {
1946 if (global_shader_uniforms.buffer_dirty_regions[i]) {
1947 RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]);
1948
1949 global_shader_uniforms.buffer_dirty_regions[i] = false;
1950 }
1951 }
1952 }
1953
1954 global_shader_uniforms.buffer_dirty_region_count = 0;
1955 }
1956
1957 if (global_shader_uniforms.must_update_buffer_materials) {
1958 // only happens in the case of a buffer variable added or removed,
1959 // so not often.
1960 for (const RID &E : global_shader_uniforms.materials_using_buffer) {
1961 Material *material = material_storage->get_material(E);
1962 ERR_CONTINUE(!material); //wtf
1963
1964 material_storage->_material_queue_update(material, true, false);
1965 }
1966
1967 global_shader_uniforms.must_update_buffer_materials = false;
1968 }
1969
1970 if (global_shader_uniforms.must_update_texture_materials) {
1971 // only happens in the case of a buffer variable added or removed,
1972 // so not often.
1973 for (const RID &E : global_shader_uniforms.materials_using_texture) {
1974 Material *material = material_storage->get_material(E);
1975 ERR_CONTINUE(!material); //wtf
1976
1977 material_storage->_material_queue_update(material, false, true);
1978 }
1979
1980 global_shader_uniforms.must_update_texture_materials = false;
1981 }
1982}
1983
1984/* SHADER API */
1985
1986RID MaterialStorage::shader_allocate() {
1987 return shader_owner.allocate_rid();
1988}
1989
1990void MaterialStorage::shader_initialize(RID p_rid) {
1991 Shader shader;
1992 shader.data = nullptr;
1993 shader.type = SHADER_TYPE_MAX;
1994
1995 shader_owner.initialize_rid(p_rid, shader);
1996}
1997
1998void MaterialStorage::shader_free(RID p_rid) {
1999 Shader *shader = shader_owner.get_or_null(p_rid);
2000 ERR_FAIL_COND(!shader);
2001
2002 //make material unreference this
2003 while (shader->owners.size()) {
2004 material_set_shader((*shader->owners.begin())->self, RID());
2005 }
2006
2007 //clear data if exists
2008 if (shader->data) {
2009 memdelete(shader->data);
2010 }
2011 shader_owner.free(p_rid);
2012}
2013
2014void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
2015 Shader *shader = shader_owner.get_or_null(p_shader);
2016 ERR_FAIL_COND(!shader);
2017
2018 shader->code = p_code;
2019 String mode_string = ShaderLanguage::get_shader_type(p_code);
2020
2021 ShaderType new_type;
2022 if (mode_string == "canvas_item") {
2023 new_type = SHADER_TYPE_2D;
2024 } else if (mode_string == "particles") {
2025 new_type = SHADER_TYPE_PARTICLES;
2026 } else if (mode_string == "spatial") {
2027 new_type = SHADER_TYPE_3D;
2028 } else if (mode_string == "sky") {
2029 new_type = SHADER_TYPE_SKY;
2030 } else if (mode_string == "fog") {
2031 new_type = SHADER_TYPE_FOG;
2032 } else {
2033 new_type = SHADER_TYPE_MAX;
2034 }
2035
2036 if (new_type != shader->type) {
2037 if (shader->data) {
2038 memdelete(shader->data);
2039 shader->data = nullptr;
2040 }
2041
2042 for (Material *E : shader->owners) {
2043 Material *material = E;
2044 material->shader_type = new_type;
2045 if (material->data) {
2046 memdelete(material->data);
2047 material->data = nullptr;
2048 }
2049 }
2050
2051 shader->type = new_type;
2052
2053 if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
2054 shader->data = shader_data_request_func[new_type]();
2055 } else {
2056 shader->type = SHADER_TYPE_MAX; //invalid
2057 }
2058
2059 for (Material *E : shader->owners) {
2060 Material *material = E;
2061 if (shader->data) {
2062 material->data = material_get_data_request_function(new_type)(shader->data);
2063 material->data->self = material->self;
2064 material->data->set_next_pass(material->next_pass);
2065 material->data->set_render_priority(material->priority);
2066 }
2067 material->shader_type = new_type;
2068 }
2069
2070 if (shader->data) {
2071 for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) {
2072 for (const KeyValue<int, RID> &E2 : E.value) {
2073 shader->data->set_default_texture_parameter(E.key, E2.value, E2.key);
2074 }
2075 }
2076 }
2077 }
2078
2079 if (shader->data) {
2080 shader->data->set_path_hint(shader->path_hint);
2081 shader->data->set_code(p_code);
2082 }
2083
2084 for (Material *E : shader->owners) {
2085 Material *material = E;
2086 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2087 _material_queue_update(material, true, true);
2088 }
2089}
2090
2091void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
2092 Shader *shader = shader_owner.get_or_null(p_shader);
2093 ERR_FAIL_COND(!shader);
2094
2095 shader->path_hint = p_path;
2096 if (shader->data) {
2097 shader->data->set_path_hint(p_path);
2098 }
2099}
2100
2101String MaterialStorage::shader_get_code(RID p_shader) const {
2102 Shader *shader = shader_owner.get_or_null(p_shader);
2103 ERR_FAIL_COND_V(!shader, String());
2104 return shader->code;
2105}
2106
2107void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
2108 Shader *shader = shader_owner.get_or_null(p_shader);
2109 ERR_FAIL_COND(!shader);
2110 if (shader->data) {
2111 return shader->data->get_shader_uniform_list(p_param_list);
2112 }
2113}
2114
2115void MaterialStorage::shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
2116 Shader *shader = shader_owner.get_or_null(p_shader);
2117 ERR_FAIL_COND(!shader);
2118
2119 if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) {
2120 if (!shader->default_texture_parameter.has(p_name)) {
2121 shader->default_texture_parameter[p_name] = HashMap<int, RID>();
2122 }
2123 shader->default_texture_parameter[p_name][p_index] = p_texture;
2124 } else {
2125 if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
2126 shader->default_texture_parameter[p_name].erase(p_index);
2127
2128 if (shader->default_texture_parameter[p_name].is_empty()) {
2129 shader->default_texture_parameter.erase(p_name);
2130 }
2131 }
2132 }
2133 if (shader->data) {
2134 shader->data->set_default_texture_parameter(p_name, p_texture, p_index);
2135 }
2136 for (Material *E : shader->owners) {
2137 Material *material = E;
2138 _material_queue_update(material, false, true);
2139 }
2140}
2141
2142RID MaterialStorage::shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const {
2143 Shader *shader = shader_owner.get_or_null(p_shader);
2144 ERR_FAIL_COND_V(!shader, RID());
2145 if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
2146 return shader->default_texture_parameter[p_name][p_index];
2147 }
2148
2149 return RID();
2150}
2151
2152Variant MaterialStorage::shader_get_parameter_default(RID p_shader, const StringName &p_param) const {
2153 Shader *shader = shader_owner.get_or_null(p_shader);
2154 ERR_FAIL_COND_V(!shader, Variant());
2155 if (shader->data) {
2156 return shader->data->get_default_parameter(p_param);
2157 }
2158 return Variant();
2159}
2160
2161void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
2162 ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
2163 shader_data_request_func[p_shader_type] = p_function;
2164}
2165
2166RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const {
2167 Shader *shader = shader_owner.get_or_null(p_shader);
2168 ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
2169 if (shader->data) {
2170 return shader->data->get_native_source_code();
2171 }
2172 return RS::ShaderNativeSourceCode();
2173}
2174
2175/* MATERIAL API */
2176
2177void MaterialStorage::_material_uniform_set_erased(void *p_material) {
2178 RID rid = *(RID *)p_material;
2179 Material *material = MaterialStorage::get_singleton()->get_material(rid);
2180 if (material) {
2181 if (material->data) {
2182 // Uniform set may be gone because a dependency was erased. This happens
2183 // if a texture is deleted, so re-create it.
2184 MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
2185 }
2186 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2187 }
2188}
2189
2190void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
2191 material->uniform_dirty = material->uniform_dirty || p_uniform;
2192 material->texture_dirty = material->texture_dirty || p_texture;
2193
2194 if (material->update_element.in_list()) {
2195 return;
2196 }
2197
2198 material_update_list.add(&material->update_element);
2199}
2200
2201void MaterialStorage::_update_queued_materials() {
2202 while (material_update_list.first()) {
2203 Material *material = material_update_list.first()->self();
2204 bool uniforms_changed = false;
2205
2206 if (material->data) {
2207 uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
2208 }
2209 material->texture_dirty = false;
2210 material->uniform_dirty = false;
2211
2212 material_update_list.remove(&material->update_element);
2213
2214 if (uniforms_changed) {
2215 //some implementations such as 3D renderer cache the material uniform set, so update is required
2216 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2217 }
2218 }
2219}
2220
2221RID MaterialStorage::material_allocate() {
2222 return material_owner.allocate_rid();
2223}
2224
2225void MaterialStorage::material_initialize(RID p_rid) {
2226 material_owner.initialize_rid(p_rid);
2227 Material *material = material_owner.get_or_null(p_rid);
2228 material->self = p_rid;
2229}
2230
2231void MaterialStorage::material_free(RID p_rid) {
2232 Material *material = material_owner.get_or_null(p_rid);
2233 ERR_FAIL_COND(!material);
2234
2235 // Need to clear texture arrays to prevent spin locking of their RID's.
2236 // This happens when the app is being closed.
2237 for (KeyValue<StringName, Variant> &E : material->params) {
2238 if (E.value.get_type() == Variant::ARRAY) {
2239 Array(E.value).clear();
2240 }
2241 }
2242
2243 material_set_shader(p_rid, RID()); //clean up shader
2244 material->dependency.deleted_notify(p_rid);
2245
2246 material_owner.free(p_rid);
2247}
2248
2249void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
2250 Material *material = material_owner.get_or_null(p_material);
2251 ERR_FAIL_COND(!material);
2252
2253 if (material->data) {
2254 memdelete(material->data);
2255 material->data = nullptr;
2256 }
2257
2258 if (material->shader) {
2259 material->shader->owners.erase(material);
2260 material->shader = nullptr;
2261 material->shader_type = SHADER_TYPE_MAX;
2262 }
2263
2264 if (p_shader.is_null()) {
2265 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2266 material->shader_id = 0;
2267 return;
2268 }
2269
2270 Shader *shader = get_shader(p_shader);
2271 ERR_FAIL_COND(!shader);
2272 material->shader = shader;
2273 material->shader_type = shader->type;
2274 material->shader_id = p_shader.get_local_index();
2275 shader->owners.insert(material);
2276
2277 if (shader->type == SHADER_TYPE_MAX) {
2278 return;
2279 }
2280
2281 ERR_FAIL_COND(shader->data == nullptr);
2282
2283 material->data = material_data_request_func[shader->type](shader->data);
2284 material->data->self = p_material;
2285 material->data->set_next_pass(material->next_pass);
2286 material->data->set_render_priority(material->priority);
2287 //updating happens later
2288 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2289 _material_queue_update(material, true, true);
2290}
2291
2292MaterialStorage::ShaderData *MaterialStorage::material_get_shader_data(RID p_material) {
2293 const MaterialStorage::Material *material = MaterialStorage::get_singleton()->get_material(p_material);
2294 if (material && material->shader && material->shader->data) {
2295 return material->shader->data;
2296 }
2297
2298 return nullptr;
2299}
2300
2301void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
2302 Material *material = material_owner.get_or_null(p_material);
2303 ERR_FAIL_COND(!material);
2304
2305 if (p_value.get_type() == Variant::NIL) {
2306 material->params.erase(p_param);
2307 } else {
2308 ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
2309 material->params[p_param] = p_value;
2310 }
2311
2312 if (material->shader && material->shader->data) { //shader is valid
2313 bool is_texture = material->shader->data->is_parameter_texture(p_param);
2314 _material_queue_update(material, !is_texture, is_texture);
2315 } else {
2316 _material_queue_update(material, true, true);
2317 }
2318}
2319
2320Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
2321 Material *material = material_owner.get_or_null(p_material);
2322 ERR_FAIL_COND_V(!material, Variant());
2323 if (material->params.has(p_param)) {
2324 return material->params[p_param];
2325 } else {
2326 return Variant();
2327 }
2328}
2329
2330void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
2331 Material *material = material_owner.get_or_null(p_material);
2332 ERR_FAIL_COND(!material);
2333
2334 if (material->next_pass == p_next_material) {
2335 return;
2336 }
2337
2338 material->next_pass = p_next_material;
2339 if (material->data) {
2340 material->data->set_next_pass(p_next_material);
2341 }
2342
2343 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2344}
2345
2346void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
2347 Material *material = material_owner.get_or_null(p_material);
2348 ERR_FAIL_COND(!material);
2349 material->priority = priority;
2350 if (material->data) {
2351 material->data->set_render_priority(priority);
2352 }
2353 material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
2354}
2355
2356bool MaterialStorage::material_is_animated(RID p_material) {
2357 Material *material = material_owner.get_or_null(p_material);
2358 ERR_FAIL_COND_V(!material, false);
2359 if (material->shader && material->shader->data) {
2360 if (material->shader->data->is_animated()) {
2361 return true;
2362 } else if (material->next_pass.is_valid()) {
2363 return material_is_animated(material->next_pass);
2364 }
2365 }
2366 return false; //by default nothing is animated
2367}
2368
2369bool MaterialStorage::material_casts_shadows(RID p_material) {
2370 Material *material = material_owner.get_or_null(p_material);
2371 ERR_FAIL_COND_V(!material, true);
2372 if (material->shader && material->shader->data) {
2373 if (material->shader->data->casts_shadows()) {
2374 return true;
2375 } else if (material->next_pass.is_valid()) {
2376 return material_casts_shadows(material->next_pass);
2377 }
2378 }
2379 return true; //by default everything casts shadows
2380}
2381
2382void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
2383 Material *material = material_owner.get_or_null(p_material);
2384 ERR_FAIL_COND(!material);
2385 if (material->shader && material->shader->data) {
2386 material->shader->data->get_instance_param_list(r_parameters);
2387
2388 if (material->next_pass.is_valid()) {
2389 material_get_instance_shader_parameters(material->next_pass, r_parameters);
2390 }
2391 }
2392}
2393
2394void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
2395 Material *material = material_owner.get_or_null(p_material);
2396 ERR_FAIL_COND(!material);
2397 p_instance->update_dependency(&material->dependency);
2398 if (material->next_pass.is_valid()) {
2399 material_update_dependency(material->next_pass, p_instance);
2400 }
2401}
2402
2403Vector<RD::Uniform> MaterialStorage::get_default_sampler_uniforms(int first_index) {
2404 Vector<RD::Uniform> uniforms;
2405
2406 // Binding ids are aligned with samplers_inc.glsl.
2407 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 0, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)));
2408 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 1, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)));
2409 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 2, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)));
2410 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 3, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)));
2411 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 4, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)));
2412 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 5, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)));
2413 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 6, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED)));
2414 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 7, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED)));
2415 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 8, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED)));
2416 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 9, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED)));
2417 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 10, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED)));
2418 uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 11, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED)));
2419
2420 return uniforms;
2421}
2422
2423void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialStorage::MaterialDataRequestFunction p_function) {
2424 ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
2425 material_data_request_func[p_shader_type] = p_function;
2426}
2427
2428MaterialStorage::MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
2429 ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
2430 return material_data_request_func[p_shader_type];
2431}
2432