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 | |
45 | namespace RendererRD { |
46 | |
47 | class MaterialStorage : public RendererMaterialStorage { |
48 | public: |
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 | |
108 | private: |
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 | |
236 | public: |
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 | |