summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp235
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h19
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp188
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h53
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp30
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp53
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h14
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp81
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h28
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h5
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp67
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h16
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp89
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h14
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp2368
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h254
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp2392
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h315
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.cpp2
22 files changed, 3246 insertions, 2991 deletions
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 0ae51ed876..2b3ed4ffad 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -59,14 +59,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
Vector<RID> fb;
- fb.push_back(color);
- fb.push_back(specular);
- fb.push_back(depth);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -79,14 +71,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
{
Vector<RID> fb;
- fb.push_back(color_msaa);
- fb.push_back(specular_msaa);
- fb.push_back(depth_msaa);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular_msaa);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -165,11 +149,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
color = RID();
depth = RID();
- color_specular_fb = RID();
- specular_only_fb = RID();
- color_fb = RID();
depth_fb = RID();
+ color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
+
if (normal_roughness_buffer.is_valid()) {
RD::get_singleton()->free(normal_roughness_buffer);
if (normal_roughness_buffer_msaa.is_valid()) {
@@ -203,7 +186,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(p_color_buffer);
fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
@@ -246,7 +229,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
@@ -257,6 +240,31 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
}
}
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) {
+ if (color_framebuffers.has(p_color_pass_flags)) {
+ return color_framebuffers[p_color_pass_flags];
+ }
+
+ bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED;
+
+ Vector<RID> fb;
+ fb.push_back(use_msaa ? color_msaa : color);
+
+ if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ ensure_specular();
+ fb.push_back(use_msaa ? specular_msaa : specular);
+ } else {
+ fb.push_back(RID());
+ }
+
+ fb.push_back(use_msaa ? depth_msaa : depth);
+
+ int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
+ RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
+ color_framebuffers[p_color_pass_flags] = framebuffer;
+ return framebuffer;
+}
+
void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) {
if (rb->normal_roughness_buffer.is_valid()) {
return;
@@ -306,7 +314,7 @@ bool RenderForwardClustered::free(RID p_rid) {
/// RENDERING ///
-template <RenderForwardClustered::PassMode p_pass_mode>
+template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags>
void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -340,7 +348,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
- if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
}
@@ -403,10 +411,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
-
+ uint32_t pipeline_color_pass_flags = 0;
uint32_t pipeline_specialization = 0;
- if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) {
+ if (p_pass_mode == PASS_MODE_COLOR) {
if (element_info.uses_softshadow) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
}
@@ -422,28 +430,26 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
switch (p_pass_mode) {
case PASS_MODE_COLOR: {
if (element_info.uses_lightmap) {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS;
- } else {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS;
- }
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- if (element_info.uses_lightmap) {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS;
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_LIGHTMAP;
} else {
if (element_info.uses_forward_gi) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
}
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS;
}
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for specular pass");
- if (element_info.uses_lightmap) {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
- } else {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MULTIVIEW;
}
+
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS;
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
@@ -473,7 +479,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
PipelineCacheRD *pipeline = nullptr;
- pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ if constexpr (p_pass_mode == PASS_MODE_COLOR) {
+ pipeline = &shader->color_pipelines[cull_variant][primitive][pipeline_color_pass_flags];
+ } else {
+ pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ }
RD::VertexFormatID vertex_format = -1;
RID vertex_array_rd;
@@ -544,14 +554,23 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
//use template for faster performance (pass mode comparisons are inlined)
switch (p_params->pass_mode) {
+#define VALID_FLAG_COMBINATION(f) \
+ case f: { \
+ _render_list_template<PASS_MODE_COLOR, f>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); \
+ } break;
+
case PASS_MODE_COLOR: {
- _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ switch (p_params->color_pass_flags) {
+ VALID_FLAG_COMBINATION(0);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW);
+ default: {
+ ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags));
+ }
+ }
+
} break;
case PASS_MODE_SHADOW: {
_render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
@@ -1238,12 +1257,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
- RID opaque_framebuffer;
- RID opaque_specular_framebuffer;
+ RID color_framebuffer;
+ RID color_only_framebuffer;
RID depth_framebuffer;
- RID alpha_framebuffer;
PassMode depth_pass_mode = PASS_MODE_DEPTH;
+ uint32_t color_pass_flags = 0;
Vector<Color> depth_pass_clear;
bool using_separate_specular = false;
bool using_ssr = false;
@@ -1256,15 +1275,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- opaque_framebuffer = render_buffer->color_fb;
-
if (p_render_data->voxel_gi_instances->size() > 0) {
using_voxelgi = true;
}
- if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ if (p_render_data->view_count > 1) {
+ depth_pass_mode = PASS_MODE_DEPTH;
+ } else if (!p_render_data->environment.is_valid() && using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
if (environment_is_sdfgi_enabled(p_render_data->environment)) {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
@@ -1272,14 +1290,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} else {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
-
if (environment_is_ssr_enabled(p_render_data->environment)) {
- render_buffer->ensure_specular();
using_separate_specular = true;
using_ssr = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1304,15 +1319,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
};
}
- alpha_framebuffer = opaque_framebuffer;
+ if (p_render_data->view_count > 1) {
+ color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
+ color_only_framebuffer = render_buffer->color_only_fb;
} else if (p_render_data->reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_only_framebuffer = color_framebuffer;
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- alpha_framebuffer = opaque_framebuffer;
if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
@@ -1342,11 +1362,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
- if (using_sss) {
- using_separate_specular = true;
- render_buffer->ensure_specular();
+ if (using_sss && !using_separate_specular) {
using_separate_specular = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
}
RID radiance_texture;
bool draw_sky = false;
@@ -1368,7 +1387,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
} break;
case RS::ENV_BG_COLOR: {
@@ -1378,7 +1397,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
@@ -1449,7 +1468,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1495,20 +1514,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
- //regular forward for now
Vector<Color> c;
- if (using_separate_specular) {
+ {
Color cc = clear_color.to_linear();
- cc.a = 0; //subsurf scatter must be 0
+ if (using_separate_specular) {
+ cc.a = 0; //subsurf scatter must be 0
+ }
c.push_back(cc);
- c.push_back(Color(0, 0, 0, 0));
- } else {
- c.push_back(clear_color.to_linear());
+
+ if (render_buffer) {
+ c.push_back(Color(0, 0, 0, 0));
+ }
}
- RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
- _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
@@ -1526,10 +1546,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
- gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
+ gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
}
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
@@ -1543,9 +1563,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
- _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm);
+ _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm);
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
@@ -1559,9 +1579,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix correction;
correction.set_depth_correction(true);
CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
} else {
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1588,12 +1608,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (using_ssr) {
RENDER_TIMESTAMP("Screen-Space Reflections");
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
- _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
}
}
@@ -1616,7 +1636,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -1738,7 +1760,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1781,7 +1803,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
{
//regular forward for now
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set);
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
RD::get_singleton()->draw_command_end_label();
@@ -1818,7 +1840,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1864,7 +1886,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1984,7 +2006,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false);
_render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
@@ -2165,7 +2187,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2182,6 +2204,8 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
RenderBufferDataForwardClustered *rb = nullptr;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
@@ -2429,6 +2453,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
}
RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
Vector<RD::Uniform> uniforms;
{
@@ -2633,7 +2658,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material_shadow = (SceneShaderForwardClustered::MaterialData *)RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
@@ -2688,23 +2713,25 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
SceneShaderForwardClustered::MaterialData *material = p_material;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid) {
break;
}
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
}
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
}
}
void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2712,7 +2739,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
SceneShaderForwardClustered::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2720,10 +2747,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (material) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
m_src = scene_shader.default_material;
}
@@ -2734,10 +2761,10 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardClustered::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index b770cc8f0e..11016968ed 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -103,10 +103,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID depth_fb;
RID depth_normal_roughness_fb;
RID depth_normal_roughness_voxelgi_fb;
- RID color_fb;
- RID color_specular_fb;
+ RID color_only_fb;
RID specular_only_fb;
int width, height;
+ Map<uint32_t, RID> color_framebuffers;
uint32_t view_count;
RID render_sdfgi_uniform_set;
@@ -114,6 +114,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void ensure_voxelgi();
void clear();
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ RID get_color_pass_fb(uint32_t p_color_pass_flags);
~RenderBufferDataForwardClustered();
};
@@ -135,8 +136,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
enum PassMode {
PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
@@ -146,6 +145,12 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PASS_MODE_SDF,
};
+ enum ColorPassFlags {
+ COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ COLOR_PASS_FLAG_MULTIVIEW = 1 << 2
+ };
+
struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
@@ -155,6 +160,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
int element_count = 0;
bool reverse_cull = false;
PassMode pass_mode = PASS_MODE_COLOR;
+ uint32_t color_pass_flags = 0;
bool no_gi = false;
uint32_t view_count = 1;
RID render_pass_uniform_set;
@@ -168,12 +174,13 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t barrier = RD::BARRIER_MASK_ALL;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
pass_mode = p_pass_mode;
+ color_pass_flags = p_color_pass_flags;
no_gi = p_no_gi;
view_count = p_view_count;
render_pass_uniform_set = p_render_pass_uniform_set;
@@ -374,7 +381,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t lod_index : 8;
};
- template <PassMode p_pass_mode>
+ template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 33ad2c2c31..c42ac98a84 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "render_forward_clustered.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
using namespace RendererSceneRenderImplementation;
@@ -233,10 +234,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
}
- RD::PipelineColorBlendState blend_state_blend;
- blend_state_blend.attachments.push_back(blend_attachment);
- RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
- RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
+ // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular
+ RD::PipelineColorBlendState blend_state_color_blend;
+ blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment() };
+ RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(2);
RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1);
RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2);
@@ -279,18 +280,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
-
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_COLOR_PASS,
};
shader_version = shader_version_table[k];
@@ -306,38 +297,62 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
RD::PipelineMultisampleState multisample_state;
- if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS || k == PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW) {
- if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
- multisample_state.enable_alpha_to_coverage = true;
- } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
- multisample_state.enable_alpha_to_coverage = true;
- multisample_state.enable_alpha_to_one = true;
- }
-
- blend_state = blend_state_blend;
-
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ if (k == PIPELINE_VERSION_COLOR_PASS) {
+ for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
+ if (!shader_singleton->valid_color_pass_pipelines.has(l)) {
+ continue;
+ }
+
+ int shader_flags = 0;
+ if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
+ if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ multisample_state.enable_alpha_to_one = true;
+ }
+
+ blend_state = blend_state_color_blend;
+
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ }
+ } else {
+ blend_state = blend_state_color_opaque;
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ }
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP;
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ int variant = shader_version + shader_flags;
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, variant);
+ color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
- } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS || k == PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW) {
- blend_state = blend_state_opaque;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW || k == PIPELINE_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
} else {
- //specular write
- blend_state = blend_state_opaque_specular;
- }
+ if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) {
+ //none, leave empty
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal_roughness;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ blend_state = blend_state_depth_normal_roughness_giprobe;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
+ blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
+ blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
+ }
- RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ }
}
}
}
@@ -384,13 +399,13 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
}
}
-void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -445,7 +460,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -469,7 +484,7 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -484,17 +499,20 @@ SceneShaderForwardClustered::SceneShaderForwardClustered() {
}
SceneShaderForwardClustered::~SceneShaderForwardClustered() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(overdraw_material_shader);
- storage->free(default_shader);
+ material_storage->shader_free(overdraw_material_shader);
+ material_storage->shader_free(default_shader);
- storage->free(overdraw_material);
- storage->free(default_material);
+ material_storage->material_free(overdraw_material);
+ material_storage->material_free(default_material);
}
void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{
@@ -505,27 +523,40 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
- shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
- shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
-
- // multiview versions of our shaders
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
+
+ Vector<String> color_pass_flags = {
+ "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
+ "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP
+ "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW
+ };
+
+ for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
+ String version = "";
+ for (int j = 0; (1 << j) < SHADER_COLOR_PASS_FLAG_COUNT; j += 1) {
+ if ((1 << j) & i) {
+ version += color_pass_flags[j];
+ }
+ }
+ shader_versions.push_back(version);
+ }
shader.initialize(shader_versions, p_defines);
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
+ // TODO Add a way to enable/disable color pass flags
}
}
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+ valid_color_pass_pipelines.insert(0);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
@@ -616,7 +647,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT"] = "light";
actions.renames["ATTENUATION"] = "attenuation";
- actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation";
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
actions.renames["SPECULAR_LIGHT"] = "specular_light";
@@ -711,9 +741,9 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
{
//default material and shader
- default_shader = storage->shader_allocate();
- storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, R"(
+ default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_shader);
+ material_storage->shader_set_code(default_shader, R"(
// Default 3D material shader (clustered).
shader_type spatial;
@@ -728,11 +758,11 @@ void fragment() {
METALLIC = 0.2;
}
)");
- default_material = storage->material_allocate();
- storage->material_initialize(default_material);
- storage->material_set_shader(default_material, default_shader);
+ default_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_material);
+ material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = (MaterialData *)material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D);
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
@@ -741,10 +771,10 @@ void fragment() {
}
{
- overdraw_material_shader = storage->shader_allocate();
- storage->shader_initialize(overdraw_material_shader);
+ overdraw_material_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
- storage->shader_set_code(overdraw_material_shader, R"(
+ material_storage->shader_set_code(overdraw_material_shader, R"(
// 3D editor Overdraw debug draw mode shader (clustered).
shader_type spatial;
@@ -756,11 +786,11 @@ void fragment() {
ALPHA = 0.1;
}
)");
- overdraw_material = storage->material_allocate();
- storage->material_initialize(overdraw_material);
- storage->material_set_shader(overdraw_material, overdraw_material_shader);
+ overdraw_material = material_storage->material_allocate();
+ material_storage->material_initialize(overdraw_material);
+ material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = (MaterialData *)material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D);
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 4398517259..c3039e2f7f 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -51,18 +51,18 @@ public:
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
-
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
-
+ SHADER_VERSION_COLOR_PASS,
SHADER_VERSION_MAX
};
+ enum ShaderColorPassFlags {
+ SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0,
+ SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1,
+ SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2,
+ SHADER_COLOR_PASS_FLAG_COUNT = 1 << 3
+ };
+
enum PipelineVersion {
PIPELINE_VERSION_DEPTH_PASS,
PIPELINE_VERSION_DEPTH_PASS_DP,
@@ -70,22 +70,19 @@ public:
PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
- PIPELINE_VERSION_OPAQUE_PASS,
- PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_TRANSPARENT_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS,
-
PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW,
- PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW,
- PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW,
-
+ PIPELINE_VERSION_COLOR_PASS,
PIPELINE_VERSION_MAX
};
+ enum PipelineColorPassFlags {
+ PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
+ PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
+ PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 4,
+ };
+
enum ShaderSpecializations {
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
@@ -93,7 +90,7 @@ public:
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
};
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct ShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -137,6 +134,7 @@ public:
RID version;
uint32_t vertex_input_mask;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
+ PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
String path;
@@ -180,7 +178,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -195,12 +193,12 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
+ struct MaterialData : public RendererRD::MaterialData {
ShaderData *shader_data;
RID uniform_set;
uint64_t last_pass = 0;
@@ -213,8 +211,8 @@ public:
virtual ~MaterialData();
};
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -240,6 +238,7 @@ public:
ShaderData *overdraw_material_shader_ptr = nullptr;
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
+ Set<uint32_t> valid_color_pass_pipelines;
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index a09a604e49..1153a33a27 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -290,6 +290,8 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() {
}
RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
//there should always be enough uniform buffers for render passes, otherwise bugs
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
@@ -593,7 +595,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
*/
} break;
@@ -605,7 +607,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
}
*/
} break;
@@ -1300,7 +1302,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2326,7 +2328,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material_shadow = (SceneShaderForwardMobile::MaterialData *)RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
@@ -2379,23 +2381,25 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
SceneShaderForwardMobile::MaterialData *material = p_material;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), material_storage->material_get_shader_id(p_mat_src), p_mesh);
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid) {
break;
}
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
}
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), material_storage->material_get_shader_id(next_pass), p_mesh);
}
}
void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RID m_src;
m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
@@ -2403,7 +2407,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
SceneShaderForwardMobile::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2411,10 +2415,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (material) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(scene_shader.default_material, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
m_src = scene_shader.default_material;
}
@@ -2425,10 +2429,10 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ material = (SceneShaderForwardMobile::MaterialData *)material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D);
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
_geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index d7ed4a36f0..2f56dc0af6 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "render_forward_mobile.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
using namespace RendererSceneRenderImplementation;
@@ -366,13 +367,13 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
}
}
-void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -427,7 +428,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
+RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -451,7 +452,7 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -469,6 +470,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
storage = p_storage;
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
/* SCENE SHADER */
@@ -494,8 +496,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
@@ -586,7 +588,6 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT"] = "light";
actions.renames["ATTENUATION"] = "attenuation";
- actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation";
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
actions.renames["SPECULAR_LIGHT"] = "specular_light";
@@ -678,9 +679,9 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
{
//default material and shader
- default_shader = storage->shader_allocate();
- storage->shader_initialize(default_shader);
- storage->shader_set_code(default_shader, R"(
+ default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_shader);
+ material_storage->shader_set_code(default_shader, R"(
// Default 3D material shader (mobile).
shader_type spatial;
@@ -695,11 +696,11 @@ void fragment() {
METALLIC = 0.2;
}
)");
- default_material = storage->material_allocate();
- storage->material_initialize(default_material);
- storage->material_set_shader(default_material, default_shader);
+ default_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_material);
+ material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = (MaterialData *)material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D);
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_material_shader_ptr = md->shader_data;
@@ -707,10 +708,10 @@ void fragment() {
}
{
- overdraw_material_shader = storage->shader_allocate();
- storage->shader_initialize(overdraw_material_shader);
+ overdraw_material_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
- storage->shader_set_code(overdraw_material_shader, R"(
+ material_storage->shader_set_code(overdraw_material_shader, R"(
// 3D editor Overdraw debug draw mode shader (mobile).
shader_type spatial;
@@ -722,11 +723,11 @@ void fragment() {
ALPHA = 0.1;
}
)");
- overdraw_material = storage->material_allocate();
- storage->material_initialize(overdraw_material);
- storage->material_set_shader(overdraw_material, overdraw_material_shader);
+ overdraw_material = material_storage->material_allocate();
+ material_storage->material_initialize(overdraw_material);
+ material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = (MaterialData *)storage->material_get_data(overdraw_material, RendererStorageRD::SHADER_TYPE_3D);
+ MaterialData *md = (MaterialData *)material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D);
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
@@ -766,12 +767,14 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector
}
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
- storage->free(overdraw_material_shader);
- storage->free(default_shader);
+ material_storage->shader_free(overdraw_material_shader);
+ material_storage->shader_free(default_shader);
- storage->free(overdraw_material);
- storage->free(default_material);
+ material_storage->material_free(overdraw_material);
+ material_storage->material_free(default_material);
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 92db15e3b0..0f5017dba1 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -57,7 +57,7 @@ public:
SHADER_VERSION_MAX
};
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct ShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -143,7 +143,7 @@ public:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -157,12 +157,12 @@ public:
virtual ~ShaderData();
};
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
+ struct MaterialData : public RendererRD::MaterialData {
ShaderData *shader_data;
RID uniform_set;
uint64_t last_pass = 0;
@@ -177,8 +177,8 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index e56e263540..8c8532d367 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -35,7 +35,10 @@
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -359,7 +362,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
bool use_normal;
bool use_specular;
- bool success = canvas_texture_storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+ bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
//something odd happened
if (!success) {
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -978,7 +981,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
} else {
screen = storage->render_target_get_rd_backbuffer(p_to_render_target);
if (screen.is_null()) { //unallocated backbuffer
- screen = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
}
u.append_id(screen);
@@ -1021,7 +1024,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 9;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1036,6 +1039,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
}
void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1100,9 +1104,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
if (material != prev_material) {
- MaterialData *material_data = nullptr;
+ CanvasMaterialData *material_data = nullptr;
if (material.is_valid()) {
- material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+ material_data = (CanvasMaterialData *)material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D);
}
if (material_data) {
@@ -1129,6 +1133,8 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
}
void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
r_sdf_used = false;
int item_count = 0;
@@ -1364,7 +1370,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (material.is_valid()) {
- MaterialData *md = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D);
+ CanvasMaterialData *md = (CanvasMaterialData *)material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D);
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_found) {
@@ -1938,7 +1944,7 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
-void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
+void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -2120,7 +2126,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -2137,7 +2143,7 @@ void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringN
}
}
-void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -2158,13 +2164,13 @@ void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_pa
}
}
-void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -2173,7 +2179,7 @@ void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererSt
}
}
-bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -2181,15 +2187,15 @@ bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_pa
return uniforms[p_param].texture_order >= 0;
}
-bool RendererCanvasRenderRD::ShaderData::is_animated() const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_animated() const {
return false;
}
-bool RendererCanvasRenderRD::ShaderData::casts_shadows() const {
+bool RendererCanvasRenderRD::CanvasShaderData::casts_shadows() const {
return false;
}
-Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant RendererCanvasRenderRD::CanvasShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -2198,18 +2204,18 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
return Variant();
}
-RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const {
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_source_code() const {
RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
}
-RendererCanvasRenderRD::ShaderData::ShaderData() {
+RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() {
valid = false;
uses_screen_texture = false;
uses_sdf = false;
}
-RendererCanvasRenderRD::ShaderData::~ShaderData() {
+RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
ERR_FAIL_COND(!canvas_singleton);
//pipeline variants will clear themselves if shader is gone
@@ -2218,23 +2224,23 @@ RendererCanvasRenderRD::ShaderData::~ShaderData() {
}
}
-RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
- ShaderData *shader_data = memnew(ShaderData);
+RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
+ CanvasShaderData *shader_data = memnew(CanvasShaderData);
return shader_data;
}
-bool RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
}
-RendererCanvasRenderRD::MaterialData::~MaterialData() {
+RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
- MaterialData *material_data = memnew(MaterialData);
+RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
+ CanvasMaterialData *material_data = memnew(CanvasMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
@@ -2248,8 +2254,8 @@ void RendererCanvasRenderRD::update() {
}
RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
- canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
- texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{ //create default samplers
@@ -2586,16 +2592,16 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
//create functions for shader and material
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs);
state.time = 0;
{
- default_canvas_group_shader = storage->shader_allocate();
- storage->shader_initialize(default_canvas_group_shader);
+ default_canvas_group_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_canvas_group_shader);
- storage->shader_set_code(default_canvas_group_shader, R"(
+ material_storage->shader_set_code(default_canvas_group_shader, R"(
// Default CanvasGroup shader.
shader_type canvas_item;
@@ -2610,10 +2616,10 @@ void fragment() {
COLOR *= c;
}
)");
- default_canvas_group_material = storage->material_allocate();
- storage->material_initialize(default_canvas_group_material);
+ default_canvas_group_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_canvas_group_material);
- storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+ material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
static_assert(sizeof(PushConstant) == 128);
@@ -2661,10 +2667,11 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
}
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//canvas state
- storage->free(default_canvas_group_material);
- storage->free(default_canvas_group_shader);
+ material_storage->material_free(default_canvas_group_material);
+ material_storage->shader_free(default_canvas_group_shader);
{
if (state.canvas_state_buffer.is_valid()) {
@@ -2701,6 +2708,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
}
RD::get_singleton()->free(state.shadow_texture);
- canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+ RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index c0138c4fe0..b33ee3fbfe 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -37,14 +37,10 @@
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
- RendererRD::CanvasTextureStorage *canvas_texture_storage;
- RendererRD::TextureStorage *texture_storage;
RendererStorageRD *storage;
enum {
@@ -155,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
ShaderCompiler compiler;
} shader;
- struct ShaderData : public RendererStorageRD::ShaderData {
+ struct CanvasShaderData : public RendererRD::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -186,7 +182,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
@@ -194,28 +190,28 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- ShaderData();
- virtual ~ShaderData();
+ CanvasShaderData();
+ virtual ~CanvasShaderData();
};
- RendererStorageRD::ShaderData *_create_shader_func();
- static RendererStorageRD::ShaderData *_create_shader_funcs() {
+ RendererRD::ShaderData *_create_shader_func();
+ static RendererRD::ShaderData *_create_shader_funcs() {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererStorageRD::MaterialData {
- ShaderData *shader_data;
+ struct CanvasMaterialData : public RendererRD::MaterialData {
+ CanvasShaderData *shader_data;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~MaterialData();
+ virtual ~CanvasMaterialData();
};
- RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
- return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
+ RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader);
+ static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader));
}
/**************************/
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 6d6cf0ce73..cfec5dac5d 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -156,6 +156,7 @@ void RendererCompositorRD::finalize() {
memdelete(canvas);
memdelete(storage);
memdelete(decal_atlas_storage);
+ memdelete(material_storage);
memdelete(texture_storage);
memdelete(canvas_texture_storage);
@@ -289,6 +290,7 @@ RendererCompositorRD::RendererCompositorRD() {
canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
texture_storage = memnew(RendererRD::TextureStorage);
decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
+ material_storage = memnew(RendererRD::MaterialStorage);
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index a860093bb1..f2d7679e23 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -41,6 +41,7 @@
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
@@ -49,6 +50,7 @@ protected:
UniformSetCacheRD *uniform_set_cache;
RendererCanvasRenderRD *canvas;
RendererRD::CanvasTextureStorage *canvas_texture_storage;
+ RendererRD::MaterialStorage *material_storage;
RendererRD::TextureStorage *texture_storage;
RendererRD::DecalAtlasStorage *decal_atlas_storage;
RendererStorageRD *storage;
@@ -95,8 +97,9 @@ protected:
public:
RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }
- RendererTextureStorage *get_texture_storage() { return texture_storage; }
RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; }
+ RendererMaterialStorage *get_material_storage() { return material_storage; };
+ RendererTextureStorage *get_texture_storage() { return texture_storage; };
RendererStorage *get_storage() { return storage; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 4a6dbc137c..b5a40f6c86 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -34,6 +34,8 @@
#include "core/os/os.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
void get_vogel_disk(float *r_kernel, int p_sample_count) {
@@ -2359,6 +2361,7 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
}
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
@@ -2571,6 +2574,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -2647,6 +2651,7 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
}
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
EffectsRD *effects = storage->get_effects();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
@@ -3920,13 +3925,13 @@ void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_
}
}
-void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E->get());
p.info.name = E->key(); //supply name
p.index = E->get().instance_index;
@@ -3994,23 +3999,23 @@ RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
FogShaderData *shader_data = memnew(FogShaderData);
return shader_data;
}
-RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
+RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
};
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
FogMaterialData *material_data = memnew(FogMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
};
@@ -4068,6 +4073,9 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto
}
void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -4268,7 +4276,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
FogMaterialData *material = nullptr;
if (fog_material.is_valid()) {
- material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ material = (FogMaterialData *)material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -4276,7 +4284,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
if (!material) {
fog_material = volumetric_fog.default_material;
- material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ material = (FogMaterialData *)material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG);
}
ERR_FAIL_COND(!material);
@@ -5605,12 +5613,13 @@ uint32_t RendererSceneRenderRD::get_max_elements() const {
}
RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
- texture_storage = RendererRD::TextureStorage::get_singleton();
storage = p_storage;
singleton = this;
}
void RendererSceneRenderRD::init() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
max_cluster_elements = get_max_elements();
directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
@@ -5667,8 +5676,8 @@ void RendererSceneRenderRD::init() {
volumetric_fog_modes.push_back("");
volumetric_fog.shader.initialize(volumetric_fog_modes);
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
}
@@ -5707,9 +5716,9 @@ void RendererSceneRenderRD::init() {
{
// default material and shader for fog shader
- volumetric_fog.default_shader = storage->shader_allocate();
- storage->shader_initialize(volumetric_fog.default_shader);
- storage->shader_set_code(volumetric_fog.default_shader, R"(
+ volumetric_fog.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(volumetric_fog.default_shader);
+ material_storage->shader_set_code(volumetric_fog.default_shader, R"(
// Default fog shader.
shader_type fog;
@@ -5719,11 +5728,11 @@ void fog() {
ALBEDO = vec3(1.0);
}
)");
- volumetric_fog.default_material = storage->material_allocate();
- storage->material_initialize(volumetric_fog.default_material);
- storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+ volumetric_fog.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(volumetric_fog.default_material);
+ material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
- FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG);
+ FogMaterialData *md = (FogMaterialData *)material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG);
volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -5753,7 +5762,7 @@ void fog() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -5822,6 +5831,8 @@ void fog() {
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
RD::get_singleton()->free(E.value.cubemap);
}
@@ -5838,20 +5849,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
RD::get_singleton()->free(volumetric_fog.volume_ubo);
RD::get_singleton()->free(volumetric_fog.params_ubo);
- storage->free(volumetric_fog.default_shader);
- storage->free(volumetric_fog.default_material);
- }
-
- RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
- sky.sky_shader.shader.version_free(md->shader_data->version);
- RD::get_singleton()->free(sky.sky_scene_state.directional_light_buffer);
- RD::get_singleton()->free(sky.sky_scene_state.uniform_buffer);
- memdelete_arr(sky.sky_scene_state.directional_lights);
- memdelete_arr(sky.sky_scene_state.last_frame_directional_lights);
- storage->free(sky.sky_shader.default_shader);
- storage->free(sky.sky_shader.default_material);
- storage->free(sky.sky_scene_state.fog_shader);
- storage->free(sky.sky_scene_state.fog_material);
+ material_storage->shader_free(volumetric_fog.default_shader);
+ material_storage->material_free(volumetric_fog.default_material);
+ }
+
memdelete_arr(directional_penumbra_shadow_kernel);
memdelete_arr(directional_soft_shadow_kernel);
memdelete_arr(penumbra_shadow_kernel);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index e302db2631..77c0437e83 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -41,7 +41,6 @@
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -93,7 +92,6 @@ class RendererSceneRenderRD : public RendererSceneRender {
friend RendererSceneGIRD;
protected:
- RendererRD::TextureStorage *texture_storage;
RendererStorageRD *storage;
double time;
double time_step = 0;
@@ -909,7 +907,7 @@ private:
void _volumetric_fog_erase(RenderBuffers *rb);
void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
- struct FogShaderData : public RendererStorageRD::ShaderData {
+ struct FogShaderData : public RendererRD::ShaderData {
bool valid;
RID version;
@@ -929,7 +927,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
@@ -939,7 +937,7 @@ private:
virtual ~FogShaderData();
};
- struct FogMaterialData : public RendererStorageRD::MaterialData {
+ struct FogMaterialData : public RendererRD::MaterialData {
FogShaderData *shader_data;
RID uniform_set;
bool uniform_set_updated;
@@ -950,11 +948,11 @@ private:
virtual ~FogMaterialData();
};
- RendererStorageRD::ShaderData *_create_fog_shader_func();
- static RendererStorageRD::ShaderData *_create_fog_shader_funcs();
+ RendererRD::ShaderData *_create_fog_shader_func();
+ static RendererRD::ShaderData *_create_fog_shader_funcs();
- RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader);
+ RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
RID shadow_sampler;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 44da9e40f8..1c4ddcb5e1 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -33,6 +33,7 @@
#include "core/math/math_defs.h"
#include "renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
@@ -177,13 +178,13 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
}
}
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -767,24 +768,24 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
////////////////////////////////////////////////////////////////////////////////
// RendererSceneSkyRD
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
-RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
// !BAS! Why isn't _create_sky_shader_func not just static too?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
};
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
// !BAS! same here, we could just make _create_sky_material_func static?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
@@ -797,6 +798,7 @@ RendererSceneSkyRD::RendererSceneSkyRD() {
void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
{
@@ -833,8 +835,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
}
// register our shader funds
- storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
- storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -896,10 +898,10 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
{
// default material and shader for sky shader
- sky_shader.default_shader = storage->shader_allocate();
- storage->shader_initialize(sky_shader.default_shader);
+ sky_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(sky_shader.default_shader);
- storage->shader_set_code(sky_shader.default_shader, R"(
+ material_storage->shader_set_code(sky_shader.default_shader, R"(
// Default sky shader.
shader_type sky;
@@ -909,12 +911,12 @@ void sky() {
}
)");
- sky_shader.default_material = storage->material_allocate();
- storage->material_initialize(sky_shader.default_material);
+ sky_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(sky_shader.default_material);
- storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
+ material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
- SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
+ SkyMaterialData *md = (SkyMaterialData *)material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY);
sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
@@ -947,7 +949,7 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(storage->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -986,10 +988,10 @@ void sky() {
{
// Need defaults for using fog with clear color
- sky_scene_state.fog_shader = storage->shader_allocate();
- storage->shader_initialize(sky_scene_state.fog_shader);
+ sky_scene_state.fog_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(sky_scene_state.fog_shader);
- storage->shader_set_code(sky_scene_state.fog_shader, R"(
+ material_storage->shader_set_code(sky_scene_state.fog_shader, R"(
// Default clear color sky shader.
shader_type sky;
@@ -1000,10 +1002,10 @@ void sky() {
COLOR = clear_color.rgb;
}
)");
- sky_scene_state.fog_material = storage->material_allocate();
- storage->material_initialize(sky_scene_state.fog_material);
+ sky_scene_state.fog_material = material_storage->material_allocate();
+ material_storage->material_initialize(sky_scene_state.fog_material);
- storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
+ material_storage->material_set_shader(sky_scene_state.fog_material, sky_scene_state.fog_shader);
Vector<RD::Uniform> uniforms;
{
@@ -1054,7 +1056,19 @@ void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
}
RendererSceneSkyRD::~RendererSceneSkyRD() {
- // TODO cleanup anything created in init...
+ // cleanup anything created in init...
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ SkyMaterialData *md = (SkyMaterialData *)material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY);
+ sky_shader.shader.version_free(md->shader_data->version);
+ RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
+ RD::get_singleton()->free(sky_scene_state.uniform_buffer);
+ memdelete_arr(sky_scene_state.directional_lights);
+ memdelete_arr(sky_scene_state.last_frame_directional_lights);
+ material_storage->shader_free(sky_shader.default_shader);
+ material_storage->material_free(sky_shader.default_material);
+ material_storage->shader_free(sky_scene_state.fog_shader);
+ material_storage->material_free(sky_scene_state.fog_material);
if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
RD::get_singleton()->free(sky_scene_state.uniform_set);
@@ -1072,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
}
void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
SkyMaterialData *material = nullptr;
@@ -1085,7 +1100,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1093,7 +1108,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
ERR_FAIL_COND(!material);
@@ -1282,6 +1297,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
}
void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@@ -1292,7 +1308,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1300,7 +1316,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
ERR_FAIL_COND(!material);
@@ -1450,6 +1466,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1467,7 +1484,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1475,13 +1492,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
ERR_FAIL_COND(!material);
@@ -1556,6 +1573,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1570,7 +1588,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1578,7 +1596,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
ERR_FAIL_COND(!material);
@@ -1640,6 +1658,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
}
void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1657,7 +1676,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
sky_material = sky_get_material(p_env->sky);
if (sky_material.is_valid()) {
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1665,13 +1684,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
if (!material) {
sky_material = sky_shader.default_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY);
+ material = (SkyMaterialData *)material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY);
}
ERR_FAIL_COND(!material);
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 13d24e2508..7a3e545add 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -105,7 +105,7 @@ private:
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
- struct SkyShaderData : public RendererStorageRD::ShaderData {
+ struct SkyShaderData : public RendererRD::ShaderData {
bool valid;
RID version;
@@ -129,7 +129,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
@@ -227,7 +227,7 @@ public:
RID default_shader_rd;
} sky_shader;
- struct SkyMaterialData : public RendererStorageRD::MaterialData {
+ struct SkyMaterialData : public RendererRD::MaterialData {
SkyShaderData *shader_data;
RID uniform_set;
bool uniform_set_updated;
@@ -281,11 +281,11 @@ public:
mutable RID_Owner<Sky, true> sky_owner;
int roughness_layers;
- RendererStorageRD::ShaderData *_create_sky_shader_func();
- static RendererStorageRD::ShaderData *_create_sky_shader_funcs();
+ RendererRD::ShaderData *_create_sky_shader_func();
+ static RendererRD::ShaderData *_create_sky_shader_funcs();
- RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
+ RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
RendererSceneSkyRD();
void init(RendererStorageRD *p_storage);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 5b6dfbe19f..c5df3a9f4e 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -35,9 +35,6 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
@@ -137,1622 +134,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
}
}
-/* SHADER API */
-
-RID RendererStorageRD::shader_allocate() {
- return shader_owner.allocate_rid();
-}
-void RendererStorageRD::shader_initialize(RID p_rid) {
- Shader shader;
- shader.data = nullptr;
- shader.type = SHADER_TYPE_MAX;
-
- shader_owner.initialize_rid(p_rid, shader);
-}
-
-void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
-
- shader->code = p_code;
- String mode_string = ShaderLanguage::get_shader_type(p_code);
-
- ShaderType new_type;
- if (mode_string == "canvas_item") {
- new_type = SHADER_TYPE_2D;
- } else if (mode_string == "particles") {
- new_type = SHADER_TYPE_PARTICLES;
- } else if (mode_string == "spatial") {
- new_type = SHADER_TYPE_3D;
- } else if (mode_string == "sky") {
- new_type = SHADER_TYPE_SKY;
- } else if (mode_string == "fog") {
- new_type = SHADER_TYPE_FOG;
- } else {
- new_type = SHADER_TYPE_MAX;
- }
-
- if (new_type != shader->type) {
- if (shader->data) {
- memdelete(shader->data);
- shader->data = nullptr;
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- material->shader_type = new_type;
- if (material->data) {
- memdelete(material->data);
- material->data = nullptr;
- }
- }
-
- shader->type = new_type;
-
- if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
- shader->data = shader_data_request_func[new_type]();
- } else {
- shader->type = SHADER_TYPE_MAX; //invalid
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- if (shader->data) {
- material->data = material_data_request_func[new_type](shader->data);
- material->data->self = material->self;
- material->data->set_next_pass(material->next_pass);
- material->data->set_render_priority(material->priority);
- }
- material->shader_type = new_type;
- }
-
- if (shader->data) {
- for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
- for (const KeyValue<int, RID> &E2 : E.value) {
- shader->data->set_default_texture_param(E.key, E2.value, E2.key);
- }
- }
- }
- }
-
- if (shader->data) {
- shader->data->set_code(p_code);
- }
-
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- _material_queue_update(material, true, true);
- }
-}
-
-String RendererStorageRD::shader_get_code(RID p_shader) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, String());
- return shader->code;
-}
-
-void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
- if (shader->data) {
- return shader->data->get_param_list(p_param_list);
- }
-}
-
-void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
-
- if (p_texture.is_valid() && RendererRD::TextureStorage::get_singleton()->owns_texture(p_texture)) {
- if (!shader->default_texture_parameter.has(p_name)) {
- shader->default_texture_parameter[p_name] = Map<int, RID>();
- }
- shader->default_texture_parameter[p_name][p_index] = p_texture;
- } else {
- if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
- shader->default_texture_parameter[p_name].erase(p_index);
-
- if (shader->default_texture_parameter[p_name].is_empty()) {
- shader->default_texture_parameter.erase(p_name);
- }
- }
- }
- if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture, p_index);
- }
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
- Material *material = E->get();
- _material_queue_update(material, false, true);
- }
-}
-
-RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, RID());
- if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
- return shader->default_texture_parameter[p_name][p_index];
- }
-
- return RID();
-}
-
-Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, Variant());
- if (shader->data) {
- return shader->data->get_default_parameter(p_param);
- }
- return Variant();
-}
-
-void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
- ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
- shader_data_request_func[p_shader_type] = p_function;
-}
-
-RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
- if (shader->data) {
- return shader->data->get_native_source_code();
- }
- return RS::ShaderNativeSourceCode();
-}
-
-/* COMMON MATERIAL API */
-
-RID RendererStorageRD::material_allocate() {
- return material_owner.allocate_rid();
-}
-void RendererStorageRD::material_initialize(RID p_rid) {
- material_owner.initialize_rid(p_rid);
- Material *material = material_owner.get_or_null(p_rid);
- material->self = p_rid;
-}
-
-void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
- material->uniform_dirty = material->uniform_dirty || p_uniform;
- material->texture_dirty = material->texture_dirty || p_texture;
-
- if (material->update_element.in_list()) {
- return;
- }
-
- material_update_list.add(&material->update_element);
-}
-
-void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (material->data) {
- memdelete(material->data);
- material->data = nullptr;
- }
-
- if (material->shader) {
- material->shader->owners.erase(material);
- material->shader = nullptr;
- material->shader_type = SHADER_TYPE_MAX;
- }
-
- if (p_shader.is_null()) {
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- material->shader_id = 0;
- return;
- }
-
- Shader *shader = shader_owner.get_or_null(p_shader);
- ERR_FAIL_COND(!shader);
- material->shader = shader;
- material->shader_type = shader->type;
- material->shader_id = p_shader.get_local_index();
- shader->owners.insert(material);
-
- if (shader->type == SHADER_TYPE_MAX) {
- return;
- }
-
- ERR_FAIL_COND(shader->data == nullptr);
-
- material->data = material_data_request_func[shader->type](shader->data);
- material->data->self = p_material;
- material->data->set_next_pass(material->next_pass);
- material->data->set_render_priority(material->priority);
- //updating happens later
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- _material_queue_update(material, true, true);
-}
-
-void RendererStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (p_value.get_type() == Variant::NIL) {
- material->params.erase(p_param);
- } else {
- ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
- material->params[p_param] = p_value;
- }
-
- if (material->shader && material->shader->data) { //shader is valid
- bool is_texture = material->shader->data->is_param_texture(p_param);
- _material_queue_update(material, !is_texture, is_texture);
- } else {
- _material_queue_update(material, true, true);
- }
-}
-
-Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, Variant());
- if (material->params.has(p_param)) {
- return material->params[p_param];
- } else {
- return Variant();
- }
-}
-
-void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
-
- if (material->next_pass == p_next_material) {
- return;
- }
-
- material->next_pass = p_next_material;
- if (material->data) {
- material->data->set_next_pass(p_next_material);
- }
-
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
-}
-
-void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- material->priority = priority;
- if (material->data) {
- material->data->set_render_priority(priority);
- }
-}
-
-bool RendererStorageRD::material_is_animated(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, false);
- if (material->shader && material->shader->data) {
- if (material->shader->data->is_animated()) {
- return true;
- } else if (material->next_pass.is_valid()) {
- return material_is_animated(material->next_pass);
- }
- }
- return false; //by default nothing is animated
-}
-
-bool RendererStorageRD::material_casts_shadows(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND_V(!material, true);
- if (material->shader && material->shader->data) {
- if (material->shader->data->casts_shadows()) {
- return true;
- } else if (material->next_pass.is_valid()) {
- return material_casts_shadows(material->next_pass);
- }
- }
- return true; //by default everything casts shadows
-}
-
-void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- if (material->shader && material->shader->data) {
- material->shader->data->get_instance_param_list(r_parameters);
-
- if (material->next_pass.is_valid()) {
- material_get_instance_shader_parameters(material->next_pass, r_parameters);
- }
- }
-}
-
-void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
- Material *material = material_owner.get_or_null(p_material);
- ERR_FAIL_COND(!material);
- p_instance->update_dependency(&material->dependency);
- if (material->next_pass.is_valid()) {
- material_update_dependency(material->next_pass, p_instance);
- }
-}
-
-void RendererStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
- ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
- material_data_request_func[p_shader_type] = p_function;
-}
-
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = (r[i] != 0) ? 1 : 0;
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- bool v = value;
- gui[0] = v ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 2 * p_array_size;
-
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i] ? 1 : 0;
- gui[j + 1] = r[i + 1] ? 1 : 0;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v & 1 ? 1 : 0;
- gui[1] = v & 2 ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 3 * p_array_size;
-
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i] ? 1 : 0;
- gui[j + 1] = r[i + 1] ? 1 : 0;
- gui[j + 2] = r[i + 2] ? 1 : 0;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- const PackedInt32Array &ba = value;
- int s = ba.size();
- const int *r = ba.ptr();
- int count = 4 * p_array_size;
-
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i] ? 1 : 0;
- gui[i + 1] = r[i + 1] ? 1 : 0;
- gui[i + 2] = r[i + 2] ? 1 : 0;
- gui[i + 3] = r[i + 3] ? 1 : 0;
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } else {
- int v = value;
- gui[0] = (v & 1) ? 1 : 0;
- gui[1] = (v & 2) ? 1 : 0;
- gui[2] = (v & 4) ? 1 : 0;
- gui[3] = (v & 8) ? 1 : 0;
- }
- } break;
- case ShaderLanguage::TYPE_INT: {
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size > 0) {
- Vector<int> iv = value;
- int s = iv.size();
- const int *r = iv.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
- int32_t *gui = (int32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } break;
- case ShaderLanguage::TYPE_UINT: {
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size > 0) {
- Vector<int> iv = value;
- int s = iv.size();
- const int *r = iv.ptr();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- int v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
- uint32_t *gui = (uint32_t *)data;
-
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i];
- } else {
- gui[j] = 0;
- }
- gui[j + 1] = 0; // ignored
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- float v = value;
- gui[0] = v;
- }
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedVector2Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i].x;
- gui[j + 1] = a[i].y;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- }
- } else {
- Vector2 v = value;
- gui[0] = v.x;
- gui[1] = v.y;
- }
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedVector3Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- gui[j] = a[i].x;
- gui[j + 1] = a[i].y;
- gui[j + 2] = a[i].z;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- }
- gui[j + 3] = 0; // ignored
- }
- } else {
- Vector3 v = value;
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- }
- } break;
- case ShaderLanguage::TYPE_VEC4: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
- const PackedColorArray &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
- if (i < s) {
- Color color = a[i];
- if (p_linear_color) {
- color = color.to_linear();
- }
- gui[j] = color.r;
- gui[j + 1] = color.g;
- gui[j + 2] = color.b;
- gui[j + 3] = color.a;
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
- gui[j + 3] = 0;
- }
- }
- } else {
- const PackedFloat32Array &a = value;
- int s = a.size();
- int count = 4 * p_array_size;
-
- for (int i = 0; i < count; i += 4) {
- if (i + 3 < s) {
- gui[i] = a[i];
- gui[i + 1] = a[i + 1];
- gui[i + 2] = a[i + 2];
- gui[i + 3] = a[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
- }
- }
- }
- } else {
- if (value.get_type() == Variant::COLOR) {
- Color v = value;
-
- if (p_linear_color) {
- v = v.to_linear();
- }
-
- gui[0] = v.r;
- gui[1] = v.g;
- gui[2] = v.b;
- gui[3] = v.a;
- } else if (value.get_type() == Variant::RECT2) {
- Rect2 v = value;
-
- gui[0] = v.position.x;
- gui[1] = v.position.y;
- gui[2] = v.size.x;
- gui[3] = v.size.y;
- } else if (value.get_type() == Variant::QUATERNION) {
- Quaternion v = value;
-
- gui[0] = v.x;
- gui[1] = v.y;
- gui[2] = v.z;
- gui[3] = v.w;
- } else {
- Plane v = value;
-
- gui[0] = v.normal.x;
- gui[1] = v.normal.y;
- gui[2] = v.normal.z;
- gui[3] = v.d;
- }
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
- if (i + 3 < s) {
- gui[j] = a[i];
- gui[j + 1] = a[i + 1];
-
- gui[j + 4] = a[i + 2];
- gui[j + 5] = a[i + 3];
- } else {
- gui[j] = 1;
- gui[j + 1] = 0;
-
- gui[j + 4] = 0;
- gui[j + 5] = 1;
- }
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
- gui[j + 6] = 0; // ignored
- gui[j + 7] = 0; // ignored
- }
- } else {
- Transform2D v = value;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[0][1];
- gui[2] = 0; // ignored
- gui[3] = 0; // ignored
-
- gui[4] = v.elements[1][0];
- gui[5] = v.elements[1][1];
- gui[6] = 0; // ignored
- gui[7] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
- if (i + 8 < s) {
- gui[j] = a[i];
- gui[j + 1] = a[i + 1];
- gui[j + 2] = a[i + 2];
-
- gui[j + 4] = a[i + 3];
- gui[j + 5] = a[i + 4];
- gui[j + 6] = a[i + 5];
-
- gui[j + 8] = a[i + 6];
- gui[j + 9] = a[i + 7];
- gui[j + 10] = a[i + 8];
- } else {
- gui[j] = 1;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
-
- gui[j + 4] = 0;
- gui[j + 5] = 1;
- gui[j + 6] = 0;
-
- gui[j + 8] = 0;
- gui[j + 9] = 0;
- gui[j + 10] = 1;
- }
- gui[j + 3] = 0; // ignored
- gui[j + 7] = 0; // ignored
- gui[j + 11] = 0; // ignored
- }
- } else {
- Basis v = value;
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[1][0];
- gui[2] = v.elements[2][0];
- gui[3] = 0; // ignored
-
- gui[4] = v.elements[0][1];
- gui[5] = v.elements[1][1];
- gui[6] = v.elements[2][1];
- gui[7] = 0; // ignored
-
- gui[8] = v.elements[0][2];
- gui[9] = v.elements[1][2];
- gui[10] = v.elements[2][2];
- gui[11] = 0; // ignored
- }
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- float *gui = (float *)data;
-
- if (p_array_size > 0) {
- const PackedFloat32Array &a = value;
- int s = a.size();
-
- for (int i = 0; i < p_array_size * 16; i += 16) {
- if (i + 15 < s) {
- gui[i] = a[i];
- gui[i + 1] = a[i + 1];
- gui[i + 2] = a[i + 2];
- gui[i + 3] = a[i + 3];
-
- gui[i + 4] = a[i + 4];
- gui[i + 5] = a[i + 5];
- gui[i + 6] = a[i + 6];
- gui[i + 7] = a[i + 7];
-
- gui[i + 8] = a[i + 8];
- gui[i + 9] = a[i + 9];
- gui[i + 10] = a[i + 10];
- gui[i + 11] = a[i + 11];
-
- gui[i + 12] = a[i + 12];
- gui[i + 13] = a[i + 13];
- gui[i + 14] = a[i + 14];
- gui[i + 15] = a[i + 15];
- } else {
- gui[i] = 1;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
-
- gui[i + 4] = 0;
- gui[i + 5] = 1;
- gui[i + 6] = 0;
- gui[i + 7] = 0;
-
- gui[i + 8] = 0;
- gui[i + 9] = 0;
- gui[i + 10] = 1;
- gui[i + 11] = 0;
-
- gui[i + 12] = 0;
- gui[i + 13] = 0;
- gui[i + 14] = 0;
- gui[i + 15] = 1;
- }
- }
- } else {
- Transform3D v = value;
- gui[0] = v.basis.elements[0][0];
- gui[1] = v.basis.elements[1][0];
- gui[2] = v.basis.elements[2][0];
- gui[3] = 0;
-
- gui[4] = v.basis.elements[0][1];
- gui[5] = v.basis.elements[1][1];
- gui[6] = v.basis.elements[2][1];
- gui[7] = 0;
-
- gui[8] = v.basis.elements[0][2];
- gui[9] = v.basis.elements[1][2];
- gui[10] = v.basis.elements[2][2];
- gui[11] = 0;
-
- gui[12] = v.origin.x;
- gui[13] = v.origin.y;
- gui[14] = v.origin.z;
- gui[15] = 1;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
- switch (type) {
- case ShaderLanguage::TYPE_BOOL: {
- uint32_t *gui = (uint32_t *)data;
- *gui = value[0].boolean ? 1 : 0;
- } break;
- case ShaderLanguage::TYPE_BVEC2: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_BVEC3: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
- gui[2] = value[2].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_BVEC4: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].boolean ? 1 : 0;
- gui[1] = value[1].boolean ? 1 : 0;
- gui[2] = value[2].boolean ? 1 : 0;
- gui[3] = value[3].boolean ? 1 : 0;
-
- } break;
- case ShaderLanguage::TYPE_INT: {
- int32_t *gui = (int32_t *)data;
- gui[0] = value[0].sint;
-
- } break;
- case ShaderLanguage::TYPE_IVEC2: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC3: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_IVEC4: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].sint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UINT: {
- uint32_t *gui = (uint32_t *)data;
- gui[0] = value[0].uint;
-
- } break;
- case ShaderLanguage::TYPE_UVEC2: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_UVEC3: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].uint;
- }
-
- } break;
- case ShaderLanguage::TYPE_UVEC4: {
- int32_t *gui = (int32_t *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].uint;
- }
- } break;
- case ShaderLanguage::TYPE_FLOAT: {
- float *gui = (float *)data;
- gui[0] = value[0].real;
-
- } break;
- case ShaderLanguage::TYPE_VEC2: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 2; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC3: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 3; i++) {
- gui[i] = value[i].real;
- }
-
- } break;
- case ShaderLanguage::TYPE_VEC4: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 4; i++) {
- gui[i] = value[i].real;
- }
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- float *gui = (float *)data;
-
- //in std140 members of mat2 are treated as vec4s
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = 0;
- gui[3] = 0;
- gui[4] = value[2].real;
- gui[5] = value[3].real;
- gui[6] = 0;
- gui[7] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- float *gui = (float *)data;
-
- gui[0] = value[0].real;
- gui[1] = value[1].real;
- gui[2] = value[2].real;
- gui[3] = 0;
- gui[4] = value[3].real;
- gui[5] = value[4].real;
- gui[6] = value[5].real;
- gui[7] = 0;
- gui[8] = value[6].real;
- gui[9] = value[7].real;
- gui[10] = value[8].real;
- gui[11] = 0;
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- float *gui = (float *)data;
-
- for (int i = 0; i < 16; i++) {
- gui[i] = value[i].real;
- }
- } break;
- default: {
- }
- }
-}
-
-_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
-
- switch (type) {
- case ShaderLanguage::TYPE_BOOL:
- case ShaderLanguage::TYPE_INT:
- case ShaderLanguage::TYPE_UINT:
- case ShaderLanguage::TYPE_FLOAT: {
- memset(data, 0, 4 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_BVEC2:
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_UVEC2:
- case ShaderLanguage::TYPE_VEC2: {
- memset(data, 0, 8 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_BVEC3:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_VEC3:
- case ShaderLanguage::TYPE_BVEC4:
- case ShaderLanguage::TYPE_IVEC4:
- case ShaderLanguage::TYPE_UVEC4:
- case ShaderLanguage::TYPE_VEC4: {
- memset(data, 0, 16 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT2: {
- memset(data, 0, 32 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT3: {
- memset(data, 0, 48 * p_array_size);
- } break;
- case ShaderLanguage::TYPE_MAT4: {
- memset(data, 0, 64 * p_array_size);
- } break;
-
- default: {
- }
- }
-}
-
-void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
- bool uses_global_buffer = false;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
- if (E.value.order < 0) {
- continue; // texture, does not go here
- }
-
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue; //instance uniforms don't appear in the buffer
- }
-
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
- //this is a global variable, get the index to it
- RendererStorageRD *rs = base_singleton;
-
- GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E.key);
- uint32_t index = 0;
- if (gv) {
- index = gv->buffer_index;
- } else {
- WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
- }
-
- uint32_t offset = p_uniform_offsets[E.value.order];
- uint32_t *intptr = (uint32_t *)&p_buffer[offset];
- *intptr = index;
- uses_global_buffer = true;
- continue;
- }
-
- //regular uniform
- uint32_t offset = p_uniform_offsets[E.value.order];
-#ifdef DEBUG_ENABLED
- uint32_t size = 0U;
- // The following code enforces a 16-byte alignment of uniform arrays.
- if (E.value.array_size > 0) {
- size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
- int m = (16 * E.value.array_size);
- if ((size % m) != 0U) {
- size += m - (size % m);
- }
- } else {
- size = ShaderLanguage::get_datatype_size(E.value.type);
- }
- ERR_CONTINUE(offset + size > p_buffer_size);
-#endif
- uint8_t *data = &p_buffer[offset];
- const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
-
- if (V) {
- //user provided
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
-
- } else if (E.value.default_value.size()) {
- //default value
- _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
- //value=E.value.default_value;
- } else {
- //zero because it was not provided
- if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
- //colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
- } else {
- //else just zero it out
- _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
- }
- }
- }
-
- if (uses_global_buffer != (global_buffer_E != nullptr)) {
- RendererStorageRD *rs = base_singleton;
- if (uses_global_buffer) {
- global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self);
- } else {
- rs->global_variables.materials_using_buffer.erase(global_buffer_E);
- global_buffer_E = nullptr;
- }
- }
-}
-
-RendererStorageRD::MaterialData::~MaterialData() {
- if (global_buffer_E) {
- //unregister global buffers
- RendererStorageRD *rs = base_singleton;
- rs->global_variables.materials_using_buffer.erase(global_buffer_E);
- }
-
- if (global_texture_E) {
- //unregister global textures
- RendererStorageRD *rs = base_singleton;
-
- for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E.key);
- if (v) {
- v->texture_materials.erase(self);
- }
- }
- //unregister material from those using global textures
- rs->global_variables.materials_using_texture.erase(global_texture_E);
- }
-
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- }
-}
-
-void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
-#ifdef TOOLS_ENABLED
- RendererRD::Texture *roughness_detect_texture = nullptr;
- RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
- RendererRD::Texture *normal_detect_texture = nullptr;
-#endif
-
- bool uses_global_textures = false;
- global_textures_pass++;
-
- for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
- const StringName &uniform_name = p_texture_uniforms[i].name;
- int uniform_array_size = p_texture_uniforms[i].array_size;
-
- Vector<RID> textures;
-
- if (p_texture_uniforms[i].global) {
- RendererStorageRD *rs = base_singleton;
-
- uses_global_textures = true;
-
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name);
- if (v) {
- if (v->buffer_index >= 0) {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
-
- } else {
- Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
- if (!E) {
- E = used_global_textures.insert(uniform_name, global_textures_pass);
- v->texture_materials.insert(self);
- } else {
- E->get() = global_textures_pass;
- }
-
- textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
- }
-
- } else {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
- }
- } else {
- const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
- if (V) {
- if (V->get().is_array()) {
- Array array = (Array)V->get();
- if (uniform_array_size > 0) {
- for (int j = 0; j < array.size(); j++) {
- textures.push_back(array[j]);
- }
- } else {
- if (array.size() > 0) {
- textures.push_back(array[0]);
- }
- }
- } else {
- textures.push_back(V->get());
- }
- }
-
- if (uniform_array_size > 0) {
- if (textures.size() < uniform_array_size) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- for (int j = textures.size(); j < uniform_array_size; j++) {
- if (W && W->get().has(j)) {
- textures.push_back(W->get()[j]);
- } else {
- textures.push_back(RID());
- }
- }
- }
- } else if (textures.is_empty()) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- if (W && W->get().has(0)) {
- textures.push_back(W->get()[0]);
- }
- }
- }
-
- RID rd_texture;
-
- if (textures.is_empty()) {
- //check default usage
- switch (p_texture_uniforms[i].type) {
- case ShaderLanguage::TYPE_ISAMPLER2D:
- case ShaderLanguage::TYPE_USAMPLER2D:
- case ShaderLanguage::TYPE_SAMPLER2D: {
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_ANISO);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
- } break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
- } break;
- default: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
- } break;
- }
- } break;
-
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- } break;
- default: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
- } break;
- }
- } break;
- case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER3D:
- case ShaderLanguage::TYPE_USAMPLER3D:
- case ShaderLanguage::TYPE_SAMPLER3D: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- } break;
-
- case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
- case ShaderLanguage::TYPE_USAMPLER2DARRAY:
- case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
- } break;
-
- default: {
- }
- }
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
- if (uniform_array_size > 0) {
- for (int j = 0; j < uniform_array_size; j++) {
- p_textures[k++] = rd_texture;
- }
- } else {
- p_textures[k++] = rd_texture;
- }
- } else {
- bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
-
- for (int j = 0; j < textures.size(); j++) {
- RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(textures[j]);
-
- if (tex) {
- rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
-#ifdef TOOLS_ENABLED
- if (tex->detect_3d_callback && p_use_linear_color) {
- tex->detect_3d_callback(tex->detect_3d_callback_ud);
- }
- 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)) {
- if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
- normal_detect_texture = tex;
- }
- tex->detect_normal_callback(tex->detect_normal_callback_ud);
- }
- 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)) {
- //find the normal texture
- roughness_detect_texture = tex;
- roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
- }
-#endif
- }
- if (rd_texture.is_null()) {
- rd_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
- }
-#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
- roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
- }
-#endif
- p_textures[k++] = rd_texture;
- }
- }
- }
- {
- //for textures no longer used, unregister them
- List<Map<StringName, uint64_t>::Element *> to_delete;
- RendererStorageRD *rs = base_singleton;
-
- for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
- if (E->get() != global_textures_pass) {
- to_delete.push_back(E);
-
- GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
- if (v) {
- v->texture_materials.erase(self);
- }
- }
- }
-
- while (to_delete.front()) {
- used_global_textures.erase(to_delete.front()->get());
- to_delete.pop_front();
- }
- //handle registering/unregistering global textures
- if (uses_global_textures != (global_texture_E != nullptr)) {
- if (uses_global_textures) {
- global_texture_E = rs->global_variables.materials_using_texture.push_back(self);
- } else {
- rs->global_variables.materials_using_texture.erase(global_texture_E);
- global_texture_E = nullptr;
- }
- }
- }
-}
-
-void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
- if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(p_uniform_set);
- }
-}
-
-bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
- if ((uint32_t)ubo_data.size() != p_ubo_size) {
- p_uniform_dirty = true;
- if (uniform_buffer.is_valid()) {
- RD::get_singleton()->free(uniform_buffer);
- uniform_buffer = RID();
- }
-
- ubo_data.resize(p_ubo_size);
- if (ubo_data.size()) {
- uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
- memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
- }
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- //check whether buffer changed
- if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
- RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
- }
-
- uint32_t tex_uniform_count = 0U;
- for (int i = 0; i < p_texture_uniforms.size(); i++) {
- tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
- }
-
- if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
- texture_cache.resize(tex_uniform_count);
- p_textures_dirty = true;
-
- //clear previous uniform set
- if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
- RD::get_singleton()->free(uniform_set);
- uniform_set = RID();
- }
- }
-
- if (p_textures_dirty && tex_uniform_count) {
- update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
- }
-
- if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
- // This material does not require an uniform set, so don't create it.
- return false;
- }
-
- if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //no reason to update uniform set, only UBO (or nothing) was needed to update
- return false;
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- if (p_ubo_size) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.append_id(uniform_buffer);
- uniforms.push_back(u);
- }
-
- const RID *textures = texture_cache.ptrw();
- for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
- const int array_size = p_texture_uniforms[i].array_size;
-
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1 + k;
- if (array_size > 0) {
- for (int j = 0; j < array_size; j++) {
- u.append_id(textures[k++]);
- }
- } else {
- u.append_id(textures[k++]);
- }
- uniforms.push_back(u);
- }
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
-
- RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, _material_uniform_set_erased, &self);
-
- return true;
-}
-
-void RendererStorageRD::_material_uniform_set_erased(void *p_material) {
- RID rid = *(RID *)p_material;
- Material *material = base_singleton->material_owner.get_or_null(rid);
- if (material) {
- if (material->data) {
- // Uniform set may be gone because a dependency was erased. This happens
- // if a texture is deleted, so re-create it.
- base_singleton->_material_queue_update(material, false, true);
- }
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- }
-}
-
-void RendererStorageRD::_update_queued_materials() {
- while (material_update_list.first()) {
- Material *material = material_update_list.first()->self();
- bool uniforms_changed = false;
-
- if (material->data) {
- uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
- }
- material->texture_dirty = false;
- material->uniform_dirty = false;
-
- material_update_list.remove(&material->update_element);
-
- if (uniforms_changed) {
- //some implementations such as 3D renderer cache the matreial uniform set, so update is required
- material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- }
- }
-}
-
/* MESH API */
RID RendererStorageRD::mesh_allocate() {
@@ -3705,6 +2086,7 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool
void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -4094,9 +2476,9 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
- ParticlesMaterialData *m = (ParticlesMaterialData *)material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES);
+ ParticlesMaterialData *m = (ParticlesMaterialData *)material_storage->material_get_data(p_particles->process_material, RendererRD::SHADER_TYPE_PARTICLES);
if (!m) {
- m = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES);
+ m = (ParticlesMaterialData *)material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES);
}
ERR_FAIL_COND(!m);
@@ -4249,7 +2631,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
void RendererStorageRD::_particles_update_buffers(Particles *particles) {
uint32_t userdata_count = 0;
- const Material *material = material_owner.get_or_null(particles->process_material);
+ const RendererRD::Material *material = RendererRD::MaterialStorage::get_singleton()->get_material(particles->process_material);
if (material && material->shader && material->shader->data) {
const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
userdata_count = shader_data->userdata_count;
@@ -4636,13 +3018,13 @@ void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *
}
}
-void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
- RendererStorage::InstanceShaderParam p;
+ RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
@@ -4691,7 +3073,7 @@ RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() {
}
}
-RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func() {
+RendererRD::ShaderData *RendererStorageRD::_create_particles_shader_func() {
ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
return shader_data;
}
@@ -4704,7 +3086,7 @@ RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
+RendererRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -7013,673 +5395,9 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
return RS::INSTANCE_NONE;
}
-int32_t RendererStorageRD::_global_variable_allocate(uint32_t p_elements) {
- int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
- bool valid = true;
- for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
- valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
- break;
- }
- }
-
- if (!valid) {
- continue; //if not valid, idx is in new position
- }
-
- return idx;
- } else {
- idx += global_variables.buffer_usage[idx].elements;
- }
- }
-
- return -1;
-}
-
-void RendererStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
- switch (p_type) {
- case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- bool b = p_value;
- bv.x = b ? 1.0 : 0.0;
- bv.y = 0.0;
- bv.z = 0.0;
- bv.w = 0.0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = 0.0;
- bv.w = 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = (bvec & 4) ? 1.0 : 0.0;
- bv.w = 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- uint32_t bvec = p_value;
- bv.x = (bvec & 1) ? 1.0 : 0.0;
- bv.y = (bvec & 2) ? 1.0 : 0.0;
- bv.z = (bvec & 4) ? 1.0 : 0.0;
- bv.w = (bvec & 8) ? 1.0 : 0.0;
- } break;
- case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- int32_t v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector2i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector3i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Vector<int32_t> v = p_value;
- bv.x = v.size() >= 1 ? v[0] : 0;
- bv.y = v.size() >= 2 ? v[1] : 0;
- bv.z = v.size() >= 3 ? v[2] : 0;
- bv.w = v.size() >= 4 ? v[3] : 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
- Rect2i v = p_value;
- bv.x = v.position.x;
- bv.y = v.position.y;
- bv.z = v.size.x;
- bv.w = v.size.y;
- } break;
- case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- uint32_t v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector2i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector3i v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
- Vector<int32_t> v = p_value;
- bv.x = v.size() >= 1 ? v[0] : 0;
- bv.y = v.size() >= 2 ? v[1] : 0;
- bv.z = v.size() >= 3 ? v[2] : 0;
- bv.w = v.size() >= 4 ? v[3] : 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- float v = p_value;
- bv.x = v;
- bv.y = 0;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Vector2 v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = 0;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Vector3 v = p_value;
- bv.x = v.x;
- bv.y = v.y;
- bv.z = v.z;
- bv.w = 0;
- } break;
- case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Plane v = p_value;
- bv.x = v.normal.x;
- bv.y = v.normal.y;
- bv.z = v.normal.z;
- bv.w = v.d;
- } break;
- case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Color v = p_value;
- bv.x = v.r;
- bv.y = v.g;
- bv.z = v.b;
- bv.w = v.a;
-
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
- v = v.to_linear();
- bv_linear.x = v.r;
- bv_linear.y = v.g;
- bv_linear.z = v.b;
- bv_linear.w = v.a;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
- Rect2 v = p_value;
- bv.x = v.position.x;
- bv.y = v.position.y;
- bv.z = v.size.x;
- bv.w = v.size.y;
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Vector<float> m2 = p_value;
- if (m2.size() < 4) {
- m2.resize(4);
- }
- bv[0].x = m2[0];
- bv[0].y = m2[1];
- bv[0].z = 0;
- bv[0].w = 0;
-
- bv[1].x = m2[2];
- bv[1].y = m2[3];
- bv[1].z = 0;
- bv[1].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Basis v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[1][0];
- bv[0].z = v.elements[2][0];
- bv[0].w = 0;
-
- bv[1].x = v.elements[0][1];
- bv[1].y = v.elements[1][1];
- bv[1].z = v.elements[2][1];
- bv[1].w = 0;
-
- bv[2].x = v.elements[0][2];
- bv[2].y = v.elements[1][2];
- bv[2].z = v.elements[2][2];
- bv[2].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
-
- Vector<float> m2 = p_value;
- if (m2.size() < 16) {
- m2.resize(16);
- }
-
- bv[0].x = m2[0];
- bv[0].y = m2[1];
- bv[0].z = m2[2];
- bv[0].w = m2[3];
-
- bv[1].x = m2[4];
- bv[1].y = m2[5];
- bv[1].z = m2[6];
- bv[1].w = m2[7];
-
- bv[2].x = m2[8];
- bv[2].y = m2[9];
- bv[2].z = m2[10];
- bv[2].w = m2[11];
-
- bv[3].x = m2[12];
- bv[3].y = m2[13];
- bv[3].z = m2[14];
- bv[3].w = m2[15];
-
- } break;
- case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform2D v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[0][1];
- bv[0].z = 0;
- bv[0].w = 0;
-
- bv[1].x = v.elements[1][0];
- bv[1].y = v.elements[1][1];
- bv[1].z = 0;
- bv[1].w = 0;
-
- bv[2].x = v.elements[2][0];
- bv[2].y = v.elements[2][1];
- bv[2].z = 1;
- bv[2].w = 0;
-
- } break;
- case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
- Transform3D v = p_value;
- bv[0].x = v.basis.elements[0][0];
- bv[0].y = v.basis.elements[1][0];
- bv[0].z = v.basis.elements[2][0];
- bv[0].w = 0;
-
- bv[1].x = v.basis.elements[0][1];
- bv[1].y = v.basis.elements[1][1];
- bv[1].z = v.basis.elements[2][1];
- bv[1].w = 0;
-
- bv[2].x = v.basis.elements[0][2];
- bv[2].y = v.basis.elements[1][2];
- bv[2].z = v.basis.elements[2][2];
- bv[2].w = 0;
-
- bv[3].x = v.origin.x;
- bv[3].y = v.origin.y;
- bv[3].z = v.origin.z;
- bv[3].w = 1;
-
- } break;
- default: {
- ERR_FAIL();
- }
- }
-}
-
-void RendererStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
- int32_t prev_chunk = -1;
-
- for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
- }
- }
-
- prev_chunk = chunk;
- }
-}
-
-void RendererStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
- gv.type = p_type;
- gv.value = p_value;
- gv.buffer_index = -1;
-
- if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //is texture
- global_variables.must_update_texture_materials = true; //normally there are none
- } else {
- gv.buffer_elements = 1;
- if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 2;
- }
- if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 3;
- }
- if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
- //color needs to elements to store srgb and linear
- gv.buffer_elements = 4;
- }
-
- //is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
- 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)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
-
- global_variables.must_update_buffer_materials = true; //normally there are none
- }
-
- global_variables.variables[p_name] = gv;
-}
-
-void RendererStorageRD::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
- return;
- }
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
-
- if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
- } else {
- global_variables.must_update_texture_materials = true;
- }
-
- global_variables.variables.erase(p_name);
-}
-
-Vector<StringName> RendererStorageRD::global_variable_get_list() const {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
- }
-
- const StringName *K = nullptr;
- Vector<StringName> names;
- while ((K = global_variables.variables.next(K))) {
- names.push_back(*K);
- }
- names.sort_custom<StringName::AlphCompare>();
- return names;
-}
-
-void RendererStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
- gv.value = p_value;
- if (gv.override.get_type() == Variant::NIL) {
- if (gv.buffer_index >= 0) {
- //buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- } else {
- //texture
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.get_or_null(E->get());
- ERR_CONTINUE(!material);
- _material_queue_update(material, false, true);
- }
- }
- }
-}
-
-void RendererStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
- return; //variable may not exist
- }
-
- ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
-
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
-
- gv.override = p_value;
-
- if (gv.buffer_index >= 0) {
- //buffer
- if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- } else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
- }
-
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- } else {
- //texture
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
- Material *material = material_owner.get_or_null(E->get());
- ERR_CONTINUE(!material);
- _material_queue_update(material, false, true);
- }
- }
-}
-
-Variant RendererStorageRD::global_variable_get(const StringName &p_name) const {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
- }
-
- if (!global_variables.variables.has(p_name)) {
- return Variant();
- }
-
- return global_variables.variables[p_name].value;
-}
-
-RS::GlobalVariableType RendererStorageRD::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
- return RS::GLOBAL_VAR_TYPE_MAX;
- }
-
- return global_variables.variables[p_name].type;
-}
-
-RS::GlobalVariableType RendererStorageRD::global_variable_get_type(const StringName &p_name) const {
- if (!Engine::get_singleton()->is_editor_hint()) {
- ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
- }
-
- return global_variable_get_type_internal(p_name);
-}
-
-void RendererStorageRD::global_variables_load_settings(bool p_load_textures) {
- List<PropertyInfo> settings;
- ProjectSettings::get_singleton()->get_property_list(&settings);
-
- for (const PropertyInfo &E : settings) {
- if (E.name.begins_with("shader_globals/")) {
- StringName name = E.name.get_slice("/", 1);
- Dictionary d = ProjectSettings::get_singleton()->get(E.name);
-
- ERR_CONTINUE(!d.has("type"));
- ERR_CONTINUE(!d.has("value"));
-
- String type = d["type"];
-
- static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
- "bool",
- "bvec2",
- "bvec3",
- "bvec4",
- "int",
- "ivec2",
- "ivec3",
- "ivec4",
- "rect2i",
- "uint",
- "uvec2",
- "uvec3",
- "uvec4",
- "float",
- "vec2",
- "vec3",
- "vec4",
- "color",
- "rect2",
- "mat2",
- "mat3",
- "mat4",
- "transform_2d",
- "transform",
- "sampler2D",
- "sampler2DArray",
- "sampler3D",
- "samplerCube",
- };
-
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
-
- for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
- if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
- break;
- }
- }
-
- ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
-
- Variant value = d["value"];
-
- if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //textire
- if (!p_load_textures) {
- value = RID();
- continue;
- }
-
- String path = value;
- RES resource = ResourceLoader::load(path);
- ERR_CONTINUE(resource.is_null());
- value = resource;
- }
-
- if (global_variables.variables.has(name)) {
- //has it, update it
- global_variable_set(name, value);
- } else {
- global_variable_add(name, gvtype, value);
- }
- }
- }
-}
-
-void RendererStorageRD::global_variables_clear() {
- global_variables.variables.clear(); //not right but for now enough
-}
-
-RID RendererStorageRD::global_variables_get_storage_buffer() const {
- return global_variables.buffer;
-}
-
-int32_t RendererStorageRD::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
- ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
- return pos;
-}
-
-void RendererStorageRD::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
- if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
- }
- global_variables.instance_buffer_pos.erase(p_instance);
-}
-
-void RendererStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
- return; //just not allocated, ignore
- }
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
-
- if (pos < 0) {
- return; //again, not allocated, ignore
- }
- ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
-
- ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
- ShaderLanguage::TYPE_MAX, //nil
- ShaderLanguage::TYPE_BOOL, //bool
- ShaderLanguage::TYPE_INT, //int
- ShaderLanguage::TYPE_FLOAT, //float
- ShaderLanguage::TYPE_MAX, //string
- ShaderLanguage::TYPE_VEC2, //vec2
- ShaderLanguage::TYPE_IVEC2, //vec2i
- ShaderLanguage::TYPE_VEC4, //rect2
- ShaderLanguage::TYPE_IVEC4, //rect2i
- ShaderLanguage::TYPE_VEC3, // vec3
- ShaderLanguage::TYPE_IVEC3, //vec3i
- ShaderLanguage::TYPE_MAX, //xform2d not supported here
- ShaderLanguage::TYPE_VEC4, //plane
- ShaderLanguage::TYPE_VEC4, //quat
- ShaderLanguage::TYPE_MAX, //aabb not supported here
- ShaderLanguage::TYPE_MAX, //basis not supported here
- ShaderLanguage::TYPE_MAX, //xform not supported here
- ShaderLanguage::TYPE_VEC4 //color
- };
-
- ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
-
- ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
-
- pos += p_index;
-
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
- _global_variable_mark_buffer_dirty(pos, 1);
-}
-
-void RendererStorageRD::_update_global_variables() {
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
- // 25% of regions dirty, just update all buffer
- RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
- } else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
-
- for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
-
- global_variables.buffer_dirty_regions[i] = false;
- }
- }
- }
-
- global_variables.buffer_dirty_region_count = 0;
- }
-
- if (global_variables.must_update_buffer_materials) {
- // only happens in the case of a buffer variable added or removed,
- // so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
- Material *material = material_owner.get_or_null(E);
- ERR_CONTINUE(!material); //wtf
-
- _material_queue_update(material, true, false);
- }
-
- global_variables.must_update_buffer_materials = false;
- }
-
- if (global_variables.must_update_texture_materials) {
- // only happens in the case of a buffer variable added or removed,
- // so not often.
- for (const RID &E : global_variables.materials_using_texture) {
- Material *material = material_owner.get_or_null(E);
- ERR_CONTINUE(!material); //wtf
-
- _material_queue_update(material, false, true);
- }
-
- global_variables.must_update_texture_materials = false;
- }
-}
-
void RendererStorageRD::update_dirty_resources() {
- _update_global_variables(); //must do before materials, so it can queue them for update
- _update_queued_materials();
+ RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
+ RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
_update_dirty_multimeshes();
_update_dirty_skeletons();
RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas();
@@ -7710,24 +5428,10 @@ bool RendererStorageRD::free(RID p_rid) {
RendererRD::TextureStorage::get_singleton()->texture_free(p_rid);
} else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid);
- } else if (shader_owner.owns(p_rid)) {
- Shader *shader = shader_owner.get_or_null(p_rid);
- //make material unreference this
- while (shader->owners.size()) {
- material_set_shader(shader->owners.front()->get()->self, RID());
- }
- //clear data if exists
- if (shader->data) {
- memdelete(shader->data);
- }
- shader_owner.free(p_rid);
-
- } else if (material_owner.owns(p_rid)) {
- Material *material = material_owner.get_or_null(p_rid);
- material_set_shader(p_rid, RID()); //clean up shader
- material->dependency.deleted_notify(p_rid);
-
- material_owner.free(p_rid);
+ } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
+ RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid);
+ } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) {
+ RendererRD::MaterialStorage::get_singleton()->material_free(p_rid);
} else if (mesh_owner.owns(p_rid)) {
mesh_clear(p_rid);
mesh_set_shadow_mesh(p_rid, RID());
@@ -7902,20 +5606,7 @@ RendererStorageRD::RendererStorageRD() {
base_singleton = this;
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
- for (int i = 0; i < SHADER_TYPE_MAX; i++) {
- shader_data_request_func[i] = nullptr;
- }
-
- static_assert(sizeof(GlobalVariables::Value) == 16);
-
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//default samplers
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
@@ -8144,8 +5835,8 @@ RendererStorageRD::RendererStorageRD() {
particles_modes.push_back("");
particles_shader.shader.initialize(particles_modes, String());
}
- shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
- material_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+ RendererRD::MaterialStorage::get_singleton()->shader_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+ RendererRD::MaterialStorage::get_singleton()->material_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -8209,9 +5900,9 @@ RendererStorageRD::RendererStorageRD() {
{
// default material and shader for particles shader
- particles_shader.default_shader = shader_allocate();
- shader_initialize(particles_shader.default_shader);
- shader_set_code(particles_shader.default_shader, R"(
+ particles_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(particles_shader.default_shader);
+ material_storage->shader_set_code(particles_shader.default_shader, R"(
// Default particles shader.
shader_type particles;
@@ -8220,11 +5911,11 @@ void process() {
COLOR = vec4(1.0);
}
)");
- particles_shader.default_material = material_allocate();
- material_initialize(particles_shader.default_material);
- material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+ particles_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(particles_shader.default_material);
+ material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
- ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES);
+ ParticlesMaterialData *md = (ParticlesMaterialData *)material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES);
particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -8254,7 +5945,7 @@ void process() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(global_variables_get_storage_buffer());
+ u.append_id(material_storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -8332,10 +6023,7 @@ void process() {
}
RendererStorageRD::~RendererStorageRD() {
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- RD::get_singleton()->free(global_variables.buffer);
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//def samplers
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
@@ -8363,8 +6051,8 @@ RendererStorageRD::~RendererStorageRD() {
skeleton_shader.shader.version_free(skeleton_shader.version);
- RenderingServer::get_singleton()->free(particles_shader.default_material);
- RenderingServer::get_singleton()->free(particles_shader.default_shader);
+ material_storage->material_free(particles_shader.default_material);
+ material_storage->shader_free(particles_shader.default_shader);
RD::get_singleton()->free(default_rd_storage_buffer);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 3aa475b34d..42d4141f9c 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -42,6 +42,8 @@
#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -127,61 +129,6 @@ public:
}
}
- enum ShaderType {
- SHADER_TYPE_2D,
- SHADER_TYPE_3D,
- SHADER_TYPE_PARTICLES,
- SHADER_TYPE_SKY,
- SHADER_TYPE_FOG,
- SHADER_TYPE_MAX
- };
-
- struct ShaderData {
- virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
-
- virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_param_texture(const StringName &p_param) const = 0;
- virtual bool is_animated() const = 0;
- virtual bool casts_shadows() const = 0;
- virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
-
- virtual ~ShaderData() {}
- };
-
- typedef ShaderData *(*ShaderDataRequestFunction)();
-
- struct MaterialData {
- void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
-
- virtual void set_render_priority(int p_priority) = 0;
- virtual void set_next_pass(RID p_pass) = 0;
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
- virtual ~MaterialData();
-
- //to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void free_parameters_uniform_set(RID p_uniform_set);
-
- private:
- friend class RendererStorageRD;
- RID self;
- List<RID>::Element *global_buffer_E = nullptr;
- List<RID>::Element *global_texture_E = nullptr;
- uint64_t global_textures_pass = 0;
- Map<StringName, uint64_t> used_global_textures;
-
- //internally by update_parameters_uniform_set
- Vector<uint8_t> ubo_data;
- RID uniform_buffer;
- Vector<RID> texture_cache;
- };
- typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
- static void _material_uniform_set_erased(void *p_material);
-
enum DefaultRDBuffer {
DEFAULT_RD_BUFFER_VERTEX,
DEFAULT_RD_BUFFER_NORMAL,
@@ -205,50 +152,6 @@ private:
RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID default_rd_storage_buffer;
- /* SHADER */
-
- struct Material;
-
- struct Shader {
- ShaderData *data;
- String code;
- ShaderType type;
- Map<StringName, Map<int, RID>> default_texture_parameter;
- Set<Material *> owners;
- };
-
- ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Shader, true> shader_owner;
-
- /* Material */
-
- struct Material {
- RID self;
- MaterialData *data = nullptr;
- Shader *shader = nullptr;
- //shortcut to shader data and type
- ShaderType shader_type = SHADER_TYPE_MAX;
- uint32_t shader_id = 0;
- bool uniform_dirty = false;
- bool texture_dirty = false;
- Map<StringName, Variant> params;
- int32_t priority = 0;
- RID next_pass;
- SelfList<Material> update_element;
-
- Dependency dependency;
-
- Material() :
- update_element(this) {}
- };
-
- MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
- mutable RID_Owner<Material, true> material_owner;
-
- SelfList<Material>::List material_update_list;
- void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
- void _update_queued_materials();
-
/* Mesh */
struct MeshInstance;
@@ -714,7 +617,7 @@ private:
Particles *particle_update_list = nullptr;
- struct ParticlesShaderData : public ShaderData {
+ struct ParticlesShaderData : public RendererRD::ShaderData {
bool valid;
RID version;
bool uses_collision = false;
@@ -740,7 +643,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
@@ -751,12 +654,12 @@ private:
virtual ~ParticlesShaderData();
};
- ShaderData *_create_particles_shader_func();
- static RendererStorageRD::ShaderData *_create_particles_shader_funcs() {
+ RendererRD::ShaderData *_create_particles_shader_func();
+ static RendererRD::ShaderData *_create_particles_shader_funcs() {
return base_singleton->_create_particles_shader_func();
}
- struct ParticlesMaterialData : public MaterialData {
+ struct ParticlesMaterialData : public RendererRD::MaterialData {
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
@@ -766,8 +669,8 @@ private:
virtual ~ParticlesMaterialData();
};
- MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
- static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+ RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+ static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) {
return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
}
@@ -1054,72 +957,6 @@ private:
RID pipelines[SHADER_MAX];
} rt_sdf;
- /* GLOBAL SHADER VARIABLES */
-
- struct GlobalVariables {
- enum {
- BUFFER_DIRTY_REGION_SIZE = 1024
- };
- struct Variable {
- Set<RID> texture_materials; // materials using this
-
- RS::GlobalVariableType type;
- Variant value;
- Variant override;
- int32_t buffer_index; //for vectors
- int32_t buffer_elements; //for vectors
- };
-
- HashMap<StringName, Variable> variables;
-
- struct Value {
- float x;
- float y;
- float z;
- float w;
- };
-
- struct ValueInt {
- int32_t x;
- int32_t y;
- int32_t z;
- int32_t w;
- };
-
- struct ValueUInt {
- uint32_t x;
- uint32_t y;
- uint32_t z;
- uint32_t w;
- };
-
- struct ValueUsage {
- uint32_t elements = 0;
- };
-
- List<RID> materials_using_buffer;
- List<RID> materials_using_texture;
-
- RID buffer;
- Value *buffer_values;
- ValueUsage *buffer_usage;
- bool *buffer_dirty_regions;
- uint32_t buffer_dirty_region_count = 0;
-
- uint32_t buffer_size;
-
- bool must_update_texture_materials = false;
- bool must_update_buffer_materials = false;
-
- HashMap<RID, int32_t> instance_buffer_pos;
-
- } global_variables;
-
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
-
- void _update_global_variables();
/* EFFECTS */
EffectsRD *effects = nullptr;
@@ -1138,58 +975,6 @@ public:
void sampler_rd_set_default(float p_mipmap_bias);
- /* SHADER API */
-
- RID shader_allocate();
- void shader_initialize(RID p_shader);
-
- void shader_set_code(RID p_shader, const String &p_code);
- String shader_get_code(RID p_shader) const;
- void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
-
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
- Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
- void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
-
- virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const;
-
- /* COMMON MATERIAL API */
-
- RID material_allocate();
- void material_initialize(RID p_material);
-
- void material_set_shader(RID p_material, RID p_shader);
-
- void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value);
- Variant material_get_param(RID p_material, const StringName &p_param) const;
-
- void material_set_next_pass(RID p_material, RID p_next_material);
- void material_set_render_priority(RID p_material, int priority);
-
- bool material_is_animated(RID p_material);
- bool material_casts_shadows(RID p_material);
-
- void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
-
- void material_update_dependency(RID p_material, DependencyTracker *p_instance);
-
- void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
-
- _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
- return material->shader_id;
- }
-
- _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
- Material *material = material_owner.get_or_null(p_material);
- if (!material || material->shader_type != p_shader_type) {
- return nullptr;
- } else {
- return material->data;
- }
- }
-
/* MESH API */
RID mesh_allocate();
@@ -1972,27 +1757,6 @@ public:
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
- /* GLOBAL VARIABLES API */
-
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
- virtual void global_variable_remove(const StringName &p_name);
- virtual Vector<StringName> global_variable_get_list() const;
-
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value);
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value);
- virtual Variant global_variable_get(const StringName &p_name) const;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
-
- virtual void global_variables_load_settings(bool p_load_textures = true);
- virtual void global_variables_clear();
-
- virtual int32_t global_variables_instance_allocate(RID p_instance);
- virtual void global_variables_instance_free(RID p_instance);
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value);
-
- RID global_variables_get_storage_buffer() const;
-
/* RENDER TARGET API */
RID render_target_create();
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 4e6e50bc44..abe1a09b06 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -499,14 +499,14 @@ layout(location = 1) out uvec2 voxel_gi_buffer;
#endif //MODE_RENDER_NORMAL
#else // RENDER DEPTH
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
layout(location = 0) out vec4 frag_color;
-#endif // MODE_MULTIPLE_RENDER_TARGETS
+#endif // MODE_SEPARATE_SPECULAR
#endif // RENDER DEPTH
@@ -1966,7 +1966,7 @@ void main() {
//restore fog
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
diffuse_buffer = vec4(albedo.rgb, 0.0);
@@ -1984,7 +1984,7 @@ void main() {
diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
-#else //MODE_MULTIPLE_RENDER_TARGETS
+#else //MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
frag_color = vec4(albedo, alpha);
@@ -1996,7 +1996,7 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
-#endif //MODE_MULTIPLE_RENDER_TARGETS
+#endif //MODE_SEPARATE_SPECULAR
#endif //MODE_RENDER_DEPTH
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
new file mode 100644
index 0000000000..9e3d124bbb
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -0,0 +1,2392 @@
+/*************************************************************************/
+/* material_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "material_storage.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/io/resource_loader.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+///////////////////////////////////////////////////////////////////////////
+// UBI helper functions
+
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = (r[i] != 0) ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ bool v = value;
+ gui[0] = v ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 2 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v & 1 ? 1 : 0;
+ gui[1] = v & 2 ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 3 * p_array_size;
+
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i] ? 1 : 0;
+ gui[j + 1] = r[i + 1] ? 1 : 0;
+ gui[j + 2] = r[i + 2] ? 1 : 0;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ const PackedInt32Array &ba = value;
+ int s = ba.size();
+ const int *r = ba.ptr();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i] ? 1 : 0;
+ gui[i + 1] = r[i + 1] ? 1 : 0;
+ gui[i + 2] = r[i + 2] ? 1 : 0;
+ gui[i + 3] = r[i + 3] ? 1 : 0;
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } else {
+ int v = value;
+ gui[0] = (v & 1) ? 1 : 0;
+ gui[1] = (v & 2) ? 1 : 0;
+ gui[2] = (v & 4) ? 1 : 0;
+ gui[3] = (v & 8) ? 1 : 0;
+ }
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int32_t *gui = (int32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ const int *r = iv.ptr();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ int v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 2 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 3 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ Vector<int> iv = value;
+ int s = iv.size();
+ uint32_t *gui = (uint32_t *)data;
+
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+ int count = 4 * p_array_size;
+
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i];
+ } else {
+ gui[j] = 0;
+ }
+ gui[j + 1] = 0; // ignored
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ float v = value;
+ gui[0] = v;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedVector2Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector2 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedVector3Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ gui[j] = a[i].x;
+ gui[j + 1] = a[i].y;
+ gui[j + 2] = a[i].z;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
+ }
+ } else {
+ Vector3 v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ }
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ if (value.get_type() == Variant::PACKED_COLOR_ARRAY) {
+ const PackedColorArray &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
+ if (i < s) {
+ Color color = a[i];
+ if (p_linear_color) {
+ color = color.to_linear();
+ }
+ gui[j] = color.r;
+ gui[j + 1] = color.g;
+ gui[j + 2] = color.b;
+ gui[j + 3] = color.a;
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ gui[j + 3] = 0;
+ }
+ }
+ } else {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+ int count = 4 * p_array_size;
+
+ for (int i = 0; i < count; i += 4) {
+ if (i + 3 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
+ }
+ }
+ } else {
+ if (value.get_type() == Variant::COLOR) {
+ Color v = value;
+
+ if (p_linear_color) {
+ v = v.to_linear();
+ }
+
+ gui[0] = v.r;
+ gui[1] = v.g;
+ gui[2] = v.b;
+ gui[3] = v.a;
+ } else if (value.get_type() == Variant::RECT2) {
+ Rect2 v = value;
+
+ gui[0] = v.position.x;
+ gui[1] = v.position.y;
+ gui[2] = v.size.x;
+ gui[3] = v.size.y;
+ } else if (value.get_type() == Variant::QUATERNION) {
+ Quaternion v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
+ } else {
+ Plane v = value;
+
+ gui[0] = v.normal.x;
+ gui[1] = v.normal.y;
+ gui[2] = v.normal.z;
+ gui[3] = v.d;
+ }
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 4; i += 4, j += 8) {
+ if (i + 3 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+
+ gui[j + 4] = a[i + 2];
+ gui[j + 5] = a[i + 3];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
+ gui[j + 6] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ }
+ } else {
+ Transform2D v = value;
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = v.elements[0][0];
+ gui[1] = v.elements[0][1];
+ gui[2] = 0; // ignored
+ gui[3] = 0; // ignored
+
+ gui[4] = v.elements[1][0];
+ gui[5] = v.elements[1][1];
+ gui[6] = 0; // ignored
+ gui[7] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0, j = 0; i < p_array_size * 9; i += 9, j += 12) {
+ if (i + 8 < s) {
+ gui[j] = a[i];
+ gui[j + 1] = a[i + 1];
+ gui[j + 2] = a[i + 2];
+
+ gui[j + 4] = a[i + 3];
+ gui[j + 5] = a[i + 4];
+ gui[j + 6] = a[i + 5];
+
+ gui[j + 8] = a[i + 6];
+ gui[j + 9] = a[i + 7];
+ gui[j + 10] = a[i + 8];
+ } else {
+ gui[j] = 1;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+
+ gui[j + 4] = 0;
+ gui[j + 5] = 1;
+ gui[j + 6] = 0;
+
+ gui[j + 8] = 0;
+ gui[j + 9] = 0;
+ gui[j + 10] = 1;
+ }
+ gui[j + 3] = 0; // ignored
+ gui[j + 7] = 0; // ignored
+ gui[j + 11] = 0; // ignored
+ }
+ } else {
+ Basis v = value;
+ gui[0] = v.elements[0][0];
+ gui[1] = v.elements[1][0];
+ gui[2] = v.elements[2][0];
+ gui[3] = 0; // ignored
+
+ gui[4] = v.elements[0][1];
+ gui[5] = v.elements[1][1];
+ gui[6] = v.elements[2][1];
+ gui[7] = 0; // ignored
+
+ gui[8] = v.elements[0][2];
+ gui[9] = v.elements[1][2];
+ gui[10] = v.elements[2][2];
+ gui[11] = 0; // ignored
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ float *gui = (float *)data;
+
+ if (p_array_size > 0) {
+ const PackedFloat32Array &a = value;
+ int s = a.size();
+
+ for (int i = 0; i < p_array_size * 16; i += 16) {
+ if (i + 15 < s) {
+ gui[i] = a[i];
+ gui[i + 1] = a[i + 1];
+ gui[i + 2] = a[i + 2];
+ gui[i + 3] = a[i + 3];
+
+ gui[i + 4] = a[i + 4];
+ gui[i + 5] = a[i + 5];
+ gui[i + 6] = a[i + 6];
+ gui[i + 7] = a[i + 7];
+
+ gui[i + 8] = a[i + 8];
+ gui[i + 9] = a[i + 9];
+ gui[i + 10] = a[i + 10];
+ gui[i + 11] = a[i + 11];
+
+ gui[i + 12] = a[i + 12];
+ gui[i + 13] = a[i + 13];
+ gui[i + 14] = a[i + 14];
+ gui[i + 15] = a[i + 15];
+ } else {
+ gui[i] = 1;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+
+ gui[i + 4] = 0;
+ gui[i + 5] = 1;
+ gui[i + 6] = 0;
+ gui[i + 7] = 0;
+
+ gui[i + 8] = 0;
+ gui[i + 9] = 0;
+ gui[i + 10] = 1;
+ gui[i + 11] = 0;
+
+ gui[i + 12] = 0;
+ gui[i + 13] = 0;
+ gui[i + 14] = 0;
+ gui[i + 15] = 1;
+ }
+ }
+ } else {
+ Transform3D v = value;
+ gui[0] = v.basis.elements[0][0];
+ gui[1] = v.basis.elements[1][0];
+ gui[2] = v.basis.elements[2][0];
+ gui[3] = 0;
+
+ gui[4] = v.basis.elements[0][1];
+ gui[5] = v.basis.elements[1][1];
+ gui[6] = v.basis.elements[2][1];
+ gui[7] = 0;
+
+ gui[8] = v.basis.elements[0][2];
+ gui[9] = v.basis.elements[1][2];
+ gui[10] = v.basis.elements[2][2];
+ gui[11] = 0;
+
+ gui[12] = v.origin.x;
+ gui[13] = v.origin.y;
+ gui[14] = v.origin.z;
+ gui[15] = 1;
+ }
+ } break;
+ default: {
+ }
+ }
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ uint32_t *gui = (uint32_t *)data;
+ *gui = value[0].boolean ? 1 : 0;
+ } break;
+ case ShaderLanguage::TYPE_BVEC2: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC3: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+ gui[2] = value[2].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_BVEC4: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].boolean ? 1 : 0;
+ gui[1] = value[1].boolean ? 1 : 0;
+ gui[2] = value[2].boolean ? 1 : 0;
+ gui[3] = value[3].boolean ? 1 : 0;
+
+ } break;
+ case ShaderLanguage::TYPE_INT: {
+ int32_t *gui = (int32_t *)data;
+ gui[0] = value[0].sint;
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC2: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC3: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_IVEC4: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].sint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UINT: {
+ uint32_t *gui = (uint32_t *)data;
+ gui[0] = value[0].uint;
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC2: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC3: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].uint;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_UVEC4: {
+ int32_t *gui = (int32_t *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].uint;
+ }
+ } break;
+ case ShaderLanguage::TYPE_FLOAT: {
+ float *gui = (float *)data;
+ gui[0] = value[0].real;
+
+ } break;
+ case ShaderLanguage::TYPE_VEC2: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 2; i++) {
+ gui[i] = value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC3: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 3; i++) {
+ gui[i] = value[i].real;
+ }
+
+ } break;
+ case ShaderLanguage::TYPE_VEC4: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 4; i++) {
+ gui[i] = value[i].real;
+ }
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ float *gui = (float *)data;
+
+ //in std140 members of mat2 are treated as vec4s
+ gui[0] = value[0].real;
+ gui[1] = value[1].real;
+ gui[2] = 0;
+ gui[3] = 0;
+ gui[4] = value[2].real;
+ gui[5] = value[3].real;
+ gui[6] = 0;
+ gui[7] = 0;
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ float *gui = (float *)data;
+
+ gui[0] = value[0].real;
+ gui[1] = value[1].real;
+ gui[2] = value[2].real;
+ gui[3] = 0;
+ gui[4] = value[3].real;
+ gui[5] = value[4].real;
+ gui[6] = value[5].real;
+ gui[7] = 0;
+ gui[8] = value[6].real;
+ gui[9] = value[7].real;
+ gui[10] = value[8].real;
+ gui[11] = 0;
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ float *gui = (float *)data;
+
+ for (int i = 0; i < 16; i++) {
+ gui[i] = value[i].real;
+ }
+ } break;
+ default: {
+ }
+ }
+}
+
+_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, int p_array_size, uint8_t *data) {
+ if (p_array_size <= 0) {
+ p_array_size = 1;
+ }
+
+ switch (type) {
+ case ShaderLanguage::TYPE_BOOL:
+ case ShaderLanguage::TYPE_INT:
+ case ShaderLanguage::TYPE_UINT:
+ case ShaderLanguage::TYPE_FLOAT: {
+ memset(data, 0, 4 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_BVEC2:
+ case ShaderLanguage::TYPE_IVEC2:
+ case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_VEC2: {
+ memset(data, 0, 8 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_BVEC3:
+ case ShaderLanguage::TYPE_IVEC3:
+ case ShaderLanguage::TYPE_UVEC3:
+ case ShaderLanguage::TYPE_VEC3:
+ case ShaderLanguage::TYPE_BVEC4:
+ case ShaderLanguage::TYPE_IVEC4:
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_VEC4: {
+ memset(data, 0, 16 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT2: {
+ memset(data, 0, 32 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT3: {
+ memset(data, 0, 48 * p_array_size);
+ } break;
+ case ShaderLanguage::TYPE_MAT4: {
+ memset(data, 0, 64 * p_array_size);
+ } break;
+
+ default: {
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialData
+
+void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ bool uses_global_buffer = false;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
+ if (E.value.order < 0) {
+ continue; // texture, does not go here
+ }
+
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue; //instance uniforms don't appear in the buffer
+ }
+
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+ //this is a global variable, get the index to it
+ GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ uint32_t index = 0;
+ if (gv) {
+ index = gv->buffer_index;
+ } else {
+ WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
+ }
+
+ uint32_t offset = p_uniform_offsets[E.value.order];
+ uint32_t *intptr = (uint32_t *)&p_buffer[offset];
+ *intptr = index;
+ uses_global_buffer = true;
+ continue;
+ }
+
+ //regular uniform
+ uint32_t offset = p_uniform_offsets[E.value.order];
+#ifdef DEBUG_ENABLED
+ uint32_t size = 0U;
+ // The following code enforces a 16-byte alignment of uniform arrays.
+ if (E.value.array_size > 0) {
+ size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
+ int m = (16 * E.value.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ } else {
+ size = ShaderLanguage::get_datatype_size(E.value.type);
+ }
+ ERR_CONTINUE(offset + size > p_buffer_size);
+#endif
+ uint8_t *data = &p_buffer[offset];
+ const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
+
+ if (V) {
+ //user provided
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
+
+ } else if (E.value.default_value.size()) {
+ //default value
+ _fill_std140_ubo_value(E.value.type, E.value.default_value, data);
+ //value=E.value.default_value;
+ } else {
+ //zero because it was not provided
+ if (E.value.type == ShaderLanguage::TYPE_VEC4 && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
+ //colors must be set as black, with alpha as 1.0
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
+ } else {
+ //else just zero it out
+ _fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
+ }
+ }
+ }
+
+ if (uses_global_buffer != (global_buffer_E != nullptr)) {
+ if (uses_global_buffer) {
+ global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ } else {
+ material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ global_buffer_E = nullptr;
+ }
+ }
+}
+
+MaterialData::~MaterialData() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ if (global_buffer_E) {
+ //unregister global buffers
+ material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ }
+
+ if (global_texture_E) {
+ //unregister global textures
+
+ for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ //unregister material from those using global textures
+ material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ }
+
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ }
+}
+
+void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+#ifdef TOOLS_ENABLED
+ Texture *roughness_detect_texture = nullptr;
+ RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
+ Texture *normal_detect_texture = nullptr;
+#endif
+
+ bool uses_global_textures = false;
+ global_textures_pass++;
+
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const StringName &uniform_name = p_texture_uniforms[i].name;
+ int uniform_array_size = p_texture_uniforms[i].array_size;
+
+ Vector<RID> textures;
+
+ if (p_texture_uniforms[i].global) {
+ uses_global_textures = true;
+
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ if (v) {
+ if (v->buffer_index >= 0) {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
+
+ } else {
+ Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
+ if (!E) {
+ E = used_global_textures.insert(uniform_name, global_textures_pass);
+ v->texture_materials.insert(self);
+ } else {
+ E->get() = global_textures_pass;
+ }
+
+ textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
+ }
+
+ } else {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
+ }
+ } else {
+ const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
+ if (V) {
+ if (V->get().is_array()) {
+ Array array = (Array)V->get();
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < array.size(); j++) {
+ textures.push_back(array[j]);
+ }
+ } else {
+ if (array.size() > 0) {
+ textures.push_back(array[0]);
+ }
+ }
+ } else {
+ textures.push_back(V->get());
+ }
+ }
+
+ if (uniform_array_size > 0) {
+ if (textures.size() < uniform_array_size) {
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ if (W && W->get().has(j)) {
+ textures.push_back(W->get()[j]);
+ } else {
+ textures.push_back(RID());
+ }
+ }
+ }
+ } else if (textures.is_empty()) {
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ if (W && W->get().has(0)) {
+ textures.push_back(W->get()[0]);
+ }
+ }
+ }
+
+ RID rd_texture;
+
+ if (textures.is_empty()) {
+ //check default usage
+ switch (p_texture_uniforms[i].type) {
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER2D: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ default: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ } break;
+ }
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ } break;
+ default: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ } break;
+ }
+ } break;
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER3D: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ } break;
+
+ default: {
+ }
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ if (uniform_array_size > 0) {
+ for (int j = 0; j < uniform_array_size; j++) {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ p_textures[k++] = rd_texture;
+ }
+ } else {
+ bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO);
+
+ for (int j = 0; j < textures.size(); j++) {
+ Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
+
+ if (tex) {
+ rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+#ifdef TOOLS_ENABLED
+ if (tex->detect_3d_callback && p_use_linear_color) {
+ tex->detect_3d_callback(tex->detect_3d_callback_ud);
+ }
+ 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)) {
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) {
+ normal_detect_texture = tex;
+ }
+ tex->detect_normal_callback(tex->detect_normal_callback_ud);
+ }
+ 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)) {
+ //find the normal texture
+ roughness_detect_texture = tex;
+ roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R);
+ }
+#endif
+ }
+ if (rd_texture.is_null()) {
+ rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ }
+#ifdef TOOLS_ENABLED
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
+ roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
+ }
+#endif
+ p_textures[k++] = rd_texture;
+ }
+ }
+ }
+ {
+ //for textures no longer used, unregister them
+ List<Map<StringName, uint64_t>::Element *> to_delete;
+ for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
+ if (E->get() != global_textures_pass) {
+ to_delete.push_back(E);
+
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key());
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ }
+
+ while (to_delete.front()) {
+ used_global_textures.erase(to_delete.front()->get());
+ to_delete.pop_front();
+ }
+ //handle registering/unregistering global textures
+ if (uses_global_textures != (global_texture_E != nullptr)) {
+ if (uses_global_textures) {
+ global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ } else {
+ material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ global_texture_E = nullptr;
+ }
+ }
+ }
+}
+
+void MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+ if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(p_uniform_set);
+ }
+}
+
+bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+ if ((uint32_t)ubo_data.size() != p_ubo_size) {
+ p_uniform_dirty = true;
+ if (uniform_buffer.is_valid()) {
+ RD::get_singleton()->free(uniform_buffer);
+ uniform_buffer = RID();
+ }
+
+ ubo_data.resize(p_ubo_size);
+ if (ubo_data.size()) {
+ uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
+ memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
+ }
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ //check whether buffer changed
+ if (p_uniform_dirty && ubo_data.size()) {
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
+ }
+
+ uint32_t tex_uniform_count = 0U;
+ for (int i = 0; i < p_texture_uniforms.size(); i++) {
+ tex_uniform_count += uint32_t(p_texture_uniforms[i].array_size > 0 ? p_texture_uniforms[i].array_size : 1);
+ }
+
+ if ((uint32_t)texture_cache.size() != tex_uniform_count || p_textures_dirty) {
+ texture_cache.resize(tex_uniform_count);
+ p_textures_dirty = true;
+
+ //clear previous uniform set
+ if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, nullptr, nullptr);
+ RD::get_singleton()->free(uniform_set);
+ uniform_set = RID();
+ }
+ }
+
+ if (p_textures_dirty && tex_uniform_count) {
+ update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
+ }
+
+ if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ // This material does not require an uniform set, so don't create it.
+ return false;
+ }
+
+ if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //no reason to update uniform set, only UBO (or nothing) was needed to update
+ return false;
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ if (p_ubo_size) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.append_id(uniform_buffer);
+ uniforms.push_back(u);
+ }
+
+ const RID *textures = texture_cache.ptrw();
+ for (int i = 0, k = 0; i < p_texture_uniforms.size(); i++) {
+ const int array_size = p_texture_uniforms[i].array_size;
+
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1 + k;
+ if (array_size > 0) {
+ for (int j = 0; j < array_size; j++) {
+ u.append_id(textures[k++]);
+ }
+ } else {
+ u.append_id(textures[k++]);
+ }
+ uniforms.push_back(u);
+ }
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_shader_uniform_set);
+
+ RD::get_singleton()->uniform_set_set_invalidation_callback(uniform_set, MaterialStorage::_material_uniform_set_erased, &self);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// MaterialStorage
+
+MaterialStorage *MaterialStorage::singleton = nullptr;
+
+MaterialStorage *MaterialStorage::get_singleton() {
+ return singleton;
+}
+
+MaterialStorage::MaterialStorage() {
+ singleton = this;
+
+ for (int i = 0; i < SHADER_TYPE_MAX; i++) {
+ shader_data_request_func[i] = nullptr;
+ }
+
+ static_assert(sizeof(GlobalVariables::Value) == 16);
+
+ global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
+ memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
+ global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+}
+
+MaterialStorage::~MaterialStorage() {
+ memdelete_arr(global_variables.buffer_values);
+ memdelete_arr(global_variables.buffer_usage);
+ memdelete_arr(global_variables.buffer_dirty_regions);
+ RD::get_singleton()->free(global_variables.buffer);
+
+ singleton = nullptr;
+}
+
+/* GLOBAL VARIABLE API */
+
+int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+ int32_t idx = 0;
+ while (idx + p_elements <= global_variables.buffer_size) {
+ if (global_variables.buffer_usage[idx].elements == 0) {
+ bool valid = true;
+ for (uint32_t i = 1; i < p_elements; i++) {
+ if (global_variables.buffer_usage[idx + i].elements > 0) {
+ valid = false;
+ idx += i + global_variables.buffer_usage[idx + i].elements;
+ break;
+ }
+ }
+
+ if (!valid) {
+ continue; //if not valid, idx is in new position
+ }
+
+ return idx;
+ } else {
+ idx += global_variables.buffer_usage[idx].elements;
+ }
+ }
+
+ return -1;
+}
+
+void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+ switch (p_type) {
+ case RS::GLOBAL_VAR_TYPE_BOOL: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ bool b = p_value;
+ bv.x = b ? 1.0 : 0.0;
+ bv.y = 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = (bvec & 8) ? 1.0 : 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_INT: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ int32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC2: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC3: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC4: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2I: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Rect2i v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UINT: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ uint32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC2: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC3: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC4: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_FLOAT: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ float v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector2 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector3 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Plane v = p_value;
+ bv.x = v.normal.x;
+ bv.y = v.normal.y;
+ bv.z = v.normal.z;
+ bv.w = v.d;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_COLOR: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Color v = p_value;
+ bv.x = v.r;
+ bv.y = v.g;
+ bv.z = v.b;
+ bv.w = v.a;
+
+ GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ v = v.to_linear();
+ bv_linear.x = v.r;
+ bv_linear.y = v.g;
+ bv_linear.z = v.b;
+ bv_linear.w = v.a;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Rect2 v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT2: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Vector<float> m2 = p_value;
+ if (m2.size() < 4) {
+ m2.resize(4);
+ }
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = m2[2];
+ bv[1].y = m2[3];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT3: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Basis v = p_value;
+ bv[0].x = v.elements[0][0];
+ bv[0].y = v.elements[1][0];
+ bv[0].z = v.elements[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.elements[0][1];
+ bv[1].y = v.elements[1][1];
+ bv[1].z = v.elements[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.elements[0][2];
+ bv[2].y = v.elements[1][2];
+ bv[2].z = v.elements[2][2];
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT4: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+
+ Vector<float> m2 = p_value;
+ if (m2.size() < 16) {
+ m2.resize(16);
+ }
+
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = m2[2];
+ bv[0].w = m2[3];
+
+ bv[1].x = m2[4];
+ bv[1].y = m2[5];
+ bv[1].z = m2[6];
+ bv[1].w = m2[7];
+
+ bv[2].x = m2[8];
+ bv[2].y = m2[9];
+ bv[2].z = m2[10];
+ bv[2].w = m2[11];
+
+ bv[3].x = m2[12];
+ bv[3].y = m2[13];
+ bv[3].z = m2[14];
+ bv[3].w = m2[15];
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform2D v = p_value;
+ bv[0].x = v.elements[0][0];
+ bv[0].y = v.elements[0][1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = v.elements[1][0];
+ bv[1].y = v.elements[1][1];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ bv[2].x = v.elements[2][0];
+ bv[2].y = v.elements[2][1];
+ bv[2].z = 1;
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform3D v = p_value;
+ bv[0].x = v.basis.elements[0][0];
+ bv[0].y = v.basis.elements[1][0];
+ bv[0].z = v.basis.elements[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.basis.elements[0][1];
+ bv[1].y = v.basis.elements[1][1];
+ bv[1].z = v.basis.elements[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.basis.elements[0][2];
+ bv[2].y = v.basis.elements[1][2];
+ bv[2].z = v.basis.elements[2][2];
+ bv[2].w = 0;
+
+ bv[3].x = v.origin.x;
+ bv[3].y = v.origin.y;
+ bv[3].z = v.origin.z;
+ bv[3].w = 1;
+
+ } break;
+ default: {
+ ERR_FAIL();
+ }
+ }
+}
+
+void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+ int32_t prev_chunk = -1;
+
+ for (int32_t i = 0; i < p_elements; i++) {
+ int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (chunk != prev_chunk) {
+ if (!global_variables.buffer_dirty_regions[chunk]) {
+ global_variables.buffer_dirty_regions[chunk] = true;
+ global_variables.buffer_dirty_region_count++;
+ }
+ }
+
+ prev_chunk = chunk;
+ }
+}
+
+void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_variables.variables.has(p_name));
+ GlobalVariables::Variable gv;
+ gv.type = p_type;
+ gv.value = p_value;
+ gv.buffer_index = -1;
+
+ if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //is texture
+ global_variables.must_update_texture_materials = true; //normally there are none
+ } else {
+ gv.buffer_elements = 1;
+ if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 2;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 3;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 4;
+ }
+
+ //is vector, allocate in buffer and update index
+ gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ 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)));
+ global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+
+ global_variables.must_update_buffer_materials = true; //normally there are none
+ }
+
+ global_variables.variables[p_name] = gv;
+}
+
+void MaterialStorage::global_variable_remove(const StringName &p_name) {
+ if (!global_variables.variables.has(p_name)) {
+ return;
+ }
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ if (gv.buffer_index >= 0) {
+ global_variables.buffer_usage[gv.buffer_index].elements = 0;
+ global_variables.must_update_buffer_materials = true;
+ } else {
+ global_variables.must_update_texture_materials = true;
+ }
+
+ global_variables.variables.erase(p_name);
+}
+
+Vector<StringName> MaterialStorage::global_variable_get_list() const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ const StringName *K = nullptr;
+ Vector<StringName> names;
+ while ((K = global_variables.variables.next(K))) {
+ names.push_back(*K);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+ return names;
+}
+
+void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_variables.variables.has(p_name));
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ gv.value = p_value;
+ if (gv.override.get_type() == Variant::NIL) {
+ if (gv.buffer_index >= 0) {
+ //buffer
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ Material *material = material_storage->get_material(E->get());
+ ERR_CONTINUE(!material);
+ material_storage->_material_queue_update(material, false, true);
+ }
+ }
+ }
+}
+
+void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_variables.variables.has(p_name)) {
+ return; //variable may not exist
+ }
+
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
+
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ gv.override = p_value;
+
+ if (gv.buffer_index >= 0) {
+ //buffer
+ if (gv.override.get_type() == Variant::NIL) {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ } else {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ }
+
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ Material *material = material_storage->get_material(E->get());
+ ERR_CONTINUE(!material);
+ material_storage->_material_queue_update(material, false, true);
+ }
+ }
+}
+
+Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ if (!global_variables.variables.has(p_name)) {
+ return Variant();
+ }
+
+ return global_variables.variables[p_name].value;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
+ if (!global_variables.variables.has(p_name)) {
+ return RS::GLOBAL_VAR_TYPE_MAX;
+ }
+
+ return global_variables.variables[p_name].type;
+}
+
+RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ return global_variable_get_type_internal(p_name);
+}
+
+void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+ List<PropertyInfo> settings;
+ ProjectSettings::get_singleton()->get_property_list(&settings);
+
+ for (const PropertyInfo &E : settings) {
+ if (E.name.begins_with("shader_globals/")) {
+ StringName name = E.name.get_slice("/", 1);
+ Dictionary d = ProjectSettings::get_singleton()->get(E.name);
+
+ ERR_CONTINUE(!d.has("type"));
+ ERR_CONTINUE(!d.has("value"));
+
+ String type = d["type"];
+
+ static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
+ "bool",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "int",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "rect2i",
+ "uint",
+ "uvec2",
+ "uvec3",
+ "uvec4",
+ "float",
+ "vec2",
+ "vec3",
+ "vec4",
+ "color",
+ "rect2",
+ "mat2",
+ "mat3",
+ "mat4",
+ "transform_2d",
+ "transform",
+ "sampler2D",
+ "sampler2DArray",
+ "sampler3D",
+ "samplerCube",
+ };
+
+ RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+
+ for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
+ if (global_var_type_names[i] == type) {
+ gvtype = RS::GlobalVariableType(i);
+ break;
+ }
+ }
+
+ ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
+
+ Variant value = d["value"];
+
+ if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //textire
+ if (!p_load_textures) {
+ value = RID();
+ continue;
+ }
+
+ String path = value;
+ RES resource = ResourceLoader::load(path);
+ ERR_CONTINUE(resource.is_null());
+ value = resource;
+ }
+
+ if (global_variables.variables.has(name)) {
+ //has it, update it
+ global_variable_set(name, value);
+ } else {
+ global_variable_add(name, gvtype, value);
+ }
+ }
+ }
+}
+
+void MaterialStorage::global_variables_clear() {
+ global_variables.variables.clear(); //not right but for now enough
+}
+
+RID MaterialStorage::global_variables_get_storage_buffer() const {
+ return global_variables.buffer;
+}
+
+int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+ ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
+ global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ return pos;
+}
+
+void MaterialStorage::global_variables_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ if (pos >= 0) {
+ global_variables.buffer_usage[pos].elements = 0;
+ }
+ global_variables.instance_buffer_pos.erase(p_instance);
+}
+
+void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_variables.instance_buffer_pos.has(p_instance)) {
+ return; //just not allocated, ignore
+ }
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+
+ if (pos < 0) {
+ return; //again, not allocated, ignore
+ }
+ ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
+ ShaderLanguage::TYPE_MAX, //nil
+ ShaderLanguage::TYPE_BOOL, //bool
+ ShaderLanguage::TYPE_INT, //int
+ ShaderLanguage::TYPE_FLOAT, //float
+ ShaderLanguage::TYPE_MAX, //string
+ ShaderLanguage::TYPE_VEC2, //vec2
+ ShaderLanguage::TYPE_IVEC2, //vec2i
+ ShaderLanguage::TYPE_VEC4, //rect2
+ ShaderLanguage::TYPE_IVEC4, //rect2i
+ ShaderLanguage::TYPE_VEC3, // vec3
+ ShaderLanguage::TYPE_IVEC3, //vec3i
+ ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //plane
+ ShaderLanguage::TYPE_VEC4, //quat
+ ShaderLanguage::TYPE_MAX, //aabb not supported here
+ ShaderLanguage::TYPE_MAX, //basis not supported here
+ ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_VEC4 //color
+ };
+
+ ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
+
+ ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ pos += p_index;
+
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_variable_mark_buffer_dirty(pos, 1);
+}
+
+void MaterialStorage::_update_global_variables() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ if (global_variables.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ // 25% of regions dirty, just update all buffer
+ RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
+ memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ } else {
+ uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+
+ for (uint32_t i = 0; i < total_regions; i++) {
+ if (global_variables.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+
+ global_variables.buffer_dirty_regions[i] = false;
+ }
+ }
+ }
+
+ global_variables.buffer_dirty_region_count = 0;
+ }
+
+ if (global_variables.must_update_buffer_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (const RID &E : global_variables.materials_using_buffer) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material); //wtf
+
+ material_storage->_material_queue_update(material, true, false);
+ }
+
+ global_variables.must_update_buffer_materials = false;
+ }
+
+ if (global_variables.must_update_texture_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (const RID &E : global_variables.materials_using_texture) {
+ Material *material = material_storage->get_material(E);
+ ERR_CONTINUE(!material); //wtf
+
+ material_storage->_material_queue_update(material, false, true);
+ }
+
+ global_variables.must_update_texture_materials = false;
+ }
+}
+
+/* SHADER API */
+
+RID MaterialStorage::shader_allocate() {
+ return shader_owner.allocate_rid();
+}
+
+void MaterialStorage::shader_initialize(RID p_rid) {
+ Shader shader;
+ shader.data = nullptr;
+ shader.type = SHADER_TYPE_MAX;
+
+ shader_owner.initialize_rid(p_rid, shader);
+}
+
+void MaterialStorage::shader_free(RID p_rid) {
+ Shader *shader = shader_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!shader);
+
+ //make material unreference this
+ while (shader->owners.size()) {
+ material_set_shader(shader->owners.front()->get()->self, RID());
+ }
+
+ //clear data if exists
+ if (shader->data) {
+ memdelete(shader->data);
+ }
+ shader_owner.free(p_rid);
+}
+
+void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->code = p_code;
+ String mode_string = ShaderLanguage::get_shader_type(p_code);
+
+ ShaderType new_type;
+ if (mode_string == "canvas_item") {
+ new_type = SHADER_TYPE_2D;
+ } else if (mode_string == "particles") {
+ new_type = SHADER_TYPE_PARTICLES;
+ } else if (mode_string == "spatial") {
+ new_type = SHADER_TYPE_3D;
+ } else if (mode_string == "sky") {
+ new_type = SHADER_TYPE_SKY;
+ } else if (mode_string == "fog") {
+ new_type = SHADER_TYPE_FOG;
+ } else {
+ new_type = SHADER_TYPE_MAX;
+ }
+
+ if (new_type != shader->type) {
+ if (shader->data) {
+ memdelete(shader->data);
+ shader->data = nullptr;
+ }
+
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ material->shader_type = new_type;
+ if (material->data) {
+ memdelete(material->data);
+ material->data = nullptr;
+ }
+ }
+
+ shader->type = new_type;
+
+ if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) {
+ shader->data = shader_data_request_func[new_type]();
+ } else {
+ shader->type = SHADER_TYPE_MAX; //invalid
+ }
+
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ if (shader->data) {
+ material->data = material_get_data_request_function(new_type)(shader->data);
+ material->data->self = material->self;
+ material->data->set_next_pass(material->next_pass);
+ material->data->set_render_priority(material->priority);
+ }
+ material->shader_type = new_type;
+ }
+
+ if (shader->data) {
+ for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<int, RID> &E2 : E.value) {
+ shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ }
+ }
+ }
+ }
+
+ if (shader->data) {
+ shader->data->set_code(p_code);
+ }
+
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ _material_queue_update(material, true, true);
+ }
+}
+
+String MaterialStorage::shader_get_code(RID p_shader) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, String());
+ return shader->code;
+}
+
+void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+ if (shader->data) {
+ return shader->data->get_param_list(p_param_list);
+ }
+}
+
+void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) {
+ if (!shader->default_texture_parameter.has(p_name)) {
+ shader->default_texture_parameter[p_name] = Map<int, RID>();
+ }
+ shader->default_texture_parameter[p_name][p_index] = p_texture;
+ } else {
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ shader->default_texture_parameter[p_name].erase(p_index);
+
+ if (shader->default_texture_parameter[p_name].is_empty()) {
+ shader->default_texture_parameter.erase(p_name);
+ }
+ }
+ }
+ if (shader->data) {
+ shader->data->set_default_texture_param(p_name, p_texture, p_index);
+ }
+ for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ Material *material = E->get();
+ _material_queue_update(material, false, true);
+ }
+}
+
+RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RID());
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ return shader->default_texture_parameter[p_name][p_index];
+ }
+
+ return RID();
+}
+
+Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, Variant());
+ if (shader->data) {
+ return shader->data->get_default_parameter(p_param);
+ }
+ return Variant();
+}
+
+void MaterialStorage::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
+ ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
+ shader_data_request_func[p_shader_type] = p_function;
+}
+
+RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_shader) const {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
+ if (shader->data) {
+ return shader->data->get_native_source_code();
+ }
+ return RS::ShaderNativeSourceCode();
+}
+
+/* MATERIAL API */
+
+void MaterialStorage::_material_uniform_set_erased(void *p_material) {
+ RID rid = *(RID *)p_material;
+ Material *material = MaterialStorage::get_singleton()->get_material(rid);
+ if (material) {
+ if (material->data) {
+ // Uniform set may be gone because a dependency was erased. This happens
+ // if a texture is deleted, so re-create it.
+ MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
+ }
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ }
+}
+
+void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
+ material->uniform_dirty = material->uniform_dirty || p_uniform;
+ material->texture_dirty = material->texture_dirty || p_texture;
+
+ if (material->update_element.in_list()) {
+ return;
+ }
+
+ material_update_list.add(&material->update_element);
+}
+
+void MaterialStorage::_update_queued_materials() {
+ while (material_update_list.first()) {
+ Material *material = material_update_list.first()->self();
+ bool uniforms_changed = false;
+
+ if (material->data) {
+ uniforms_changed = material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty);
+ }
+ material->texture_dirty = false;
+ material->uniform_dirty = false;
+
+ material_update_list.remove(&material->update_element);
+
+ if (uniforms_changed) {
+ //some implementations such as 3D renderer cache the matreial uniform set, so update is required
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ }
+ }
+}
+
+RID MaterialStorage::material_allocate() {
+ return material_owner.allocate_rid();
+}
+
+void MaterialStorage::material_initialize(RID p_rid) {
+ material_owner.initialize_rid(p_rid);
+ Material *material = material_owner.get_or_null(p_rid);
+ material->self = p_rid;
+}
+
+void MaterialStorage::material_free(RID p_rid) {
+ Material *material = material_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!material);
+
+ material_set_shader(p_rid, RID()); //clean up shader
+ material->dependency.deleted_notify(p_rid);
+
+ material_owner.free(p_rid);
+}
+
+void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (material->data) {
+ memdelete(material->data);
+ material->data = nullptr;
+ }
+
+ if (material->shader) {
+ material->shader->owners.erase(material);
+ material->shader = nullptr;
+ material->shader_type = SHADER_TYPE_MAX;
+ }
+
+ if (p_shader.is_null()) {
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->shader_id = 0;
+ return;
+ }
+
+ Shader *shader = get_shader(p_shader);
+ ERR_FAIL_COND(!shader);
+ material->shader = shader;
+ material->shader_type = shader->type;
+ material->shader_id = p_shader.get_local_index();
+ shader->owners.insert(material);
+
+ if (shader->type == SHADER_TYPE_MAX) {
+ return;
+ }
+
+ ERR_FAIL_COND(shader->data == nullptr);
+
+ material->data = material_data_request_func[shader->type](shader->data);
+ material->data->self = p_material;
+ material->data->set_next_pass(material->next_pass);
+ material->data->set_render_priority(material->priority);
+ //updating happens later
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ _material_queue_update(material, true, true);
+}
+
+void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (p_value.get_type() == Variant::NIL) {
+ material->params.erase(p_param);
+ } else {
+ ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT); //object not allowed
+ material->params[p_param] = p_value;
+ }
+
+ if (material->shader && material->shader->data) { //shader is valid
+ bool is_texture = material->shader->data->is_param_texture(p_param);
+ _material_queue_update(material, !is_texture, is_texture);
+ } else {
+ _material_queue_update(material, true, true);
+ }
+}
+
+Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, Variant());
+ if (material->params.has(p_param)) {
+ return material->params[p_param];
+ } else {
+ return Variant();
+ }
+}
+
+void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+
+ if (material->next_pass == p_next_material) {
+ return;
+ }
+
+ material->next_pass = p_next_material;
+ if (material->data) {
+ material->data->set_next_pass(p_next_material);
+ }
+
+ material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+}
+
+void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ material->priority = priority;
+ if (material->data) {
+ material->data->set_render_priority(priority);
+ }
+}
+
+bool MaterialStorage::material_is_animated(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, false);
+ if (material->shader && material->shader->data) {
+ if (material->shader->data->is_animated()) {
+ return true;
+ } else if (material->next_pass.is_valid()) {
+ return material_is_animated(material->next_pass);
+ }
+ }
+ return false; //by default nothing is animated
+}
+
+bool MaterialStorage::material_casts_shadows(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND_V(!material, true);
+ if (material->shader && material->shader->data) {
+ if (material->shader->data->casts_shadows()) {
+ return true;
+ } else if (material->next_pass.is_valid()) {
+ return material_casts_shadows(material->next_pass);
+ }
+ }
+ return true; //by default everything casts shadows
+}
+
+void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ if (material->shader && material->shader->data) {
+ material->shader->data->get_instance_param_list(r_parameters);
+
+ if (material->next_pass.is_valid()) {
+ material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ }
+ }
+}
+
+void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+ Material *material = material_owner.get_or_null(p_material);
+ ERR_FAIL_COND(!material);
+ p_instance->update_dependency(&material->dependency);
+ if (material->next_pass.is_valid()) {
+ material_update_dependency(material->next_pass, p_instance);
+ }
+}
+
+void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
+ ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
+ material_data_request_func[p_shader_type] = p_function;
+}
+
+MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
+ ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
+ return material_data_request_func[p_shader_type];
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
new file mode 100644
index 0000000000..69b7b702b0
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -0,0 +1,315 @@
+/*************************************************************************/
+/* material_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MATERIAL_STORAGE_RD_H
+#define MATERIAL_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/shader_language.h"
+#include "servers/rendering/storage/material_storage.h"
+
+namespace RendererRD {
+
+class MaterialStorage;
+
+/* SHADER Structs */
+
+enum ShaderType {
+ SHADER_TYPE_2D,
+ SHADER_TYPE_3D,
+ SHADER_TYPE_PARTICLES,
+ SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
+ SHADER_TYPE_MAX
+};
+
+struct ShaderData {
+ virtual void set_code(const String &p_Code) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
+ virtual bool is_param_texture(const StringName &p_param) const = 0;
+ virtual bool is_animated() const = 0;
+ virtual bool casts_shadows() const = 0;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
+
+ virtual ~ShaderData() {}
+};
+
+typedef ShaderData *(*ShaderDataRequestFunction)();
+
+struct Material;
+
+struct Shader {
+ ShaderData *data;
+ String code;
+ ShaderType type;
+ Map<StringName, Map<int, RID>> default_texture_parameter;
+ Set<Material *> owners;
+};
+
+/* Material structs */
+
+struct MaterialData {
+ void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+ void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+
+ virtual void set_render_priority(int p_priority) = 0;
+ virtual void set_next_pass(RID p_pass) = 0;
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual ~MaterialData();
+
+ //to be used internally by update_parameters, in the most common configuration of material parameters
+ bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void free_parameters_uniform_set(RID p_uniform_set);
+
+private:
+ friend class MaterialStorage;
+ RID self;
+ List<RID>::Element *global_buffer_E = nullptr;
+ List<RID>::Element *global_texture_E = nullptr;
+ uint64_t global_textures_pass = 0;
+ Map<StringName, uint64_t> used_global_textures;
+
+ //internally by update_parameters_uniform_set
+ Vector<uint8_t> ubo_data;
+ RID uniform_buffer;
+ Vector<RID> texture_cache;
+};
+
+typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+
+struct Material {
+ RID self;
+ MaterialData *data = nullptr;
+ Shader *shader = nullptr;
+ //shortcut to shader data and type
+ ShaderType shader_type = SHADER_TYPE_MAX;
+ uint32_t shader_id = 0;
+ bool uniform_dirty = false;
+ bool texture_dirty = false;
+ Map<StringName, Variant> params;
+ int32_t priority = 0;
+ RID next_pass;
+ SelfList<Material> update_element;
+
+ RendererStorage::Dependency dependency;
+
+ Material() :
+ update_element(this) {}
+};
+
+/* Global variable structs */
+struct GlobalVariables {
+ enum {
+ BUFFER_DIRTY_REGION_SIZE = 1024
+ };
+ struct Variable {
+ Set<RID> texture_materials; // materials using this
+
+ RS::GlobalVariableType type;
+ Variant value;
+ Variant override;
+ int32_t buffer_index; //for vectors
+ int32_t buffer_elements; //for vectors
+ };
+
+ HashMap<StringName, Variable> variables;
+
+ struct Value {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct ValueInt {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ struct ValueUInt {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ uint32_t w;
+ };
+
+ struct ValueUsage {
+ uint32_t elements = 0;
+ };
+
+ List<RID> materials_using_buffer;
+ List<RID> materials_using_texture;
+
+ RID buffer;
+ Value *buffer_values;
+ ValueUsage *buffer_usage;
+ bool *buffer_dirty_regions;
+ uint32_t buffer_dirty_region_count = 0;
+
+ uint32_t buffer_size;
+
+ bool must_update_texture_materials = false;
+ bool must_update_buffer_materials = false;
+
+ HashMap<RID, int32_t> instance_buffer_pos;
+};
+
+class MaterialStorage : public RendererMaterialStorage {
+private:
+ friend struct MaterialData;
+ static MaterialStorage *singleton;
+
+ /* GLOBAL VARIABLE API */
+
+ GlobalVariables global_variables;
+
+ int32_t _global_variable_allocate(uint32_t p_elements);
+ void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
+ void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+
+ /* SHADER API */
+
+ ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
+ mutable RID_Owner<Shader, true> shader_owner;
+
+ /* MATERIAL API */
+ MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
+ mutable RID_Owner<Material, true> material_owner;
+
+ SelfList<Material>::List material_update_list;
+
+ static void _material_uniform_set_erased(void *p_material);
+
+public:
+ static MaterialStorage *get_singleton();
+
+ MaterialStorage();
+ virtual ~MaterialStorage();
+
+ /* GLOBAL VARIABLE API */
+
+ void _update_global_variables();
+
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
+ virtual void global_variable_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_variable_get_list() const override;
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_variable_get(const StringName &p_name) const override;
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
+ RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+
+ virtual void global_variables_load_settings(bool p_load_textures = true) override;
+ virtual void global_variables_clear() override;
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance) override;
+ virtual void global_variables_instance_free(RID p_instance) override;
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+
+ RID global_variables_get_storage_buffer() const;
+
+ /* SHADER API */
+
+ Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
+ bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
+
+ virtual RID shader_allocate() override;
+ virtual void shader_initialize(RID p_shader) override;
+ virtual void shader_free(RID p_rid) override;
+
+ virtual void shader_set_code(RID p_shader, const String &p_code) override;
+ virtual String shader_get_code(RID p_shader) const override;
+ virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
+ virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override;
+ void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
+
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;
+
+ /* MATERIAL API */
+
+ Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
+ bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
+
+ void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
+ void _update_queued_materials();
+
+ virtual RID material_allocate() override;
+ virtual void material_initialize(RID p_material) override;
+ virtual void material_free(RID p_rid) override;
+
+ virtual void material_set_shader(RID p_material, RID p_shader) override;
+
+ virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
+ virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
+
+ virtual void material_set_next_pass(RID p_material, RID p_next_material) override;
+ virtual void material_set_render_priority(RID p_material, int priority) override;
+
+ virtual bool material_is_animated(RID p_material) override;
+ virtual bool material_casts_shadows(RID p_material) override;
+
+ virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
+
+ virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override;
+
+ void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
+ MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
+
+ _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
+ Material *material = material_owner.get_or_null(p_material);
+ return material->shader_id;
+ }
+
+ _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
+ Material *material = material_owner.get_or_null(p_material);
+ if (!material || material->shader_type != p_shader_type) {
+ return nullptr;
+ } else {
+ return material->data;
+ }
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !MATERIAL_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index f1a5383295..a3ca7d3720 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -949,7 +949,7 @@ void TextureStorage::texture_set_path(RID p_texture, const String &p_path) {
}
String TextureStorage::texture_get_path(RID p_texture) const {
- RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+ Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, String());
return tex->path;
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
index 5843b9db24..84529ca400 100644
--- a/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.cpp
@@ -36,7 +36,7 @@ void UniformSetCacheRD::_invalidate(Cache *p_cache) {
if (p_cache->prev) {
p_cache->prev->next = p_cache->next;
} else {
- // At begining of table
+ // At beginning of table
uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE;
hash_table[table_idx] = p_cache->next;
}