1/**************************************************************************/
2/* material_storage.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef MATERIAL_STORAGE_RD_H
32#define MATERIAL_STORAGE_RD_H
33
34#include "texture_storage.h"
35
36#include "core/math/projection.h"
37#include "core/templates/local_vector.h"
38#include "core/templates/rid_owner.h"
39#include "core/templates/self_list.h"
40#include "servers/rendering/shader_compiler.h"
41#include "servers/rendering/shader_language.h"
42#include "servers/rendering/storage/material_storage.h"
43#include "servers/rendering/storage/utilities.h"
44
45namespace RendererRD {
46
47class MaterialStorage : public RendererMaterialStorage {
48public:
49 enum ShaderType {
50 SHADER_TYPE_2D,
51 SHADER_TYPE_3D,
52 SHADER_TYPE_PARTICLES,
53 SHADER_TYPE_SKY,
54 SHADER_TYPE_FOG,
55 SHADER_TYPE_MAX
56 };
57
58 struct ShaderData {
59 String path;
60 HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
61 HashMap<StringName, HashMap<int, RID>> default_texture_params;
62
63 virtual void set_path_hint(const String &p_hint);
64 virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
65 virtual Variant get_default_parameter(const StringName &p_parameter) const;
66 virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
67 virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
68 virtual bool is_parameter_texture(const StringName &p_param) const;
69
70 virtual void set_code(const String &p_Code) = 0;
71 virtual bool is_animated() const = 0;
72 virtual bool casts_shadows() const = 0;
73 virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
74
75 virtual ~ShaderData() {}
76 };
77
78 struct MaterialData {
79 Vector<RendererRD::TextureStorage::RenderTarget *> render_target_cache;
80 void 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);
81 void 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);
82 void set_as_used();
83
84 virtual void set_render_priority(int p_priority) = 0;
85 virtual void set_next_pass(RID p_pass) = 0;
86 virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
87 virtual ~MaterialData();
88
89 //to be used internally by update_parameters, in the most common configuration of material parameters
90 bool 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 &r_uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
91 void free_parameters_uniform_set(RID p_uniform_set);
92
93 private:
94 friend class MaterialStorage;
95
96 RID self;
97 List<RID>::Element *global_buffer_E = nullptr;
98 List<RID>::Element *global_texture_E = nullptr;
99 uint64_t global_textures_pass = 0;
100 HashMap<StringName, uint64_t> used_global_textures;
101
102 //internally by update_parameters_uniform_set
103 Vector<uint8_t> ubo_data;
104 RID uniform_buffer;
105 Vector<RID> texture_cache;
106 };
107
108private:
109 static MaterialStorage *singleton;
110
111 /* Samplers */
112
113 RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
114 RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
115
116 /* Buffers */
117
118 RID quad_index_buffer;
119 RID quad_index_array;
120
121 /* GLOBAL SHADER UNIFORM API */
122
123 struct GlobalShaderUniforms {
124 enum {
125 BUFFER_DIRTY_REGION_SIZE = 1024
126 };
127 struct Variable {
128 HashSet<RID> texture_materials; // materials using this
129
130 RS::GlobalShaderParameterType type;
131 Variant value;
132 Variant override;
133 int32_t buffer_index; //for vectors
134 int32_t buffer_elements; //for vectors
135 };
136
137 HashMap<StringName, Variable> variables;
138
139 struct Value {
140 float x;
141 float y;
142 float z;
143 float w;
144 };
145
146 struct ValueInt {
147 int32_t x;
148 int32_t y;
149 int32_t z;
150 int32_t w;
151 };
152
153 struct ValueUInt {
154 uint32_t x;
155 uint32_t y;
156 uint32_t z;
157 uint32_t w;
158 };
159
160 struct ValueUsage {
161 uint32_t elements = 0;
162 };
163
164 List<RID> materials_using_buffer;
165 List<RID> materials_using_texture;
166
167 RID buffer;
168 Value *buffer_values = nullptr;
169 ValueUsage *buffer_usage = nullptr;
170 bool *buffer_dirty_regions = nullptr;
171 uint32_t buffer_dirty_region_count = 0;
172
173 uint32_t buffer_size;
174
175 bool must_update_texture_materials = false;
176 bool must_update_buffer_materials = false;
177
178 HashMap<RID, int32_t> instance_buffer_pos;
179 } global_shader_uniforms;
180
181 int32_t _global_shader_uniform_allocate(uint32_t p_elements);
182 void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value);
183 void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
184
185 /* SHADER API */
186
187 struct Material;
188
189 struct Shader {
190 ShaderData *data = nullptr;
191 String code;
192 String path_hint;
193 ShaderType type;
194 HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
195 HashSet<Material *> owners;
196 };
197
198 typedef ShaderData *(*ShaderDataRequestFunction)();
199 ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
200
201 mutable RID_Owner<Shader, true> shader_owner;
202 Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }
203
204 /* MATERIAL API */
205
206 typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
207
208 struct Material {
209 RID self;
210 MaterialData *data = nullptr;
211 Shader *shader = nullptr;
212 //shortcut to shader data and type
213 ShaderType shader_type = SHADER_TYPE_MAX;
214 uint32_t shader_id = 0;
215 bool uniform_dirty = false;
216 bool texture_dirty = false;
217 HashMap<StringName, Variant> params;
218 int32_t priority = 0;
219 RID next_pass;
220 SelfList<Material> update_element;
221
222 Dependency dependency;
223
224 Material() :
225 update_element(this) {}
226 };
227
228 MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
229 mutable RID_Owner<Material, true> material_owner;
230 Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
231
232 SelfList<Material>::List material_update_list;
233
234 static void _material_uniform_set_erased(void *p_material);
235
236public:
237 static MaterialStorage *get_singleton();
238
239 MaterialStorage();
240 virtual ~MaterialStorage();
241
242 bool free(RID p_rid);
243
244 /* Helpers */
245
246 static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
247 p_array[0] = p_mtx.basis.rows[0][0];
248 p_array[1] = p_mtx.basis.rows[1][0];
249 p_array[2] = p_mtx.basis.rows[2][0];
250 p_array[3] = 0;
251 p_array[4] = p_mtx.basis.rows[0][1];
252 p_array[5] = p_mtx.basis.rows[1][1];
253 p_array[6] = p_mtx.basis.rows[2][1];
254 p_array[7] = 0;
255 p_array[8] = p_mtx.basis.rows[0][2];
256 p_array[9] = p_mtx.basis.rows[1][2];
257 p_array[10] = p_mtx.basis.rows[2][2];
258 p_array[11] = 0;
259 p_array[12] = p_mtx.origin.x;
260 p_array[13] = p_mtx.origin.y;
261 p_array[14] = p_mtx.origin.z;
262 p_array[15] = 1;
263 }
264
265 static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
266 p_array[0] = p_mtx.rows[0][0];
267 p_array[1] = p_mtx.rows[1][0];
268 p_array[2] = p_mtx.rows[2][0];
269 p_array[3] = 0;
270 p_array[4] = p_mtx.rows[0][1];
271 p_array[5] = p_mtx.rows[1][1];
272 p_array[6] = p_mtx.rows[2][1];
273 p_array[7] = 0;
274 p_array[8] = p_mtx.rows[0][2];
275 p_array[9] = p_mtx.rows[1][2];
276 p_array[10] = p_mtx.rows[2][2];
277 p_array[11] = 0;
278 }
279
280 static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
281 p_array[0] = p_mtx.rows[0][0];
282 p_array[1] = p_mtx.rows[1][0];
283 p_array[2] = p_mtx.rows[2][0];
284 p_array[3] = 0;
285 p_array[4] = p_mtx.rows[0][1];
286 p_array[5] = p_mtx.rows[1][1];
287 p_array[6] = p_mtx.rows[2][1];
288 p_array[7] = 0;
289 p_array[8] = p_mtx.rows[0][2];
290 p_array[9] = p_mtx.rows[1][2];
291 p_array[10] = p_mtx.rows[2][2];
292 p_array[11] = 0;
293 }
294
295 static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
296 p_array[0] = p_mtx.basis.rows[0][0];
297 p_array[1] = p_mtx.basis.rows[0][1];
298 p_array[2] = p_mtx.basis.rows[0][2];
299 p_array[3] = p_mtx.origin.x;
300 p_array[4] = p_mtx.basis.rows[1][0];
301 p_array[5] = p_mtx.basis.rows[1][1];
302 p_array[6] = p_mtx.basis.rows[1][2];
303 p_array[7] = p_mtx.origin.y;
304 p_array[8] = p_mtx.basis.rows[2][0];
305 p_array[9] = p_mtx.basis.rows[2][1];
306 p_array[10] = p_mtx.basis.rows[2][2];
307 p_array[11] = p_mtx.origin.z;
308 }
309
310 static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
311 for (int i = 0; i < 4; i++) {
312 for (int j = 0; j < 4; j++) {
313 p_array[i * 4 + j] = p_mtx.columns[i][j];
314 }
315 }
316 }
317
318 static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
319 for (int i = 0; i < 128; i++) {
320 p_array[i] = p_kernel[i];
321 }
322 }
323
324 // http://andrewthall.org/papers/df64_qf128.pdf
325#ifdef REAL_T_IS_DOUBLE
326 static _FORCE_INLINE_ void split_double(double a, float *a_hi, float *a_lo) {
327 const double SPLITTER = (1 << 29) + 1;
328 double t = a * SPLITTER;
329 double t_hi = t - (t - a);
330 double t_lo = a - t_hi;
331 *a_hi = (float)t_hi;
332 *a_lo = (float)t_lo;
333 }
334#endif
335
336 /* Samplers */
337
338 _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
339 return default_rd_samplers[p_filter][p_repeat];
340 }
341 _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
342 return custom_rd_samplers[p_filter][p_repeat];
343 }
344
345 void sampler_rd_configure_custom(float mipmap_bias);
346
347 Vector<RD::Uniform> get_default_sampler_uniforms(int first_index);
348
349 // void sampler_rd_set_default(float p_mipmap_bias);
350
351 /* Buffers */
352
353 RID get_quad_index_array() { return quad_index_array; }
354
355 /* GLOBAL SHADER UNIFORM API */
356
357 void _update_global_shader_uniforms();
358
359 virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override;
360 virtual void global_shader_parameter_remove(const StringName &p_name) override;
361 virtual Vector<StringName> global_shader_parameter_get_list() const override;
362
363 virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override;
364 virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override;
365 virtual Variant global_shader_parameter_get(const StringName &p_name) const override;
366 virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override;
367 RS::GlobalShaderParameterType global_shader_parameter_get_type_internal(const StringName &p_name) const;
368
369 virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override;
370 virtual void global_shader_parameters_clear() override;
371
372 virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override;
373 virtual void global_shader_parameters_instance_free(RID p_instance) override;
374 virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) override;
375
376 RID global_shader_uniforms_get_storage_buffer() const;
377
378 /* SHADER API */
379
380 bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
381
382 virtual RID shader_allocate() override;
383 virtual void shader_initialize(RID p_shader) override;
384 virtual void shader_free(RID p_rid) override;
385
386 virtual void shader_set_code(RID p_shader, const String &p_code) override;
387 virtual void shader_set_path_hint(RID p_shader, const String &p_path) override;
388 virtual String shader_get_code(RID p_shader) const override;
389 virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
390
391 virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
392 virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override;
393 virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_param) const override;
394 void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
395
396 virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;
397
398 /* MATERIAL API */
399
400 bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
401
402 void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
403 void _update_queued_materials();
404
405 virtual RID material_allocate() override;
406 virtual void material_initialize(RID p_material) override;
407 virtual void material_free(RID p_rid) override;
408
409 virtual void material_set_shader(RID p_material, RID p_shader) override;
410 ShaderData *material_get_shader_data(RID p_material);
411
412 virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
413 virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
414
415 virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
416 virtual void material_set_render_priority(RID p_material, int priority) override;
417
418 virtual bool material_is_animated(RID p_material) override;
419 virtual bool material_casts_shadows(RID p_material) override;
420
421 virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
422
423 virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;
424
425 void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
426 MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
427
428 _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
429 Material *material = material_owner.get_or_null(p_material);
430 return material->shader_id;
431 }
432
433 _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
434 Material *material = material_owner.get_or_null(p_material);
435 if (!material || material->shader_type != p_shader_type) {
436 return nullptr;
437 } else {
438 return material->data;
439 }
440 }
441};
442
443} // namespace RendererRD
444
445#endif // MATERIAL_STORAGE_RD_H
446