summaryrefslogtreecommitdiffstats
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h16
-rw-r--r--servers/rendering/dummy/storage/light_storage.h2
-rw-r--r--servers/rendering/dummy/storage/material_storage.h2
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h2
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h26
-rw-r--r--servers/rendering/dummy/storage/utilities.h2
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp3
-rw-r--r--servers/rendering/renderer_compositor.h2
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp18
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h1
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp84
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h4
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp2
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h6
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp4
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp12
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp8
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h20
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp41
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp12
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h39
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp422
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h82
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h2
-rw-r--r--servers/rendering/renderer_rd/shaders/blit.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl44
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl37
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl328
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl75
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp19
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h13
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h8
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp35
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h8
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h1
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h19
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.h4
-rw-r--r--servers/rendering/renderer_scene_cull.cpp25
-rw-r--r--servers/rendering/renderer_scene_cull.h2
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h10
-rw-r--r--servers/rendering/renderer_scene_render.cpp14
-rw-r--r--servers/rendering/renderer_scene_render.h9
-rw-r--r--servers/rendering/rendering_device.cpp140
-rw-r--r--servers/rendering/rendering_device.h6
-rw-r--r--servers/rendering/rendering_device_binds.cpp5
-rw-r--r--servers/rendering/rendering_device_driver.cpp2
-rw-r--r--servers/rendering/rendering_device_driver.h18
-rw-r--r--servers/rendering/rendering_device_graph.cpp91
-rw-r--r--servers/rendering/rendering_device_graph.h26
-rw-r--r--servers/rendering/rendering_method.h1
-rw-r--r--servers/rendering/rendering_server_default.cpp2
-rw-r--r--servers/rendering/rendering_server_default.h5
-rw-r--r--servers/rendering/shader_compiler.cpp10
-rw-r--r--servers/rendering/shader_language.cpp129
-rw-r--r--servers/rendering/shader_language.h6
-rw-r--r--servers/rendering/shader_preprocessor.cpp34
-rw-r--r--servers/rendering/shader_preprocessor.h1
-rw-r--r--servers/rendering/shader_types.cpp11
-rw-r--r--servers/rendering/storage/camera_attributes_storage.h4
-rw-r--r--servers/rendering/storage/environment_storage.cpp12
-rw-r--r--servers/rendering/storage/environment_storage.h5
-rw-r--r--servers/rendering/storage/light_storage.h2
-rw-r--r--servers/rendering/storage/render_scene_buffers.cpp2
71 files changed, 1353 insertions, 692 deletions
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index 7640afc711..6205193d9a 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -66,14 +66,14 @@ protected:
RasterizerSceneDummy scene;
public:
- RendererUtilities *get_utilities() override { return &utilities; };
- RendererLightStorage *get_light_storage() override { return &light_storage; };
- RendererMaterialStorage *get_material_storage() override { return &material_storage; };
- RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
- RendererParticlesStorage *get_particles_storage() override { return &particles_storage; };
- RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
- RendererGI *get_gi() override { return &gi; };
- RendererFog *get_fog() override { return &fog; };
+ RendererUtilities *get_utilities() override { return &utilities; }
+ RendererLightStorage *get_light_storage() override { return &light_storage; }
+ RendererMaterialStorage *get_material_storage() override { return &material_storage; }
+ RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; }
+ RendererParticlesStorage *get_particles_storage() override { return &particles_storage; }
+ RendererTextureStorage *get_texture_storage() override { return &texture_storage; }
+ RendererGI *get_gi() override { return &gi; }
+ RendererFog *get_fog() override { return &fog; }
RendererCanvasRender *get_canvas() override { return &canvas; }
RendererSceneRender *get_scene() override { return &scene; }
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index c3b63cdbf6..d25523753c 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -78,6 +78,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override {}
+ virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override { return 0xFFFFFFFF; }
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index e4c58474e2..74ae71cba6 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -92,7 +92,7 @@ public:
virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const override { return Variant(); }
- virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }
/* MATERIAL API */
virtual RID material_allocate() override { return RID(); }
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index b0953b5dce..855336c71f 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -64,7 +64,7 @@ public:
/* MESH API */
- bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }
virtual RID mesh_allocate() override;
virtual void mesh_initialize(RID p_rid) override;
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 6735f6bcda..63eb441915 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -53,7 +53,7 @@ public:
/* Canvas Texture API */
- virtual RID canvas_texture_allocate() override { return RID(); };
+ virtual RID canvas_texture_allocate() override { return RID(); }
virtual void canvas_texture_initialize(RID p_rid) override {}
virtual void canvas_texture_free(RID p_rid) override {}
@@ -65,13 +65,13 @@ public:
/* Texture API */
- bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
+ bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }
virtual RID texture_allocate() override {
DummyTexture *texture = memnew(DummyTexture);
ERR_FAIL_NULL_V(texture, RID());
return texture_owner.make_rid(texture);
- };
+ }
virtual void texture_free(RID p_rid) override {
// delete the texture
@@ -79,13 +79,13 @@ public:
ERR_FAIL_NULL(texture);
texture_owner.free(p_rid);
memdelete(texture);
- };
+ }
virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override {
DummyTexture *t = texture_owner.get_or_null(p_texture);
ERR_FAIL_NULL(t);
t->image = p_image->duplicate();
- };
+ }
virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {}
@@ -107,15 +107,15 @@ public:
DummyTexture *t = texture_owner.get_or_null(p_texture);
ERR_FAIL_NULL_V(t, Ref<Image>());
return t->image;
- };
- virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); };
- virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); };
+ }
+ virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
+ virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
- virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); };
+ virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
virtual void texture_set_path(RID p_texture, const String &p_path) override {}
- virtual String texture_get_path(RID p_texture) const override { return String(); };
+ virtual String texture_get_path(RID p_texture) const override { return String(); }
virtual Image::Format texture_get_format(RID p_texture) const override { return Image::FORMAT_MAX; }
@@ -127,11 +127,11 @@ public:
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override {}
- virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); };
+ virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }
virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override {}
- virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); };
- virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; };
+ virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); }
+ virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; }
/* DECAL API */
virtual RID decal_allocate() override { return RID(); }
diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h
index ae83547afd..4e20dee640 100644
--- a/servers/rendering/dummy/storage/utilities.h
+++ b/servers/rendering/dummy/storage/utilities.h
@@ -124,7 +124,7 @@ public:
virtual RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
virtual String get_video_adapter_api_version() const override { return String(); }
- virtual Size2i get_maximum_viewport_size() const override { return Size2i(); };
+ virtual Size2i get_maximum_viewport_size() const override { return Size2i(); }
};
} // namespace RendererDummy
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 701b4da8f8..d01976acf2 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -612,8 +612,9 @@ void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p
uint32_t RendererCanvasCull::canvas_item_get_visibility_layer(RID p_item) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
- if (!canvas_item)
+ if (!canvas_item) {
return 0;
+ }
return canvas_item->visibility_layer;
}
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index a585c9430b..dbc8f155bf 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -106,7 +106,7 @@ public:
virtual double get_total_time() const = 0;
virtual bool can_create_resources_async() const = 0;
- static bool is_low_end() { return low_end; };
+ static bool is_low_end() { return low_end; }
virtual bool is_xr_enabled() const;
static RendererCompositor *get_singleton() { return singleton; }
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index c7a7532d76..808c82f712 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -1002,15 +1002,19 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ Rect2i screen_rect;
+ float atlas_width = p_dst_size.width / p_rect.size.width;
+ float atlas_height = p_dst_size.height / p_rect.size.height;
+ screen_rect.position.x = (int32_t)(Math::round(p_rect.position.x * atlas_width));
+ screen_rect.position.y = (int32_t)(Math::round(p_rect.position.y * atlas_height));
+ screen_rect.size.width = (int32_t)(Math::round(p_dst_size.width));
+ screen_rect.size.height = (int32_t)(Math::round(p_dst_size.height));
+
CopyToDPPushConstant push_constant;
- push_constant.screen_rect[0] = p_rect.position.x;
- push_constant.screen_rect[1] = p_rect.position.y;
- push_constant.screen_rect[2] = p_rect.size.width;
- push_constant.screen_rect[3] = p_rect.size.height;
push_constant.z_far = p_z_far;
push_constant.z_near = p_z_near;
- push_constant.texel_size[0] = 1.0f / p_dst_size.x;
- push_constant.texel_size[1] = 1.0f / p_dst_size.y;
+ push_constant.texel_size[0] = 1.0f / p_dst_size.width;
+ push_constant.texel_size[1] = 1.0f / p_dst_size.height;
push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign
// setup our uniforms
@@ -1021,7 +1025,7 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf
RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
ERR_FAIL_COND(shader.is_null());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, Vector<Color>(), 1.0f, 0, screen_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index 014f78e2b9..b6fc95d0f1 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -217,7 +217,6 @@ private:
float z_far;
float z_near;
float texel_size[2];
- float screen_rect[4];
};
struct CopyToDP {
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 2dfcd67411..090eab384f 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -157,7 +157,7 @@ RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() {
RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() {
return Fog::get_singleton()->_create_fog_shader_func();
-};
+}
RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) {
FogMaterialData *material_data = memnew(FogMaterialData);
@@ -168,7 +168,7 @@ RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogSha
RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
-};
+}
////////////////////////////////////////////////////////////////////////////////
// FOG VOLUMES INSTANCE
@@ -622,6 +622,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
bool any_uses_time = false;
+ Vector3 cam_position = p_cam_transform.get_origin();
for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
@@ -652,41 +653,68 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
any_uses_time |= shader_data->uses_time;
- Vector3i min;
- Vector3i max;
+ Vector3i froxel_min;
+ Vector3i froxel_max;
Vector3i kernel_size;
- Vector3 position = fog_volume_instance->transform.get_origin();
+ Vector3 fog_position = fog_volume_instance->transform.get_origin();
RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2;
if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
// Local fog volume.
- Vector3i points[8];
Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);
float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
- points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
- points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
-
- min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
- max = Vector3i(1, 1, 1);
-
+ Vector3 corners[8]{
+ fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)),
+ fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)),
+ fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)),
+ fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z))
+ };
+ Vector3i froxels[8];
+ Vector3 corner_min = corners[0];
+ Vector3 corner_max = corners[0];
for (int j = 0; j < 8; j++) {
- min = min.min(points[j]);
- max = max.max(points[j]);
+ froxels[j] = _point_get_position_in_froxel_volume(corners[j], fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ corner_min = corner_min.min(corners[j]);
+ corner_max = corner_max.max(corners[j]);
+ }
+
+ froxel_min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
+ froxel_max = Vector3i(1, 1, 1);
+
+ // Tracking just the corners of the fog volume can result in missing some fog:
+ // when the camera's near plane is inside the fog, we must always consider the entire screen
+ Vector3 near_plane_corner(frustum_near_size.x, frustum_near_size.y, z_near);
+ float expand = near_plane_corner.length();
+ if (cam_position.x > (corner_min.x - expand) && cam_position.x < (corner_max.x + expand) &&
+ cam_position.y > (corner_min.y - expand) && cam_position.y < (corner_max.y + expand) &&
+ cam_position.z > (corner_min.z - expand) && cam_position.z < (corner_max.z + expand)) {
+ froxel_min.x = 0;
+ froxel_min.y = 0;
+ froxel_min.z = 0;
+ froxel_max.x = int32_t(fog->width);
+ froxel_max.y = int32_t(fog->height);
+ for (int j = 0; j < 8; j++) {
+ froxel_max.z = MAX(froxel_max.z, froxels[j].z);
+ }
+ } else {
+ // Camera is guaranteed to be outside the fog volume
+ for (int j = 0; j < 8; j++) {
+ froxel_min = froxel_min.min(froxels[j]);
+ froxel_max = froxel_max.max(froxels[j]);
+ }
}
- kernel_size = max - min;
+ kernel_size = froxel_max - froxel_min;
} else {
// Volume type global runs on all cells
extents = Vector3(fog->width, fog->height, fog->depth);
- min = Vector3i(0, 0, 0);
+ froxel_min = Vector3i(0, 0, 0);
kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
}
@@ -695,15 +723,15 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
}
VolumetricFogShader::FogPushConstant push_constant;
- push_constant.position[0] = position.x;
- push_constant.position[1] = position.y;
- push_constant.position[2] = position.z;
+ push_constant.position[0] = fog_position.x;
+ push_constant.position[1] = fog_position.y;
+ push_constant.position[2] = fog_position.z;
push_constant.size[0] = extents.x * 2;
push_constant.size[1] = extents.y * 2;
push_constant.size[2] = extents.z * 2;
- push_constant.corner[0] = min.x;
- push_constant.corner[1] = min.y;
- push_constant.corner[2] = min.z;
+ push_constant.corner[0] = froxel_min.x;
+ push_constant.corner[1] = froxel_min.y;
+ push_constant.corner[2] = froxel_min.z;
push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume));
RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform);
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
index 75b9c563f7..23de97a268 100644
--- a/servers/rendering/renderer_rd/environment/fog.h
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -233,7 +233,7 @@ public:
/* FOG VOLUMES */
- bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };
+ bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }
virtual RID fog_volume_allocate() override;
virtual void fog_volume_initialize(RID p_rid) override;
@@ -250,7 +250,7 @@ public:
/* FOG VOLUMES INSTANCE */
- bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
+ bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }
RID fog_volume_instance_create(RID p_fog_volume);
void fog_instance_free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 12ff28d7b0..235aa9f828 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -350,7 +350,7 @@ bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
bool GI::voxel_gi_is_interior(RID p_voxel_gi) const {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_NULL_V(voxel_gi, 0);
+ ERR_FAIL_NULL_V(voxel_gi, false);
return voxel_gi->interior;
}
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index f6f9ab4f75..f34bbde6f0 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -467,7 +467,7 @@ public:
/* VOXEL GI API */
- bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };
+ bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }
virtual RID voxel_gi_allocate() override;
virtual void voxel_gi_free(RID p_voxel_gi) override;
@@ -524,14 +524,14 @@ public:
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_NULL_V(voxel_gi, RID());
return voxel_gi->texture;
- };
+ }
_FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) {
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_NULL(voxel_gi);
voxel_gi->render_index = p_index;
- };
+ }
bool voxel_gi_instance_owns(RID p_rid) const {
return voxel_gi_instance_owner.owns(p_rid);
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 2087989102..63956a7918 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -701,7 +701,7 @@ RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() {
RendererRD::MaterialStorage::ShaderData *SkyRD::_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();
-};
+}
RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
@@ -713,7 +713,7 @@ RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyS
RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::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));
-};
+}
SkyRD::SkyRD() {
roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
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 76d8972ad9..eb73a9d7e6 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -395,6 +395,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
SceneShaderForwardClustered::ShaderSpecialization pipeline_specialization = p_params->base_specialization;
+ pipeline_specialization.multimesh = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH);
+ pipeline_specialization.multimesh_format_2d = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D);
+ pipeline_specialization.multimesh_has_color = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR);
+ pipeline_specialization.multimesh_has_custom_data = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA);
if constexpr (p_pass_mode == PASS_MODE_COLOR) {
pipeline_specialization.use_light_soft_shadows = element_info.uses_softshadow;
@@ -1961,7 +1965,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, Vector2(0.0f, 0.0f), this);
} else {
- sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, p_render_data->scene_data->taa_jitter, this);
+ Projection projection = p_render_data->scene_data->cam_projection;
+ if (p_render_data->scene_data->cam_frustum) {
+ // Sky is drawn upside down, the frustum offset doesn't know the image is upside down so needs a flip.
+ projection[2].y = -projection[2].y;
+ }
+
+ sky.setup_sky(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, &projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, p_render_data->scene_data->taa_jitter, this);
}
sky_energy_multiplier *= bg_energy_multiplier;
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 53982af590..00a70e3690 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
@@ -374,6 +374,10 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
specialization_constants.push_back(sc);
+ sc.constant_id = 1;
+ sc.int_value = p_pipeline_key.shader_specialization.packed_1;
+ specialization_constants.push_back(sc);
+
RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.color_pass_flags, p_pipeline_key.ubershader);
ERR_FAIL_COND(shader_rid.is_null());
@@ -610,6 +614,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["VIEWPORT_SIZE"] = "read_viewport_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@@ -649,8 +655,6 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
- actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
- actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["LIGHT_VERTEX"] = "light_vertex";
actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
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 136514588a..e1ed85779e 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
@@ -108,16 +108,26 @@ public:
uint32_t projector_use_mipmaps : 1;
uint32_t use_depth_fog : 1;
uint32_t use_lightmap_bicubic_filter : 1;
- uint32_t soft_shadow_samples : 4;
- uint32_t penumbra_shadow_samples : 4;
- uint32_t directional_soft_shadow_samples : 4;
- uint32_t directional_penumbra_shadow_samples : 4;
+ uint32_t soft_shadow_samples : 6;
+ uint32_t penumbra_shadow_samples : 6;
+ uint32_t directional_soft_shadow_samples : 6;
+ uint32_t directional_penumbra_shadow_samples : 6;
};
uint32_t packed_0;
};
- uint32_t packed_1;
+ union {
+ struct {
+ uint32_t multimesh : 1;
+ uint32_t multimesh_format_2d : 1;
+ uint32_t multimesh_has_color : 1;
+ uint32_t multimesh_has_custom_data : 1;
+ };
+
+ uint32_t packed_1;
+ };
+
uint32_t packed_2;
};
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 978ce097d3..5ad92bd211 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -911,14 +911,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Color clear_color = p_default_bg_color;
bool load_color = false;
bool copy_canvas = false;
+ bool use_ambient_cubemap = false;
+ bool use_reflection_cubemap = false;
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
+ RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(p_render_data->environment);
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment);
+ use_ambient_cubemap = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY;
+ use_reflection_cubemap = (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY;
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
@@ -963,7 +968,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
@@ -976,7 +981,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, 1, &projection, &eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, Vector2(0.0f, 0.0f), this);
} else {
- sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, screen_size, p_render_data->scene_data->taa_jitter, this);
+ Projection projection = p_render_data->scene_data->cam_projection;
+ if (p_render_data->scene_data->cam_frustum) {
+ // Sky is drawn upside down, the frustum offset doesn't know the image is upside down so needs a flip.
+ projection[2].y = -projection[2].y;
+ }
+
+ sky.setup_sky(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, p_render_data->scene_data->view_count, &projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, projection, screen_size, p_render_data->scene_data->taa_jitter, this);
}
sky_energy_multiplier *= bg_energy_multiplier;
@@ -1008,13 +1019,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
SceneShaderForwardMobile::ShaderSpecialization base_specialization = scene_shader.default_specialization;
{
- //figure out spec constants
-
- if (p_render_data->directional_light_count > 0) {
- base_specialization.use_directional_soft_shadows = p_render_data->directional_light_soft_shadows;
- } else {
- base_specialization.disable_directional_lights = true;
- }
+ base_specialization.use_directional_soft_shadows = p_render_data->directional_light_count > 0 ? p_render_data->directional_light_soft_shadows : false;
+ base_specialization.directional_lights = p_render_data->directional_light_count;
if (!is_environment(p_render_data->environment) || !environment_get_fog_enabled(p_render_data->environment)) {
base_specialization.disable_fog = true;
@@ -1023,6 +1029,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
base_specialization.use_depth_fog = true;
}
+
+ base_specialization.scene_use_ambient_cubemap = use_ambient_cubemap;
+ base_specialization.scene_use_reflection_cubemap = use_reflection_cubemap;
+ base_specialization.scene_roughness_limiter_enabled = p_render_data->render_buffers.is_valid() && screen_space_roughness_limiter_is_active();
}
{
@@ -2144,7 +2154,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
}
SceneShaderForwardMobile::ShaderSpecialization pipeline_specialization = p_params->base_specialization;
- pipeline_specialization.is_multimesh = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH);
+ pipeline_specialization.multimesh = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH);
+ pipeline_specialization.multimesh_format_2d = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D);
+ pipeline_specialization.multimesh_has_color = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR);
+ pipeline_specialization.multimesh_has_custom_data = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA);
SceneState::PushConstant push_constant;
push_constant.base_index = i + p_params->element_offset;
@@ -2165,10 +2178,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
} else {
pipeline_specialization.use_light_projector = inst->use_projector;
pipeline_specialization.use_light_soft_shadows = inst->use_soft_shadow;
- pipeline_specialization.disable_omni_lights = inst->omni_light_count == 0;
- pipeline_specialization.disable_spot_lights = inst->spot_light_count == 0;
- pipeline_specialization.disable_reflection_probes = inst->reflection_probe_count == 0;
- pipeline_specialization.disable_decals = inst->decals_count == 0;
+ pipeline_specialization.omni_lights = inst->omni_light_count;
+ pipeline_specialization.spot_lights = inst->spot_light_count;
+ pipeline_specialization.reflection_probes = inst->reflection_probe_count;
+ pipeline_specialization.decals = inst->decals_count;
#ifdef DEBUG_ENABLED
if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {
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 69f084f4c0..4525b50b6e 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
@@ -237,6 +237,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
"VERSION:", p_pipeline_key.version,
"SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
"SPEC PACKED #1:", p_pipeline_key.shader_specialization.packed_1,
+ "SPEC PACKED #2:", p_pipeline_key.shader_specialization.packed_2,
"RENDER PASS:", p_pipeline_key.render_pass,
"WIREFRAME:", p_pipeline_key.wireframe);
#endif
@@ -322,7 +323,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
specialization_constants.push_back(sc);
sc.constant_id = 1;
- sc.float_value = p_pipeline_key.shader_specialization.packed_1;
+ sc.int_value = p_pipeline_key.shader_specialization.packed_1;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+ specialization_constants.push_back(sc);
+
+ sc.constant_id = 2;
+ sc.float_value = p_pipeline_key.shader_specialization.packed_2;
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
specialization_constants.push_back(sc);
@@ -521,6 +527,8 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["VIEWPORT_SIZE"] = "read_viewport_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@@ -560,8 +568,6 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
- actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
- actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["LIGHT_VERTEX"] = "light_vertex";
actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
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 c1095d29dc..f0afeebe79 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
@@ -65,31 +65,42 @@ public:
uint32_t use_directional_soft_shadows : 1;
uint32_t decal_use_mipmaps : 1;
uint32_t projector_use_mipmaps : 1;
- uint32_t disable_omni_lights : 1;
- uint32_t disable_spot_lights : 1;
- uint32_t disable_reflection_probes : 1;
- uint32_t disable_directional_lights : 1;
- uint32_t disable_decals : 1;
uint32_t disable_fog : 1;
uint32_t use_depth_fog : 1;
- uint32_t is_multimesh : 1;
uint32_t use_lightmap_bicubic_filter : 1;
- uint32_t pad : 2;
- uint32_t soft_shadow_samples : 4;
- uint32_t penumbra_shadow_samples : 4;
- uint32_t directional_soft_shadow_samples : 4;
- uint32_t directional_penumbra_shadow_samples : 4;
+ uint32_t multimesh : 1;
+ uint32_t multimesh_format_2d : 1;
+ uint32_t multimesh_has_color : 1;
+ uint32_t multimesh_has_custom_data : 1;
+ uint32_t scene_use_ambient_cubemap : 1;
+ uint32_t scene_use_reflection_cubemap : 1;
+ uint32_t scene_roughness_limiter_enabled : 1;
+ uint32_t padding : 5;
+ uint32_t soft_shadow_samples : 6;
+ uint32_t penumbra_shadow_samples : 6;
};
uint32_t packed_0;
};
union {
- float luminance_multiplier;
- float packed_1;
+ struct {
+ uint32_t directional_soft_shadow_samples : 6;
+ uint32_t directional_penumbra_shadow_samples : 6;
+ uint32_t omni_lights : 4;
+ uint32_t spot_lights : 4;
+ uint32_t reflection_probes : 4;
+ uint32_t directional_lights : 4;
+ uint32_t decals : 4;
+ };
+
+ uint32_t packed_1;
};
- uint32_t packed_2;
+ union {
+ float luminance_multiplier;
+ float packed_2;
+ };
};
struct UbershaderConstants {
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 979f590c4c..0dcdb90948 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -911,7 +911,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
RenderingServerDefault::redraw_request();
}
- state.current_data_buffer_index = (state.current_data_buffer_index + 1) % state.canvas_instance_data_buffers.size();
+ state.current_data_buffer_index = (state.current_data_buffer_index + 1) % BATCH_DATA_BUFFER_COUNT;
state.current_instance_buffer_index = 0;
}
@@ -993,36 +993,43 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
Vector<Color> cc;
cc.push_back(Color(p_far, p_far, p_far, 1.0));
- for (int i = 0; i < 4; i++) {
- //make sure it remains orthogonal, makes easy to read angle later
+ Projection projection;
+ {
+ real_t fov = 90;
+ real_t nearp = p_near;
+ real_t farp = p_far;
+ real_t aspect = 1.0;
- //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
+ real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
+ real_t ymin = -ymax;
+ real_t xmin = ymin * aspect;
+ real_t xmax = ymax * aspect;
- Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+ projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
+ }
- Projection projection;
- {
- real_t fov = 90;
- real_t nearp = p_near;
- real_t farp = p_far;
- real_t aspect = 1.0;
+ // Precomputed:
+ // Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
+ // projection = projection * Projection(Transform3D().looking_at(cam_targets[i], Vector3(0, 0, -1)).affine_inverse());
+ const Projection projections[4] = {
+ projection * Projection(Vector4(0, 0, -1, 0), Vector4(1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
- real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
- real_t ymin = -ymax;
- real_t xmin = ymin * aspect;
- real_t xmax = ymax * aspect;
+ projection * Projection(Vector4(-1, 0, 0, 0), Vector4(0, 0, -1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
- projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
- }
+ projection * Projection(Vector4(0, 0, 1, 0), Vector4(-1, 0, 0, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1)),
+
+ projection * Projection(Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0), Vector4(0, -1, 0, 0), Vector4(0, 0, 0, 1))
+
+ };
- Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
- projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
+ for (int i = 0; i < 4; i++) {
+ Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
- push_constant.projection[y * 4 + x] = projection.columns[y][x];
+ push_constant.projection[y * 4 + x] = projections[i].columns[y][x];
}
}
static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) };
@@ -1647,6 +1654,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
default_samplers.default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
}
+ // preallocate 5 slots for uniform set 3
+ state.batch_texture_uniforms.resize(5);
+
{ //shader variants
String global_defines;
@@ -1974,15 +1984,18 @@ void fragment() {
}
{
+ uint32_t cache_size = uint32_t(GLOBAL_GET("rendering/2d/batching/uniform_set_cache_size"));
+ rid_set_to_uniform_set.set_capacity(cache_size);
+ }
+
+ {
state.max_instances_per_buffer = uint32_t(GLOBAL_GET("rendering/2d/batching/item_buffer_size"));
state.max_instance_buffer_size = state.max_instances_per_buffer * sizeof(InstanceData);
- state.canvas_instance_data_buffers.resize(3);
state.canvas_instance_batches.reserve(200);
- for (int i = 0; i < 3; i++) {
- DataBuffer db;
+ for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) {
+ DataBuffer &db = state.canvas_instance_data_buffers[i];
db.instance_buffers.push_back(RD::get_singleton()->storage_buffer_create(state.max_instance_buffer_size));
- state.canvas_instance_data_buffers[i] = db;
}
state.instance_data_array = memnew_arr(InstanceData, state.max_instances_per_buffer);
}
@@ -2159,7 +2172,7 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, clear_colors, 1, 0, Rect2(), RDD::BreadcrumbMarker::UI_PASS);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, fb_uniform_set, BASE_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET);
@@ -2203,14 +2216,47 @@ void RendererCanvasRenderRD::_render_batch_items(RenderTarget p_to_render_target
RD::get_singleton()->draw_list_end();
+ texture_info_map.clear();
state.current_batch_index = 0;
state.canvas_instance_batches.clear();
state.last_instance_index += instance_index;
}
+RendererCanvasRenderRD::InstanceData *RendererCanvasRenderRD::new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info) {
+ InstanceData *instance_data = &state.instance_data_array[p_index];
+ // Zero out most fields.
+ for (int i = 0; i < 4; i++) {
+ instance_data->modulation[i] = 0.0;
+ instance_data->ninepatch_margins[i] = 0.0;
+ instance_data->src_rect[i] = 0.0;
+ instance_data->dst_rect[i] = 0.0;
+ }
+
+ instance_data->pad[0] = 0.0;
+ instance_data->pad[1] = 0.0;
+
+ instance_data->lights[0] = p_lights[0];
+ instance_data->lights[1] = p_lights[1];
+ instance_data->lights[2] = p_lights[2];
+ instance_data->lights[3] = p_lights[3];
+
+ for (int i = 0; i < 6; i++) {
+ instance_data->world[i] = p_world[i];
+ }
+
+ instance_data->flags = p_base_flags | p_info->flags; // Reset on each command for safety, keep canvas texture binding config.
+
+ instance_data->color_texture_pixel_size[0] = p_info->texpixel_size.width;
+ instance_data->color_texture_pixel_size[1] = p_info->texpixel_size.height;
+
+ instance_data->pad1 = 0;
+
+ return instance_data;
+}
+
void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch) {
- RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter;
- RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat;
+ const RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? default_filter : p_item->texture_filter;
+ const RenderingServer::CanvasItemTextureRepeat texture_repeat = p_item->texture_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? default_repeat : p_item->texture_repeat;
Transform2D base_transform = p_base_transform;
@@ -2241,7 +2287,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
light_count++;
- if (light_count == state.max_lights_per_item - 1) {
+ if (light_count == MAX_LIGHTS_PER_ITEM - 1) {
break;
}
}
@@ -2258,38 +2304,6 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->use_lighting = use_lighting;
}
- // new_instance_data should be called after the current_batch is set.
- auto new_instance_data = [&]() -> InstanceData * {
- InstanceData *instance_data = &state.instance_data_array[r_index];
- // Zero out most fields.
- for (int i = 0; i < 4; i++) {
- instance_data->modulation[i] = 0.0;
- instance_data->ninepatch_margins[i] = 0.0;
- instance_data->src_rect[i] = 0.0;
- instance_data->dst_rect[i] = 0.0;
- }
-
- instance_data->pad[0] = 0.0;
- instance_data->pad[1] = 0.0;
-
- instance_data->lights[0] = lights[0];
- instance_data->lights[1] = lights[1];
- instance_data->lights[2] = lights[2];
- instance_data->lights[3] = lights[3];
-
- for (int i = 0; i < 6; i++) {
- instance_data->world[i] = world[i];
- }
-
- instance_data->flags = base_flags | r_current_batch->tex_info.flags; // Reset on each command for safety, keep canvas texture binding config.
-
- instance_data->color_texture_pixel_size[0] = r_current_batch->tex_info.texpixel_size.width;
- instance_data->color_texture_pixel_size[1] = r_current_batch->tex_info.texpixel_size.height;
- instance_data->specular_shininess = r_current_batch->tex_info.specular_shininess;
-
- return instance_data;
- };
-
const Item::Command *c = p_item->commands;
while (c) {
if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
@@ -2311,17 +2325,9 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
}
+ RenderingServer::CanvasItemTextureRepeat rect_repeat = texture_repeat;
if (bool(rect->flags & CANVAS_RECT_TILE)) {
- texture_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
- }
-
- bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF);
- TextureState tex_state(rect->texture, texture_filter, texture_repeat, has_msdf, use_linear_colors);
-
- if (tex_state != r_current_batch->tex_info.state) {
- r_current_batch = _new_batch(r_batch_broken);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, rect->texture);
+ rect_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
}
Color modulated = rect->modulate * base_color;
@@ -2340,12 +2346,25 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
}
- InstanceData *instance_data = new_instance_data();
+ bool has_msdf = bool(rect->flags & CANVAS_RECT_MSDF);
+ TextureState tex_state(rect->texture, texture_filter, rect_repeat, has_msdf, use_linear_colors);
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(rect->texture, tex_state, tex_info);
+ }
+
+ if (r_current_batch->tex_info != tex_info) {
+ r_current_batch = _new_batch(r_batch_broken);
+ r_current_batch->tex_info = tex_info;
+ }
+
+ InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
Rect2 src_rect;
Rect2 dst_rect;
if (rect->texture.is_valid()) {
- src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * r_current_batch->tex_info.texpixel_size, rect->source.size * r_current_batch->tex_info.texpixel_size) : Rect2(0, 0, 1, 1);
+ src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * tex_info->texpixel_size, rect->source.size * tex_info->texpixel_size) : Rect2(0, 0, 1, 1);
dst_rect = Rect2(rect->rect.position, rect->rect.size);
if (dst_rect.size.width < 0) {
@@ -2431,13 +2450,18 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
}
TextureState tex_state(np->texture, texture_filter, texture_repeat, false, use_linear_colors);
- if (tex_state != r_current_batch->tex_info.state) {
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(np->texture, tex_state, tex_info);
+ }
+
+ if (r_current_batch->tex_info != tex_info) {
r_current_batch = _new_batch(r_batch_broken);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, np->texture);
+ r_current_batch->tex_info = tex_info;
}
- InstanceData *instance_data = new_instance_data();
+ InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
Rect2 src_rect;
Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y);
@@ -2446,7 +2470,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
src_rect = Rect2(0, 0, 1, 1);
} else {
if (np->source != Rect2()) {
- src_rect = Rect2(np->source.position.x * r_current_batch->tex_info.texpixel_size.width, np->source.position.y * r_current_batch->tex_info.texpixel_size.height, np->source.size.x * r_current_batch->tex_info.texpixel_size.width, np->source.size.y * r_current_batch->tex_info.texpixel_size.height);
+ src_rect = Rect2(np->source.position.x * tex_info->texpixel_size.width, np->source.position.y * tex_info->texpixel_size.height, np->source.size.x * tex_info->texpixel_size.width, np->source.size.y * tex_info->texpixel_size.height);
instance_data->color_texture_pixel_size[0] = 1.0 / np->source.size.width;
instance_data->color_texture_pixel_size[1] = 1.0 / np->source.size.height;
} else {
@@ -2500,10 +2524,15 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->command = c;
TextureState tex_state(polygon->texture, texture_filter, texture_repeat, false, use_linear_colors);
- if (tex_state != r_current_batch->tex_info.state) {
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(polygon->texture, tex_state, tex_info);
+ }
+
+ if (r_current_batch->tex_info != tex_info) {
r_current_batch = _new_batch(r_batch_broken);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, polygon->texture);
+ r_current_batch->tex_info = tex_info;
}
// pipeline variant
@@ -2513,7 +2542,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_current_batch->render_primitive = _primitive_type_to_render_primitive(polygon->primitive);
}
- InstanceData *instance_data = new_instance_data();
+ InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
Color color = base_color;
if (use_linear_colors) {
@@ -2557,17 +2586,22 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
default:
// Unknown point count.
break;
- };
-
- TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors);
- if (tex_state != r_current_batch->tex_info.state) {
- r_current_batch = _new_batch(r_batch_broken);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, primitive->texture);
}
}
- InstanceData *instance_data = new_instance_data();
+ TextureState tex_state(primitive->texture, texture_filter, texture_repeat, false, use_linear_colors);
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(primitive->texture, tex_state, tex_info);
+ }
+
+ if (r_current_batch->tex_info != tex_info) {
+ r_current_batch = _new_batch(r_batch_broken);
+ r_current_batch->tex_info = tex_info;
+ }
+
+ InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
for (uint32_t j = 0; j < MIN(3u, primitive->point_count); j++) {
instance_data->points[j * 2 + 0] = primitive->points[j].x;
@@ -2585,7 +2619,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
_add_to_batch(r_index, r_batch_broken, r_current_batch);
if (primitive->point_count == 4) {
- instance_data = new_instance_data();
+ instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
for (uint32_t j = 0; j < 3; j++) {
int offset = j == 0 ? 0 : 1;
@@ -2594,7 +2628,7 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
instance_data->points[j * 2 + 1] = primitive->points[j + offset].y;
instance_data->uvs[j * 2 + 0] = primitive->uvs[j + offset].x;
instance_data->uvs[j * 2 + 1] = primitive->uvs[j + offset].y;
- Color col = primitive->colors[j] * base_color;
+ Color col = primitive->colors[j + offset] * base_color;
if (use_linear_colors) {
col = col.srgb_to_linear();
}
@@ -2621,9 +2655,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
TextureState tex_state(m->texture, texture_filter, texture_repeat, false, use_linear_colors);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, m->texture);
- instance_data = new_instance_data();
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(m->texture, tex_state, tex_info);
+ }
+ r_current_batch->tex_info = tex_info;
+ instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
r_current_batch->mesh_instance_count = 1;
_update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, instance_data->world);
@@ -2644,9 +2682,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
}
TextureState tex_state(mm->texture, texture_filter, texture_repeat, false, use_linear_colors);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, mm->texture);
- instance_data = new_instance_data();
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(mm->texture, tex_state, tex_info);
+ }
+ r_current_batch->tex_info = tex_info;
+ instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
instance_data->flags |= 1; // multimesh, trails disabled
@@ -2662,10 +2704,13 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
TextureState tex_state(pt->texture, texture_filter, texture_repeat, false, use_linear_colors);
- r_current_batch->tex_info.state = tex_state;
- _prepare_batch_texture_info(r_current_batch, pt->texture);
-
- instance_data = new_instance_data();
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(pt->texture, tex_state, tex_info);
+ }
+ r_current_batch->tex_info = tex_info;
+ instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
uint32_t divisor = 1;
r_current_batch->mesh_instance_count = particles_storage->particles_get_amount(pt->particles, divisor);
@@ -2747,36 +2792,137 @@ void RendererCanvasRenderRD::_record_item_commands(const Item *p_item, RenderTar
r_batch_broken = false;
}
+#ifdef DEBUG_ENABLED
+ if (debug_redraw && p_item->debug_redraw_time > 0.0) {
+ Color dc = debug_redraw_color;
+ dc.a *= p_item->debug_redraw_time / debug_redraw_time;
+
+ // 1: If commands are different, start a new batch.
+ if (r_current_batch->command_type != Item::Command::TYPE_RECT) {
+ r_current_batch = _new_batch(r_batch_broken);
+ r_current_batch->command_type = Item::Command::TYPE_RECT;
+ // it is ok to be null for a TYPE_RECT
+ r_current_batch->command = nullptr;
+ // default variant
+ r_current_batch->shader_variant = SHADER_VARIANT_QUAD;
+ r_current_batch->render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
+ }
+
+ // 2: If the current batch has lighting, start a new batch.
+ if (r_current_batch->use_lighting) {
+ r_current_batch = _new_batch(r_batch_broken);
+ r_current_batch->use_lighting = false;
+ }
+
+ // 3: If the current batch has blend, start a new batch.
+ if (r_current_batch->has_blend) {
+ r_current_batch = _new_batch(r_batch_broken);
+ r_current_batch->has_blend = false;
+ }
+
+ TextureState tex_state(default_canvas_texture, texture_filter, texture_repeat, false, use_linear_colors);
+ TextureInfo *tex_info = texture_info_map.getptr(tex_state);
+ if (!tex_info) {
+ tex_info = &texture_info_map.insert(tex_state, TextureInfo())->value;
+ _prepare_batch_texture_info(default_canvas_texture, tex_state, tex_info);
+ }
+
+ if (r_current_batch->tex_info != tex_info) {
+ r_current_batch = _new_batch(r_batch_broken);
+ r_current_batch->tex_info = tex_info;
+ }
+
+ InstanceData *instance_data = new_instance_data(world, lights, base_flags, r_index, tex_info);
+
+ Rect2 src_rect;
+ Rect2 dst_rect;
+
+ dst_rect = Rect2(Vector2(), p_item->rect.size);
+ if (dst_rect.size.width < 0) {
+ dst_rect.position.x += dst_rect.size.width;
+ dst_rect.size.width *= -1;
+ }
+ if (dst_rect.size.height < 0) {
+ dst_rect.position.y += dst_rect.size.height;
+ dst_rect.size.height *= -1;
+ }
+
+ src_rect = Rect2(0, 0, 1, 1);
+
+ instance_data->modulation[0] = dc.r;
+ instance_data->modulation[1] = dc.g;
+ instance_data->modulation[2] = dc.b;
+ instance_data->modulation[3] = dc.a;
+
+ instance_data->src_rect[0] = src_rect.position.x;
+ instance_data->src_rect[1] = src_rect.position.y;
+ instance_data->src_rect[2] = src_rect.size.width;
+ instance_data->src_rect[3] = src_rect.size.height;
+
+ instance_data->dst_rect[0] = dst_rect.position.x;
+ instance_data->dst_rect[1] = dst_rect.position.y;
+ instance_data->dst_rect[2] = dst_rect.size.width;
+ instance_data->dst_rect[3] = dst_rect.size.height;
+
+ _add_to_batch(r_index, r_batch_broken, r_current_batch);
+
+ p_item->debug_redraw_time -= RSG::rasterizer->get_frame_delta_time();
+
+ RenderingServerDefault::redraw_request();
+
+ r_batch_broken = false;
+ }
+#endif
+
if (r_current_clip && reclip) {
// will make it re-enable clipping if needed afterwards
r_current_clip = nullptr;
}
}
-void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) {
- UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
- ERR_FAIL_NULL(uniform_set_cache);
+void RendererCanvasRenderRD::_before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid) {
+ RD::get_singleton()->uniform_set_set_invalidation_callback(p_rid, nullptr, nullptr);
+ RD::get_singleton()->free(p_rid);
+}
- ERR_FAIL_NULL(p_batch->command);
+void RendererCanvasRenderRD::_uniform_set_invalidation_callback(void *p_userdata) {
+ const RIDSetKey *key = static_cast<RIDSetKey *>(p_userdata);
+ static_cast<RendererCanvasRenderRD *>(singleton)->rid_set_to_uniform_set.erase(*key);
+}
+void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info) {
{
- RD::Uniform u_diffuse(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info.diffuse);
- RD::Uniform u_normal(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info.normal);
- RD::Uniform u_specular(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info.specular);
- RD::Uniform u_sampler(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info.sampler);
- RD::Uniform u_instance_data(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
-
- RID uniform_set = uniform_set_cache->get_cache(shader.default_version_rd_shader, BATCH_UNIFORM_SET, u_diffuse, u_normal, u_specular, u_sampler, u_instance_data);
+ RIDSetKey key(
+ p_batch->tex_info->state,
+ state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
+
+ const RID *uniform_set = rid_set_to_uniform_set.getptr(key);
+ if (uniform_set == nullptr) {
+ state.batch_texture_uniforms.write[0] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 0, p_batch->tex_info->diffuse);
+ state.batch_texture_uniforms.write[1] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 1, p_batch->tex_info->normal);
+ state.batch_texture_uniforms.write[2] = RD::Uniform(RD::UNIFORM_TYPE_TEXTURE, 2, p_batch->tex_info->specular);
+ state.batch_texture_uniforms.write[3] = RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, 3, p_batch->tex_info->sampler);
+ state.batch_texture_uniforms.write[4] = RD::Uniform(RD::UNIFORM_TYPE_STORAGE_BUFFER, 4, state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers[p_batch->instance_buffer_index]);
+
+ RID rid = RD::get_singleton()->uniform_set_create(state.batch_texture_uniforms, shader.default_version_rd_shader, BATCH_UNIFORM_SET);
+ ERR_FAIL_COND_MSG(rid.is_null(), "Failed to create uniform set for batch.");
+
+ const RIDCache::Pair *iter = rid_set_to_uniform_set.insert(key, rid);
+ uniform_set = &iter->data;
+ RD::get_singleton()->uniform_set_set_invalidation_callback(rid, RendererCanvasRenderRD::_uniform_set_invalidation_callback, (void *)&iter->key);
+ }
- if (state.current_batch_uniform_set != uniform_set) {
- state.current_batch_uniform_set = uniform_set;
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, BATCH_UNIFORM_SET);
+ if (state.current_batch_uniform_set != *uniform_set) {
+ state.current_batch_uniform_set = *uniform_set;
+ RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, *uniform_set, BATCH_UNIFORM_SET);
}
}
+ PushConstant push_constant;
+ push_constant.base_instance_index = p_batch->start;
+ push_constant.specular_shininess = p_batch->tex_info->specular_shininess;
RID pipeline;
PipelineKey pipeline_key;
- PushConstant push_constant;
pipeline_key.framebuffer_format_id = p_framebuffer_format;
pipeline_key.variant = p_batch->shader_variant;
pipeline_key.render_primitive = p_batch->render_primitive;
@@ -2792,7 +2938,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, p_batch->modulate);
}
- push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
RD::get_singleton()->draw_list_draw(p_draw_list, true, p_batch->instance_count);
@@ -2805,6 +2950,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
} break;
case Item::Command::TYPE_POLYGON: {
+ ERR_FAIL_NULL(p_batch->command);
+
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(p_batch->command);
PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id);
@@ -2814,7 +2961,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array);
if (pb->indices.is_valid()) {
@@ -2830,12 +2976,13 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
} break;
case Item::Command::TYPE_PRIMITIVE: {
+ ERR_FAIL_NULL(p_batch->command);
+
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(p_batch->command);
pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]);
uint32_t instance_count = p_batch->instance_count;
@@ -2852,6 +2999,8 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
case Item::Command::TYPE_MESH:
case Item::Command::TYPE_MULTIMESH:
case Item::Command::TYPE_PARTICLES: {
+ ERR_FAIL_NULL(p_batch->command);
+
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
@@ -2912,7 +3061,6 @@ void RendererCanvasRenderRD::_render_batch(RD::DrawListID p_draw_list, CanvasSha
pipeline = _get_pipeline_specialization_or_ubershader(p_shader_data, pipeline_key, push_constant, mesh_instance, surface, j, &vertex_array);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- push_constant.base_instance_index = p_batch->start;
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0);
@@ -2994,7 +3142,7 @@ void RendererCanvasRenderRD::_allocate_instance_buffer() {
state.canvas_instance_data_buffers[state.current_data_buffer_index].instance_buffers.push_back(buf);
}
-void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const {
+void RendererCanvasRenderRD::_prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info) {
if (p_texture.is_null()) {
p_texture = default_canvas_texture;
}
@@ -3002,38 +3150,38 @@ void RendererCanvasRenderRD::_prepare_batch_texture_info(Batch *p_current_batch,
RendererRD::TextureStorage::CanvasTextureInfo info =
RendererRD::TextureStorage::get_singleton()->canvas_texture_get_info(
p_texture,
- p_current_batch->tex_info.state.texture_filter(),
- p_current_batch->tex_info.state.texture_repeat(),
- p_current_batch->tex_info.state.linear_colors(),
- p_current_batch->tex_info.state.texture_is_data());
-
+ p_state.texture_filter(),
+ p_state.texture_repeat(),
+ p_state.linear_colors(),
+ p_state.texture_is_data());
// something odd happened
if (info.is_null()) {
- _prepare_batch_texture_info(p_current_batch, default_canvas_texture);
+ _prepare_batch_texture_info(default_canvas_texture, p_state, p_info);
return;
}
- p_current_batch->tex_info.diffuse = info.diffuse;
- p_current_batch->tex_info.normal = info.normal;
- p_current_batch->tex_info.specular = info.specular;
- p_current_batch->tex_info.sampler = info.sampler;
+ p_info->state = p_state;
+ p_info->diffuse = info.diffuse;
+ p_info->normal = info.normal;
+ p_info->specular = info.specular;
+ p_info->sampler = info.sampler;
// cache values to be copied to instance data
if (info.specular_color.a < 0.999) {
- p_current_batch->tex_info.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
+ p_info->flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
}
if (info.use_normal) {
- p_current_batch->tex_info.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
+ p_info->flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
}
uint8_t a = uint8_t(CLAMP(info.specular_color.a * 255.0, 0.0, 255.0));
uint8_t b = uint8_t(CLAMP(info.specular_color.b * 255.0, 0.0, 255.0));
uint8_t g = uint8_t(CLAMP(info.specular_color.g * 255.0, 0.0, 255.0));
uint8_t r = uint8_t(CLAMP(info.specular_color.r * 255.0, 0.0, 255.0));
- p_current_batch->tex_info.specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r);
+ p_info->specular_shininess = uint32_t(a) << 24 | uint32_t(b) << 16 | uint32_t(g) << 8 | uint32_t(r);
- p_current_batch->tex_info.texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height));
+ p_info->texpixel_size = Vector2(1.0 / float(info.size.width), 1.0 / float(info.size.height));
}
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
@@ -3075,7 +3223,7 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
RD::get_singleton()->free(state.shadow_texture);
memdelete_arr(state.instance_data_array);
- for (uint32_t i = 0; i < state.canvas_instance_data_buffers.size(); i++) {
+ for (uint32_t i = 0; i < BATCH_DATA_BUFFER_COUNT; i++) {
for (uint32_t j = 0; j < state.canvas_instance_data_buffers[i].instance_buffers.size(); j++) {
RD::get_singleton()->free(state.canvas_instance_data_buffers[i].instance_buffers[j]);
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 07445b5c53..1bdc5076c5 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -31,6 +31,7 @@
#ifndef RENDERER_CANVAS_RENDER_RD_H
#define RENDERER_CANVAS_RENDER_RD_H
+#include "core/templates/lru.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
@@ -50,6 +51,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
};
const int SAMPLERS_BINDING_FIRST_INDEX = 10;
+ // The size of the ring buffer to store GPU buffers. Triple-buffering the max expected frames in flight.
+ static const uint32_t BATCH_DATA_BUFFER_COUNT = 3;
enum ShaderVariant {
SHADER_VARIANT_QUAD,
@@ -339,7 +342,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
struct InstanceData {
float world[6];
uint32_t flags;
- uint32_t specular_shininess;
+ uint32_t pad1;
union {
//rect
struct {
@@ -366,8 +369,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
struct PushConstant {
uint32_t base_instance_index;
ShaderSpecialization shader_specialization;
- uint32_t pad2;
- uint32_t pad3;
+ uint32_t specular_shininess;
+ uint32_t pad;
};
// TextureState is used to determine when a new batch is required due to a change of texture state.
@@ -398,50 +401,91 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
(((uint32_t)p_use_linear_colors & LINEAR_COLORS_MASK) << LINEAR_COLORS_SHIFT);
}
- _FORCE_INLINE_ RS::CanvasItemTextureFilter texture_filter() const {
+ _ALWAYS_INLINE_ RS::CanvasItemTextureFilter texture_filter() const {
return (RS::CanvasItemTextureFilter)((other >> FILTER_SHIFT) & FILTER_MASK);
}
- _FORCE_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const {
+ _ALWAYS_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const {
return (RS::CanvasItemTextureRepeat)((other >> REPEAT_SHIFT) & REPEAT_MASK);
}
- _FORCE_INLINE_ bool linear_colors() const {
+ _ALWAYS_INLINE_ bool linear_colors() const {
return (other >> LINEAR_COLORS_SHIFT) & LINEAR_COLORS_MASK;
}
- _FORCE_INLINE_ bool texture_is_data() const {
+ _ALWAYS_INLINE_ bool texture_is_data() const {
return (other >> TEXTURE_IS_DATA_SHIFT) & TEXTURE_IS_DATA_MASK;
}
- bool operator==(const TextureState &p_val) const {
+ _ALWAYS_INLINE_ bool operator==(const TextureState &p_val) const {
return (texture == p_val.texture) && (other == p_val.other);
}
- bool operator!=(const TextureState &p_val) const {
+ _ALWAYS_INLINE_ bool operator!=(const TextureState &p_val) const {
return (texture != p_val.texture) || (other != p_val.other);
}
+
+ _ALWAYS_INLINE_ bool is_valid() const { return texture.is_valid(); }
+ _ALWAYS_INLINE_ bool is_null() const { return texture.is_null(); }
+
+ uint32_t hash() const {
+ uint32_t hash = hash_murmur3_one_64(texture.get_id());
+ return hash_murmur3_one_32(other, hash);
+ }
};
struct TextureInfo {
TextureState state;
- uint32_t specular_shininess = 0;
- uint32_t flags = 0;
- Vector2 texpixel_size;
-
RID diffuse;
RID normal;
RID specular;
RID sampler;
+ Vector2 texpixel_size;
+ uint32_t specular_shininess = 0;
+ uint32_t flags = 0;
+ };
+
+ /// A key used to uniquely identify a distinct BATCH_UNIFORM_SET
+ struct RIDSetKey {
+ TextureState state;
+ RID instance_data;
+
+ RIDSetKey() {
+ }
+
+ RIDSetKey(TextureState p_state, RID p_instance_data) :
+ state(p_state),
+ instance_data(p_instance_data) {
+ }
+
+ _ALWAYS_INLINE_ bool operator==(const RIDSetKey &p_val) const {
+ return state == p_val.state && instance_data == p_val.instance_data;
+ }
+
+ _ALWAYS_INLINE_ bool operator!=(const RIDSetKey &p_val) const {
+ return !(*this == p_val);
+ }
+
+ _ALWAYS_INLINE_ uint32_t hash() const {
+ uint32_t h = state.hash();
+ h = hash_murmur3_one_64(instance_data.get_id(), h);
+ return hash_fmix32(h);
+ }
};
+ static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid);
+ static void _uniform_set_invalidation_callback(void *p_userdata);
+
+ typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache;
+ RIDCache rid_set_to_uniform_set;
+
struct Batch {
// Position in the UBO measured in bytes
uint32_t start = 0;
uint32_t instance_count = 0;
uint32_t instance_buffer_index = 0;
- TextureInfo tex_info;
+ TextureInfo *tex_info;
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
@@ -466,6 +510,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
bool has_blend = false;
};
+ HashMap<TextureState, TextureInfo, HashableHasher<TextureState>> texture_info_map;
+
+ // per-frame buffers
struct DataBuffer {
LocalVector<RID> instance_buffers;
};
@@ -492,7 +539,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t pad2;
};
- LocalVector<DataBuffer> canvas_instance_data_buffers;
+ DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT];
LocalVector<Batch> canvas_instance_batches;
uint32_t current_data_buffer_index = 0;
uint32_t current_instance_buffer_index = 0;
@@ -503,6 +550,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t max_instances_per_buffer = 16384;
uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData);
+ Vector<RD::Uniform> batch_texture_uniforms;
RID current_batch_uniform_set;
LightUniform *light_uniforms = nullptr;
@@ -518,7 +566,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID default_transforms_uniform_set;
uint32_t max_lights_per_render;
- uint32_t max_lights_per_item;
double time;
@@ -558,7 +605,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
void _render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch);
void _render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr);
- void _prepare_batch_texture_info(Batch *p_current_batch, RID p_texture) const;
+ void _prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info);
+ InstanceData *new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, TextureInfo *p_info);
[[nodiscard]] Batch *_new_batch(bool &r_batch_broken);
void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch);
void _allocate_instance_buffer();
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 84ea6a5da2..ba47508700 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -66,6 +66,16 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
+ // We need to invert the phone rotation.
+ const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(p_screen);
+ float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
+
+ blit.push_constant.rotation_cos = Math::cos(screen_rotation);
+ blit.push_constant.rotation_sin = Math::sin(screen_rotation);
+ // Swap width and height when the orientation is not the native one.
+ if (screen_rotation_degrees % 180 != 0) {
+ SWAP(screen_size.width, screen_size.height);
+ }
blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x;
blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y;
blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width;
@@ -228,6 +238,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0);
+ const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(DisplayServer::MAIN_WINDOW_ID);
+ float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
+ blit.push_constant.rotation_cos = Math::cos(screen_rotation);
+ blit.push_constant.rotation_sin = Math::sin(screen_rotation);
blit.push_constant.src_rect[0] = 0.0;
blit.push_constant.src_rect[1] = 0.0;
blit.push_constant.src_rect[2] = 1.0;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 2547f08715..6821fa737e 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -74,6 +74,10 @@ protected:
float src_rect[4];
float dst_rect[4];
+ float rotation_sin;
+ float rotation_cos;
+ float pad[2];
+
float eye_center[2];
float k1;
float k2;
@@ -103,7 +107,7 @@ protected:
static RendererCompositorRD *singleton;
public:
- RendererUtilities *get_utilities() { return utilities; };
+ RendererUtilities *get_utilities() { return utilities; }
RendererLightStorage *get_light_storage() { return light_storage; }
RendererMaterialStorage *get_material_storage() { return material_storage; }
RendererMeshStorage *get_mesh_storage() { return mesh_storage; }
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index dc2605b670..4417f6832c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1130,6 +1130,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
scene_data.cam_transform = p_camera_data->main_transform;
scene_data.cam_projection = p_camera_data->main_projection;
scene_data.cam_orthogonal = p_camera_data->is_orthogonal;
+ scene_data.cam_frustum = p_camera_data->is_frustum;
scene_data.camera_visible_layers = p_camera_data->visible_layers;
scene_data.taa_jitter = p_camera_data->taa_jitter;
scene_data.taa_frame_count = p_camera_data->taa_frame_count;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index b82d50378e..631ad21247 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -78,7 +78,7 @@ protected:
////////////////////////////////
- virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); };
+ virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); }
void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers);
diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl
index d451647bec..fe6416f03c 100644
--- a/servers/rendering/renderer_rd/shaders/blit.glsl
+++ b/servers/rendering/renderer_rd/shaders/blit.glsl
@@ -8,6 +8,10 @@ layout(push_constant, std140) uniform Pos {
vec4 src_rect;
vec4 dst_rect;
+ float rotation_sin;
+ float rotation_cos;
+ vec2 pad;
+
vec2 eye_center;
float k1;
float k2;
@@ -15,17 +19,23 @@ layout(push_constant, std140) uniform Pos {
float upscale;
float aspect_ratio;
uint layer;
- uint pad1;
+ bool convert_to_srgb;
}
data;
layout(location = 0) out vec2 uv;
void main() {
+ mat4 swapchain_transform = mat4(1.0);
+ swapchain_transform[0][0] = data.rotation_cos;
+ swapchain_transform[0][1] = -data.rotation_sin;
+ swapchain_transform[1][0] = data.rotation_sin;
+ swapchain_transform[1][1] = data.rotation_cos;
+
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw;
vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw;
- gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
+ gl_Position = swapchain_transform * vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
}
#[fragment]
@@ -38,6 +48,10 @@ layout(push_constant, std140) uniform Pos {
vec4 src_rect;
vec4 dst_rect;
+ float rotation_sin;
+ float rotation_cos;
+ vec2 pad;
+
vec2 eye_center;
float k1;
float k2;
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index dafcce37ad..f665bc24a4 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -28,7 +28,7 @@ layout(location = 11) in vec4 weight_attrib;
layout(location = 4) out flat uint instance_index_interp;
-#endif // USE_ATTRIBUTES
+#endif // !USE_ATTRIBUTES
layout(location = 0) out vec2 uv_interp;
layout(location = 1) out vec4 color_interp;
@@ -322,11 +322,7 @@ vec4 light_compute(
#ifdef USE_NINEPATCH
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
-#ifdef USE_ATTRIBUTES
- const InstanceData draw_data = instances.data[params.base_instance_index];
-#else
const InstanceData draw_data = instances.data[instance_index];
-#endif // USE_ATTRIBUTES
float tex_size = 1.0 / tex_pixel_size;
@@ -567,7 +563,7 @@ void main() {
if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv);
- specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess);
+ specular_shininess *= unpackUnorm4x8(params.specular_shininess);
specular_shininess_used = true;
} else {
specular_shininess = vec4(1.0);
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index ead8c459a4..84017a1fe1 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -37,7 +37,7 @@ struct InstanceData {
vec2 world_y;
vec2 world_ofs;
uint flags;
- uint specular_shininess;
+ uint pad2;
#ifdef USE_PRIMITIVE
vec2 points[3];
vec2 uvs[3];
@@ -57,8 +57,8 @@ struct InstanceData {
layout(push_constant, std430) uniform Params {
uint base_instance_index; // base index to instance data
uint sc_packed_0;
- uint pad2;
- uint pad3;
+ uint specular_shininess;
+ uint pad;
}
params;
@@ -68,7 +68,7 @@ params;
// Pull the constants from the draw call's push constants.
uint sc_packed_0() {
- return draw_call.sc_packed_0;
+ return params.sc_packed_0;
}
#else
diff --git a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
index 3fb93dda35..b45e310b61 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
@@ -8,7 +8,6 @@ layout(push_constant, std430) uniform Params {
float z_far;
float z_near;
vec2 texel_size;
- vec4 screen_rect;
}
params;
@@ -17,8 +16,7 @@ layout(location = 0) out vec2 uv_interp;
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
uv_interp = base_arr[gl_VertexIndex];
- vec2 screen_pos = uv_interp * params.screen_rect.zw + params.screen_rect.xy;
- gl_Position = vec4(screen_pos * 2.0 - 1.0, 0.0, 1.0);
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
}
#[fragment]
@@ -35,7 +33,6 @@ layout(push_constant, std430) uniform Params {
float z_far;
float z_near;
vec2 texel_size;
- vec4 screen_rect;
}
params;
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 72236dcd9f..81d3d87a22 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -211,6 +211,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
}
#endif
+uint multimesh_stride() {
+ uint stride = sc_multimesh_format_2d() ? 2 : 3;
+ stride += sc_multimesh_has_color() ? 1 : 0;
+ stride += sc_multimesh_has_custom_data() ? 1 : 0;
+ return stride;
+}
+
void vertex_shader(vec3 vertex_input,
#ifdef NORMAL_USED
in vec3 normal_input,
@@ -219,7 +226,7 @@ void vertex_shader(vec3 vertex_input,
in vec3 tangent_input,
in vec3 binormal_input,
#endif
- in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
+ in uint instance_index, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
@@ -248,7 +255,7 @@ void vertex_shader(vec3 vertex_input,
mat4 matrix;
mat4 read_model_matrix = model_matrix;
- if (is_multimesh) {
+ if (sc_multimesh()) {
//multimesh, instances are for it
#ifdef USE_PARTICLE_TRAILS
@@ -296,25 +303,10 @@ void vertex_shader(vec3 vertex_input,
#endif
#else
- uint stride = 0;
- {
- //TODO implement a small lookup table for the stride
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- stride += 2;
- } else {
- stride += 3;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- stride += 1;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- stride += 1;
- }
- }
-
+ uint stride = multimesh_stride();
uint offset = stride * (gl_InstanceIndex + multimesh_offset);
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (sc_multimesh_format_2d()) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -322,14 +314,14 @@ void vertex_shader(vec3 vertex_input,
offset += 3;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (sc_multimesh_has_color()) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (sc_multimesh_has_custom_data()) {
instance_custom = transforms.data[offset];
}
@@ -427,7 +419,7 @@ void vertex_shader(vec3 vertex_input,
// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
// We add the result to the vertex and ignore the final lost precision.
vec3 model_origin = model_matrix[3].xyz;
- if (is_multimesh) {
+ if (sc_multimesh()) {
vertex = mat3(matrix) * vertex;
model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
}
@@ -708,9 +700,7 @@ void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position
void main() {
uint instance_index = draw_call.instance_index;
-
- bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
- if (!is_multimesh) {
+ if (!sc_multimesh()) {
instance_index += gl_InstanceIndex;
}
@@ -753,7 +743,7 @@ void main() {
prev_tangent,
prev_binormal,
#endif
- instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
+ instance_index, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
#else
// Unused output.
vec4 screen_position;
@@ -792,7 +782,7 @@ void main() {
tangent,
binormal,
#endif
- instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
+ instance_index, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
}
#[fragment]
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
index 9f68d59be2..8f153f7ed5 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
@@ -59,6 +59,10 @@ uint sc_packed_0() {
return draw_call.sc_packed_0;
}
+uint sc_packed_1() {
+ return draw_call.sc_packed_1;
+}
+
uint uc_cull_mode() {
return (draw_call.uc_packed_0 >> 0) & 3U;
}
@@ -67,11 +71,16 @@ uint uc_cull_mode() {
// Pull the constants from the pipeline's specialization constants.
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
+layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
uint sc_packed_0() {
return pso_sc_packed_0;
}
+uint sc_packed_1() {
+ return pso_sc_packed_1;
+}
+
#endif
bool sc_use_forward_gi() {
@@ -107,19 +116,35 @@ bool sc_use_lightmap_bicubic_filter() {
}
uint sc_soft_shadow_samples() {
- return (sc_packed_0() >> 8) & 15U;
+ return (sc_packed_0() >> 8) & 63U;
}
uint sc_penumbra_shadow_samples() {
- return (sc_packed_0() >> 12) & 15U;
+ return (sc_packed_0() >> 14) & 63U;
}
uint sc_directional_soft_shadow_samples() {
- return (sc_packed_0() >> 16) & 15U;
+ return (sc_packed_0() >> 20) & 63U;
}
uint sc_directional_penumbra_shadow_samples() {
- return (sc_packed_0() >> 20) & 15U;
+ return (sc_packed_0() >> 26) & 63U;
+}
+
+bool sc_multimesh() {
+ return ((sc_packed_1() >> 0) & 1U) != 0;
+}
+
+bool sc_multimesh_format_2d() {
+ return ((sc_packed_1() >> 1) & 1U) != 0;
+}
+
+bool sc_multimesh_has_color() {
+ return ((sc_packed_1() >> 2) & 1U) != 0;
+}
+
+bool sc_multimesh_has_custom_data() {
+ return ((sc_packed_1() >> 3) & 1U) != 0;
}
float sc_luminance_multiplier() {
@@ -144,10 +169,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
#define INSTANCE_FLAGS_PARTICLES (1 << 11)
-#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
-#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
#define INSTANCE_FLAGS_FADE_SHIFT 24
//3 bits of stride
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 2f0e4e0bea..404f658fa6 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -178,6 +178,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
}
#endif
+uint multimesh_stride() {
+ uint stride = sc_multimesh_format_2d() ? 2 : 3;
+ stride += sc_multimesh_has_color() ? 1 : 0;
+ stride += sc_multimesh_has_custom_data() ? 1 : 0;
+ return stride;
+}
+
void main() {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
@@ -208,7 +215,7 @@ void main() {
mat4 matrix;
mat4 read_model_matrix = model_matrix;
- if (sc_is_multimesh()) {
+ if (sc_multimesh()) {
//multimesh, instances are for it
#ifdef USE_PARTICLE_TRAILS
@@ -256,25 +263,10 @@ void main() {
#endif
#else
- uint stride = 0;
- {
- //TODO implement a small lookup table for the stride
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- stride += 2;
- } else {
- stride += 3;
- }
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- stride += 1;
- }
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- stride += 1;
- }
- }
-
+ uint stride = multimesh_stride();
uint offset = stride * gl_InstanceIndex;
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (sc_multimesh_format_2d()) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -282,14 +274,14 @@ void main() {
offset += 3;
}
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (sc_multimesh_has_color()) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (sc_multimesh_has_custom_data()) {
instance_custom = transforms.data[offset];
}
@@ -404,7 +396,7 @@ void main() {
// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
// We add the result to the vertex and ignore the final lost precision.
vec3 model_origin = model_matrix[3].xyz;
- if (sc_is_multimesh()) {
+ if (sc_multimesh()) {
vertex = mat3(matrix) * vertex;
model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
}
@@ -461,50 +453,24 @@ void main() {
diffuse_light_interp = vec4(0.0);
specular_light_interp = vec4(0.0);
- if (!sc_disable_omni_lights()) {
- uint light_indices = instances.data[draw_call.instance_index].omni_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].omni_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
-
- if (light_index == 0xFF) {
- break;
- }
-
- light_process_omni_vertex(light_index, vertex, view, normal, roughness,
- diffuse_light_interp.rgb, specular_light_interp.rgb);
- }
+ uvec2 omni_light_indices = instances.data[draw_call.instance_index].omni_lights;
+ for (uint i = 0; i < sc_omni_lights(); i++) {
+ uint light_index = (i > 3) ? ((omni_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_light_indices.x >> (i * 8)) & 0xFF);
+ light_process_omni_vertex(light_index, vertex, view, normal, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
}
- if (!sc_disable_spot_lights()) {
- uint light_indices = instances.data[draw_call.instance_index].spot_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].spot_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
-
- if (light_index == 0xFF) {
- break;
- }
-
- light_process_spot_vertex(light_index, vertex, view, normal, roughness,
- diffuse_light_interp.rgb, specular_light_interp.rgb);
- }
+ uvec2 spot_light_indices = instances.data[draw_call.instance_index].spot_lights;
+ for (uint i = 0; i < sc_spot_lights(); i++) {
+ uint light_index = (i > 3) ? ((spot_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_light_indices.x >> (i * 8)) & 0xFF);
+ light_process_spot_vertex(light_index, vertex, view, normal, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
}
- if (!sc_disable_directional_lights()) {
+ if (sc_directional_lights() > 0) {
// We process the first directional light separately as it may have shadows.
vec3 directional_diffuse = vec3(0.0);
vec3 directional_specular = vec3(0.0);
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
continue; // Not masked, skip.
}
@@ -823,7 +789,7 @@ vec4 fog_process(vec3 vertex) {
float sun_total = 0.0;
vec3 view = normalize(vertex);
- for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0);
fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter;
@@ -1110,97 +1076,83 @@ void main() {
vec3 vertex_ddx = dFdx(vertex);
vec3 vertex_ddy = dFdy(vertex);
- if (!sc_disable_decals()) { //Decals
- // must implement
-
- uint decal_indices = instances.data[draw_call.instance_index].decals.x;
- for (uint i = 0; i < 8; i++) {
- uint decal_index = decal_indices & 0xFF;
- if (i == 3) {
- decal_indices = instances.data[draw_call.instance_index].decals.y;
- } else {
- decal_indices = decal_indices >> 8;
- }
+ uvec2 decal_indices = instances.data[draw_call.instance_index].decals;
+ for (uint i = 0; i < sc_decals(); i++) {
+ uint decal_index = (i > 3) ? ((decal_indices.y >> ((i - 4) * 8)) & 0xFF) : ((decal_indices.x >> (i * 8)) & 0xFF);
+ if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
+ continue; //not masked
+ }
- if (decal_index == 0xFF) {
- break;
- }
+ vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
+ if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
+ continue; //out of decal
+ }
- if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
- continue; //not masked
- }
+ float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
- vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
- if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
- continue; //out of decal
- }
+ if (decals.data[decal_index].normal_fade > 0.0) {
+ fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+ }
- float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
+ //we need ddx/ddy for mipmaps, so simulate them
+ vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+ vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
- if (decals.data[decal_index].normal_fade > 0.0) {
- fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+ if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
+ //has albedo
+ vec4 decal_albedo;
+ if (sc_decal_use_mipmaps()) {
+ decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ } else {
+ decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
}
+ decal_albedo *= decals.data[decal_index].modulate;
+ decal_albedo.a *= fade;
+ albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
- //we need ddx/ddy for mipmaps, so simulate them
- vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
- vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
-
- if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
- //has albedo
- vec4 decal_albedo;
+ if (decals.data[decal_index].normal_rect != vec4(0.0)) {
+ vec3 decal_normal;
if (sc_decal_use_mipmaps()) {
- decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
} else {
- decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
- }
- decal_albedo *= decals.data[decal_index].modulate;
- decal_albedo.a *= fade;
- albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
-
- if (decals.data[decal_index].normal_rect != vec4(0.0)) {
- vec3 decal_normal;
- if (sc_decal_use_mipmaps()) {
- decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
- } else {
- decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
- }
- decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
- decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
- //convert to view space, use xzy because y is up
- decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
-
- normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+ decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
}
+ decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
+ decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
+ //convert to view space, use xzy because y is up
+ decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
- if (decals.data[decal_index].orm_rect != vec4(0.0)) {
- vec3 decal_orm;
- if (sc_decal_use_mipmaps()) {
- decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
- } else {
- decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
- }
- ao = mix(ao, decal_orm.r, decal_albedo.a);
- roughness = mix(roughness, decal_orm.g, decal_albedo.a);
- metallic = mix(metallic, decal_orm.b, decal_albedo.a);
- }
+ normal = normalize(mix(normal, decal_normal, decal_albedo.a));
}
- if (decals.data[decal_index].emission_rect != vec4(0.0)) {
- //emission is additive, so its independent from albedo
+ if (decals.data[decal_index].orm_rect != vec4(0.0)) {
+ vec3 decal_orm;
if (sc_decal_use_mipmaps()) {
- emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
} else {
- emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
}
+ ao = mix(ao, decal_orm.r, decal_albedo.a);
+ roughness = mix(roughness, decal_orm.g, decal_albedo.a);
+ metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+ }
+ }
+
+ if (decals.data[decal_index].emission_rect != vec4(0.0)) {
+ //emission is additive, so its independent from albedo
+ if (sc_decal_use_mipmaps()) {
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ } else {
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
}
}
- } //Decals
+ }
#endif //!MODE_RENDER_DEPTH
/////////////////////// LIGHTING //////////////////////////////
#ifdef NORMAL_USED
- if (scene_data.roughness_limiter_enabled) {
+ if (sc_scene_roughness_limiter_enabled()) {
//https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
vec3 dndu = dFdx(normal), dndv = dFdy(normal);
@@ -1225,7 +1177,7 @@ void main() {
#ifndef AMBIENT_LIGHT_DISABLED
- if (scene_data.use_reflection_cubemap) {
+ if (sc_scene_use_reflection_cubemap()) {
#ifdef LIGHT_ANISOTROPY_USED
// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
@@ -1266,7 +1218,7 @@ void main() {
if (scene_data.use_ambient_light) {
ambient_light = scene_data.ambient_light_color_energy.rgb;
- if (scene_data.use_ambient_cubemap) {
+ if (sc_scene_use_ambient_cubemap()) {
vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb;
@@ -1285,7 +1237,7 @@ void main() {
#endif // CUSTOM_IRRADIANCE_USED
#ifdef LIGHT_CLEARCOAT_USED
- if (scene_data.use_reflection_cubemap) {
+ if (sc_scene_use_reflection_cubemap()) {
vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map
float NoV = max(dot(n, view), 0.0001);
vec3 ref_vec = reflect(-view, n);
@@ -1393,12 +1345,10 @@ void main() {
// skipping ssao, do we remove ssao totally?
- if (!sc_disable_reflection_probes()) { //Reflection probes
+ if (sc_reflection_probes() > 0) {
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
- uint reflection_indices = instances.data[draw_call.instance_index].reflection_probes.x;
-
#ifdef LIGHT_ANISOTROPY_USED
// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
@@ -1411,18 +1361,9 @@ void main() {
vec3 ref_vec = normalize(reflect(-view, bent_normal));
ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
- for (uint i = 0; i < 8; i++) {
- uint reflection_index = reflection_indices & 0xFF;
- if (i == 3) {
- reflection_indices = instances.data[draw_call.instance_index].reflection_probes.y;
- } else {
- reflection_indices = reflection_indices >> 8;
- }
-
- if (reflection_index == 0xFF) {
- break;
- }
-
+ uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes;
+ for (uint i = 0; i < sc_reflection_probes(); i++) {
+ uint reflection_index = (i > 3) ? ((reflection_indices.y >> ((i - 4) * 8)) & 0xFF) : ((reflection_indices.x >> (i * 8)) & 0xFF);
reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
@@ -1487,7 +1428,7 @@ void main() {
specular_light += specular_light_interp.rgb * f0;
#endif
- if (!sc_disable_directional_lights()) { //directional light
+ if (sc_directional_lights() > 0) {
#ifndef SHADOWS_DISABLED
// Do shadow and lighting in two passes to reduce register pressure
uint shadow0 = 0;
@@ -1497,7 +1438,7 @@ void main() {
// Only process the first light's shadow for vertex lighting.
for (uint i = 0; i < 1; i++) {
#else
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
#endif
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
@@ -1612,7 +1553,7 @@ void main() {
#endif // SHADOWS_DISABLED
#ifndef USE_VERTEX_LIGHTING
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
continue; //not masked
}
@@ -1678,95 +1619,72 @@ void main() {
} //directional light
#ifndef USE_VERTEX_LIGHTING
- if (!sc_disable_omni_lights()) { //omni lights
- uint light_indices = instances.data[draw_call.instance_index].omni_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].omni_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
-
- if (light_index == 0xFF) {
- break;
- }
+ uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
+ for (uint i = 0; i < sc_omni_lights(); i++) {
+ uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
- float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
+ float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
- shadow = blur_shadow(shadow);
+ shadow = blur_shadow(shadow);
- // Fragment lighting
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
+ // Fragment lighting
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
/*
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
#endif
*/
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
+ rim,
+ rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
+ clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent,
- binormal, anisotropy,
+ tangent,
+ binormal, anisotropy,
#endif
- diffuse_light, specular_light);
- }
- } //omni lights
-
- if (!sc_disable_spot_lights()) { //spot lights
-
- uint light_indices = instances.data[draw_call.instance_index].spot_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].spot_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
+ diffuse_light, specular_light);
+ }
- if (light_index == 0xFF) {
- break;
- }
+ uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
+ for (uint i = 0; i < sc_spot_lights(); i++) {
+ uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
- float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
+ float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
- shadow = blur_shadow(shadow);
+ shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
/*
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
#endif
*/
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
+ rim,
+ rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
+ clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent,
- binormal, anisotropy,
+ tangent,
+ binormal, anisotropy,
#endif
- diffuse_light, specular_light);
- }
- } //spot lights
+ diffuse_light, specular_light);
+ }
#endif // !VERTEX_LIGHTING
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
index 495e52a29e..2cc86482f6 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
@@ -22,8 +22,8 @@ layout(push_constant, std430) uniform DrawCall {
uint pad;
#ifdef UBERSHADER
uint sc_packed_0;
- float sc_packed_1;
- uint sc_packed_2;
+ uint sc_packed_1;
+ float sc_packed_2;
uint uc_packed_0;
#endif
}
@@ -42,10 +42,14 @@ uint sc_packed_0() {
return draw_call.sc_packed_0;
}
-float sc_packed_1() {
+uint sc_packed_1() {
return draw_call.sc_packed_1;
}
+float sc_packed_2() {
+ return draw_call.sc_packed_2;
+}
+
uint uc_cull_mode() {
return (draw_call.uc_packed_0 >> 0) & 3U;
}
@@ -54,16 +58,21 @@ uint uc_cull_mode() {
// Pull the constants from the pipeline's specialization constants.
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
-layout(constant_id = 1) const float pso_sc_packed_1 = 2.0;
+layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
+layout(constant_id = 2) const float pso_sc_packed_2 = 2.0;
uint sc_packed_0() {
return pso_sc_packed_0;
}
-float sc_packed_1() {
+uint sc_packed_1() {
return pso_sc_packed_1;
}
+float sc_packed_2() {
+ return pso_sc_packed_2;
+}
+
#endif
bool sc_use_light_projector() {
@@ -86,60 +95,84 @@ bool sc_projector_use_mipmaps() {
return ((sc_packed_0() >> 4) & 1U) != 0;
}
-bool sc_disable_omni_lights() {
+bool sc_disable_fog() {
return ((sc_packed_0() >> 5) & 1U) != 0;
}
-bool sc_disable_spot_lights() {
+bool sc_use_depth_fog() {
return ((sc_packed_0() >> 6) & 1U) != 0;
}
-bool sc_disable_reflection_probes() {
+bool sc_use_lightmap_bicubic_filter() {
return ((sc_packed_0() >> 7) & 1U) != 0;
}
-bool sc_disable_directional_lights() {
+bool sc_multimesh() {
return ((sc_packed_0() >> 8) & 1U) != 0;
}
-bool sc_disable_decals() {
+bool sc_multimesh_format_2d() {
return ((sc_packed_0() >> 9) & 1U) != 0;
}
-bool sc_disable_fog() {
+bool sc_multimesh_has_color() {
return ((sc_packed_0() >> 10) & 1U) != 0;
}
-bool sc_use_depth_fog() {
+bool sc_multimesh_has_custom_data() {
return ((sc_packed_0() >> 11) & 1U) != 0;
}
-bool sc_is_multimesh() {
+bool sc_scene_use_ambient_cubemap() {
return ((sc_packed_0() >> 12) & 1U) != 0;
}
-bool sc_use_lightmap_bicubic_filter() {
+bool sc_scene_use_reflection_cubemap() {
return ((sc_packed_0() >> 13) & 1U) != 0;
}
+bool sc_scene_roughness_limiter_enabled() {
+ return ((sc_packed_0() >> 14) & 1U) != 0;
+}
+
uint sc_soft_shadow_samples() {
- return (sc_packed_0() >> 16) & 15U;
+ return (sc_packed_0() >> 20) & 63U;
}
uint sc_penumbra_shadow_samples() {
- return (sc_packed_0() >> 20) & 15U;
+ return (sc_packed_0() >> 26) & 63U;
}
uint sc_directional_soft_shadow_samples() {
- return (sc_packed_0() >> 24) & 15U;
+ return (sc_packed_1() >> 0) & 63U;
}
uint sc_directional_penumbra_shadow_samples() {
- return (sc_packed_0() >> 28) & 15U;
+ return (sc_packed_1() >> 6) & 63U;
+}
+
+uint sc_omni_lights() {
+ return (sc_packed_1() >> 12) & 15U;
+}
+
+uint sc_spot_lights() {
+ return (sc_packed_1() >> 16) & 15U;
+}
+
+uint sc_reflection_probes() {
+ return (sc_packed_1() >> 20) & 15U;
+}
+
+uint sc_directional_lights() {
+ return (sc_packed_1() >> 24) & 15U;
+}
+
+uint sc_decals() {
+ return (sc_packed_1() >> 28) & 15U;
}
float sc_luminance_multiplier() {
- return sc_packed_1();
+ return sc_packed_2();
}
/* Set 0: Base Pass (never changes) */
@@ -157,10 +190,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
#define INSTANCE_FLAGS_PARTICLES (1 << 11)
-#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
-#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 8f71909154..9de37050f0 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -285,6 +285,23 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
+void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL(light);
+
+ light->shadow_caster_mask = p_caster_mask;
+
+ light->version++;
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
+}
+
+uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL_V(light, 0);
+
+ return light->shadow_caster_mask;
+}
+
void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);
@@ -1032,7 +1049,7 @@ void LightStorage::reflection_probe_free(RID p_rid) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
reflection_probe->dependency.deleted_notify(p_rid);
reflection_probe_owner.free(p_rid);
-};
+}
void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 59303e8a73..1a92c5470d 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -72,6 +72,7 @@ private:
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
uint32_t max_sdfgi_cascade = 2;
uint32_t cull_mask = 0xFFFFFFFF;
+ uint32_t shadow_caster_mask = 0xFFFFFFFF;
bool distance_fade = false;
real_t distance_fade_begin = 40.0;
real_t distance_fade_shadow = 50.0;
@@ -480,6 +481,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
+ virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
@@ -587,7 +590,7 @@ public:
/* LIGHT INSTANCE API */
- bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); };
+ bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_free(RID p_light) override;
@@ -808,7 +811,7 @@ public:
/* REFLECTION PROBE */
- bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
+ bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }
virtual RID reflection_probe_allocate() override;
virtual void reflection_probe_initialize(RID p_reflection_probe) override;
@@ -950,7 +953,7 @@ public:
/* LIGHTMAP */
- bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
+ bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }
virtual RID lightmap_allocate() override;
virtual void lightmap_initialize(RID p_lightmap) override;
@@ -1016,7 +1019,7 @@ public:
/* LIGHTMAP INSTANCE */
- bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); };
+ bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }
virtual RID lightmap_instance_create(RID p_lightmap) override;
virtual void lightmap_instance_free(RID p_lightmap) override;
@@ -1036,7 +1039,7 @@ public:
/* SHADOW ATLAS API */
- bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); };
+ bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }
virtual RID shadow_atlas_create() override;
virtual void shadow_atlas_free(RID p_atlas) override;
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index 08c1064dcb..89a8b36853 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -254,7 +254,7 @@ private:
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Material, true> material_owner;
- Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
+ Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }
SelfList<Material>::List material_update_list;
Mutex material_update_list_mutex;
@@ -403,7 +403,7 @@ public:
/* SHADER API */
- bool owns_shader(RID p_rid) { return shader_owner.owns(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;
@@ -423,7 +423,7 @@ public:
/* MATERIAL API */
- bool owns_material(RID p_rid) { return material_owner.owns(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();
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 322f3cc6f4..c14c2945bd 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -351,7 +351,7 @@ public:
/* MESH API */
- bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }
virtual RID mesh_allocate() override;
virtual void mesh_initialize(RID p_mesh) override;
@@ -616,7 +616,7 @@ public:
/* MESH INSTANCE API */
- bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); };
+ bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); }
virtual RID mesh_instance_create(RID p_base) override;
virtual void mesh_instance_free(RID p_rid) override;
@@ -628,7 +628,7 @@ public:
/* MULTIMESH API */
- bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
+ bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); }
virtual RID _multimesh_allocate() override;
virtual void _multimesh_initialize(RID p_multimesh) override;
@@ -737,7 +737,7 @@ public:
/* SKELETON API */
- bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); };
+ bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); }
virtual RID skeleton_allocate() override;
virtual void skeleton_initialize(RID p_skeleton) override;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 314cbf9aa9..6efb8c176f 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -306,9 +306,14 @@ void ParticlesStorage::_particles_free_data(Particles *particles) {
particles->emission_storage_buffer = RID();
}
- if (particles->unused_storage_buffer.is_valid()) {
- RD::get_singleton()->free(particles->unused_storage_buffer);
- particles->unused_storage_buffer = RID();
+ if (particles->unused_emission_storage_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->unused_emission_storage_buffer);
+ particles->unused_emission_storage_buffer = RID();
+ }
+
+ if (particles->unused_trail_storage_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->unused_trail_storage_buffer);
+ particles->unused_trail_storage_buffer = RID();
}
if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
@@ -534,9 +539,15 @@ void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles)
}
}
-void ParticlesStorage::_particles_ensure_unused_buffer(Particles *particles) {
- if (particles->unused_storage_buffer.is_null()) {
- particles->unused_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
+void ParticlesStorage::_particles_ensure_unused_emission_buffer(Particles *particles) {
+ if (particles->unused_emission_storage_buffer.is_null()) {
+ particles->unused_emission_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
+ }
+}
+
+void ParticlesStorage::_particles_ensure_unused_trail_buffer(Particles *particles) {
+ if (particles->unused_trail_storage_buffer.is_null()) {
+ particles->unused_trail_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
}
}
@@ -763,8 +774,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
if (p_particles->emission_storage_buffer.is_valid()) {
u.append_id(p_particles->emission_storage_buffer);
} else {
- _particles_ensure_unused_buffer(p_particles);
- u.append_id(p_particles->unused_storage_buffer);
+ _particles_ensure_unused_emission_buffer(p_particles);
+ u.append_id(p_particles->unused_emission_storage_buffer);
}
uniforms.push_back(u);
}
@@ -779,8 +790,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
}
u.append_id(sub_emitter->emission_storage_buffer);
} else {
- _particles_ensure_unused_buffer(p_particles);
- u.append_id(p_particles->unused_storage_buffer);
+ _particles_ensure_unused_emission_buffer(p_particles);
+ u.append_id(p_particles->unused_emission_storage_buffer);
}
uniforms.push_back(u);
}
@@ -1481,8 +1492,8 @@ void ParticlesStorage::update_particles() {
if (particles->trail_bind_pose_buffer.is_valid()) {
u.append_id(particles->trail_bind_pose_buffer);
} else {
- _particles_ensure_unused_buffer(particles);
- u.append_id(particles->unused_storage_buffer);
+ _particles_ensure_unused_trail_buffer(particles);
+ u.append_id(particles->unused_trail_storage_buffer);
}
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 33f44f3045..ec897c4ea9 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -247,7 +247,8 @@ private:
ParticleEmissionBuffer *emission_buffer = nullptr;
RID emission_storage_buffer;
- RID unused_storage_buffer;
+ RID unused_emission_storage_buffer;
+ RID unused_trail_storage_buffer;
HashSet<RID> collisions;
@@ -265,7 +266,8 @@ private:
void _particles_process(Particles *p_particles, double p_delta);
void _particles_allocate_emission_buffer(Particles *particles);
- void _particles_ensure_unused_buffer(Particles *particles);
+ void _particles_ensure_unused_emission_buffer(Particles *particles);
+ void _particles_ensure_unused_trail_buffer(Particles *particles);
void _particles_free_data(Particles *particles);
void _particles_update_buffers(Particles *particles);
@@ -509,7 +511,7 @@ public:
_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_NULL_V(particles, 0);
+ ERR_FAIL_NULL_V(particles, false);
return particles->has_collision_cache;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
index 4a70482d72..59671c3a13 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
@@ -51,6 +51,7 @@ public:
float taa_frame_count = 0.0f;
uint32_t camera_visible_layers;
bool cam_orthogonal = false;
+ bool cam_frustum = false;
bool flip_y = false;
// For billboards to cast correct shadows.
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 42fce65b2d..8a9499dfc9 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -1666,7 +1666,9 @@ void TextureStorage::texture_rd_initialize(RID p_texture, const RID &p_rd_textur
ERR_FAIL_COND(tf.array_layers != 1);
texture.type = TextureStorage::TYPE_2D;
} break;
- case RD::TEXTURE_TYPE_2D_ARRAY: {
+ case RD::TEXTURE_TYPE_2D_ARRAY:
+ case RD::TEXTURE_TYPE_CUBE:
+ case RD::TEXTURE_TYPE_CUBE_ARRAY: {
// RenderingDevice doesn't distinguish between Array textures and Cube textures
// this condition covers TextureArrays, TextureCube, and TextureCubeArray.
ERR_FAIL_COND(tf.array_layers == 1);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 866fdd50ac..3d281cf98a 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -102,9 +102,9 @@ private:
/* Canvas Texture API */
struct CanvasTextureCache {
- RID diffuse = RID();
- RID normal = RID();
- RID specular = RID();
+ RID diffuse;
+ RID normal;
+ RID specular;
};
class CanvasTexture {
@@ -122,7 +122,6 @@ private:
Size2i size_cache = Size2i(1, 1);
bool use_normal_cache = false;
bool use_specular_cache = false;
- bool cleared_cache = true;
void clear_cache();
~CanvasTexture();
@@ -195,7 +194,7 @@ private:
// Textures can be created from threads, so this RID_Owner is thread safe.
mutable RID_Owner<Texture, true> texture_owner;
- Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
+ Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); }
struct TextureToRDFormat {
RD::DataFormat format;
@@ -439,7 +438,7 @@ private:
};
mutable RID_Owner<RenderTarget> render_target_owner;
- RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); };
+ RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); }
void _clear_render_target(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
@@ -486,7 +485,7 @@ public:
/* Canvas Texture API */
- bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+ bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }
virtual RID canvas_texture_allocate() override;
virtual void canvas_texture_initialize(RID p_rid) override;
@@ -502,7 +501,7 @@ public:
/* Texture API */
- bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); };
+ bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); }
virtual RID texture_allocate() override;
virtual void texture_free(RID p_rid) override;
@@ -591,7 +590,7 @@ public:
void update_decal_atlas();
- bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); };
+ bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); }
RID decal_atlas_get_texture() const;
RID decal_atlas_get_texture_srgb() const;
@@ -731,7 +730,7 @@ public:
/* RENDER TARGET API */
- bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); };
+ bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); }
virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h
index 2ba3da7515..96508fd3ff 100644
--- a/servers/rendering/renderer_rd/storage_rd/utilities.h
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.h
@@ -77,8 +77,8 @@ public:
/* VISIBILITY NOTIFIER */
- VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); };
- bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); };
+ VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }
+ bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }
virtual RID visibility_notifier_allocate() override;
virtual void visibility_notifier_initialize(RID p_notifier) override;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index ca07444465..11ca7de44f 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -2299,6 +2299,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
cull.shadow_count = p_shadow_index + 1;
cull.shadows[p_shadow_index].cascade_count = splits;
cull.shadows[p_shadow_index].light_instance = light->instance;
+ cull.shadows[p_shadow_index].caster_mask = RSG::light_storage->light_get_shadow_caster_mask(p_instance->base);
for (int i = 0; i < splits; i++) {
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
@@ -2529,7 +2530,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
+ if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2611,7 +2612,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
+ if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2678,7 +2679,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) {
Instance *instance = instance_shadow_cull_result[j];
- if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) {
+ if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask & RSG::light_storage->light_get_shadow_caster_mask(p_instance->base))) {
continue;
} else {
if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
@@ -2737,6 +2738,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
Projection projection;
bool vaspect = camera->vaspect;
bool is_orthogonal = false;
+ bool is_frustum = false;
switch (camera->type) {
case Camera::ORTHOGONAL: {
@@ -2765,10 +2767,11 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
camera->znear,
camera->zfar,
camera->vaspect);
+ is_frustum = true;
} break;
}
- camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, taa_frame_count, camera->visible_layers);
+ camera_data.set_camera(transform, projection, is_orthogonal, is_frustum, vaspect, jitter, taa_frame_count, camera->visible_layers);
} else {
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
@@ -2790,9 +2793,9 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu
}
if (view_count == 1) {
- camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers);
+ camera_data.set_camera(transforms[0], projections[0], false, false, camera->vaspect, jitter, p_jitter_phase_count, camera->visible_layers);
} else if (view_count == 2) {
- camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect);
+ camera_data.set_multiview_camera(view_count, transforms, projections, false, false, camera->vaspect);
} else {
// this won't be called (see fail check above) but keeping this comment to indicate we may support more then 2 views in the future...
}
@@ -3036,6 +3039,10 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
for (const Instance *E : geom->lights) {
InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
+ if (!(RSG::light_storage->light_get_cull_mask(E->base) & idata.layer_mask)) {
+ continue;
+ }
+
instance_pair_buffer[idx++] = light->instance;
if (idx == MAX_INSTANCE_PAIRS) {
break;
@@ -3140,7 +3147,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
- if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) {
+ if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && (LAYER_CHECK & cull_data.cull->shadows[j].caster_mask)) {
cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
mesh_visible = true;
}
@@ -3636,7 +3643,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend
RENDER_TIMESTAMP("Render Empty 3D Scene");
RendererSceneRender::CameraData camera_data;
- camera_data.set_camera(Transform3D(), Projection(), true, false);
+ camera_data.set_camera(Transform3D(), Projection(), true, false, false);
scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), compositor, p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
@@ -3714,7 +3721,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RENDER_TIMESTAMP("Render ReflectionProbe, Step " + itos(p_step));
RendererSceneRender::CameraData camera_data;
- camera_data.set_camera(xform, cm, false, false);
+ camera_data.set_camera(xform, cm, false, false, false);
Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas);
_render_scene(&camera_data, render_buffers, environment, RID(), RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 5aae59eb51..82523fd4ef 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -1121,6 +1121,7 @@ public:
struct Cull {
struct Shadow {
RID light_instance;
+ uint32_t caster_mask;
struct Cascade {
Frustum frustum;
@@ -1255,6 +1256,7 @@ public:
PASS3(environment_set_bg_energy, RID, float, float)
PASS2(environment_set_canvas_max_layer, RID, int)
PASS6(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource)
+ PASS2(environment_set_camera_feed_id, RID, int)
PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
PASS1RC(RID, environment_get_sky, RID)
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index df403c5484..14b97918ec 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -72,7 +72,7 @@ public:
return false;
}
- float min_depth = -closest_point_view.z * 0.95f;
+ float min_depth = (closest_point - p_cam_position).length();
Vector2 rect_min = Vector2(FLT_MAX, FLT_MAX);
Vector2 rect_max = Vector2(FLT_MIN, FLT_MIN);
@@ -83,6 +83,10 @@ public:
Vector3 corner = Vector3(p_bounds[0] * c.x + p_bounds[3] * nc.x, p_bounds[1] * c.y + p_bounds[4] * nc.y, p_bounds[2] * c.z + p_bounds[5] * nc.z);
Vector3 view = p_cam_inv_transform.xform(corner);
+ if (p_cam_projection.is_orthogonal()) {
+ min_depth = MIN(min_depth, -view.z);
+ }
+
Plane vp = Plane(view, 1.0);
Plane projected = p_cam_projection.xform4(vp);
@@ -230,11 +234,11 @@ public:
RendererSceneOcclusionCull() {
singleton = this;
- };
+ }
virtual ~RendererSceneOcclusionCull() {
singleton = nullptr;
- };
+ }
};
#endif // RENDERER_SCENE_OCCLUSION_CULL_H
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 797ba7eaf7..07259f73d2 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -33,9 +33,10 @@
/////////////////////////////////////////////////////////////////////////////
// CameraData
-void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter, float p_taa_frame_count, const uint32_t p_visible_layers) {
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect, const Vector2 &p_taa_jitter, float p_taa_frame_count, const uint32_t p_visible_layers) {
view_count = 1;
is_orthogonal = p_is_orthogonal;
+ is_frustum = p_is_frustum;
vaspect = p_vaspect;
main_transform = p_transform;
@@ -48,12 +49,13 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
taa_frame_count = p_taa_frame_count;
}
-void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) {
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect) {
ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
visible_layers = 0xFFFFFFFF;
view_count = p_view_count;
is_orthogonal = p_is_orthogonal;
+ is_frustum = p_is_frustum;
vaspect = p_vaspect;
Vector<Plane> planes[2];
@@ -349,6 +351,14 @@ RS::EnvironmentReflectionSource RendererSceneRender::environment_get_reflection_
return environment_storage.environment_get_reflection_source(p_env);
}
+void RendererSceneRender::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) {
+ environment_storage.environment_set_camera_feed_id(p_env, p_camera_feed_id);
+}
+
+int RendererSceneRender::environment_get_camera_feed_id(RID p_env) const {
+ return environment_storage.environment_get_camera_feed_id(p_env);
+}
+
// Tonemap
void RendererSceneRender::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) {
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 4d81a9b6a3..99418e0411 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -118,10 +118,7 @@ public:
void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value);
void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
-#endif
RS::EnvironmentBG environment_get_background(RID p_env) const;
RID environment_get_sky(RID p_env) const;
@@ -136,6 +133,7 @@ public:
float environment_get_ambient_light_energy(RID p_env) const;
float environment_get_ambient_sky_contribution(RID p_env) const;
RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
+ int environment_get_camera_feed_id(RID p_env) const;
// Tonemap
void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white);
@@ -302,6 +300,7 @@ public:
// flags
uint32_t view_count;
bool is_orthogonal;
+ bool is_frustum;
uint32_t visible_layers;
bool vaspect;
@@ -314,8 +313,8 @@ public:
Vector2 taa_jitter;
float taa_frame_count = 0.0f;
- void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), float p_taa_frame_count = 0.0f, uint32_t p_visible_layers = 0xFFFFFFFF);
- void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
+ void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2(), float p_taa_frame_count = 0.0f, uint32_t p_visible_layers = 0xFFFFFFFF);
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_is_frustum, bool p_vaspect);
};
virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_compositor, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RenderingMethod::RenderInfo *r_render_info = nullptr) = 0;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 942d5631e4..cc67873b24 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -1260,8 +1260,6 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
write_ptr = driver->buffer_map(transfer_worker->staging_buffer);
ERR_FAIL_NULL_V(write_ptr, ERR_CANT_CREATE);
- write_ptr += staging_worker_offset;
-
if (driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
// Transition the texture to the optimal layout.
RDD::TextureBarrier tb;
@@ -1303,11 +1301,12 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
if (copy_pass) {
const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z;
- _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size);
- write_ptr += to_allocate;
+ uint64_t staging_buffer_offset = staging_worker_offset + staging_local_offset;
+ uint8_t *write_ptr_mipmap_layer = write_ptr + staging_buffer_offset;
+ _copy_region_block_or_regular(read_ptr_mipmap_layer, write_ptr_mipmap_layer, 0, 0, width, width, height, block_w, block_h, pitch, pixel_size, block_size);
RDD::BufferTextureCopyRegion copy_region;
- copy_region.buffer_offset = staging_worker_offset + staging_local_offset;
+ copy_region.buffer_offset = staging_buffer_offset;
copy_region.texture_subresources.aspect = texture->read_aspect_flags;
copy_region.texture_subresources.mipmap = mm_i;
copy_region.texture_subresources.base_layer = p_layer;
@@ -3758,6 +3757,15 @@ int RenderingDevice::screen_get_height(DisplayServer::WindowID p_screen) const {
return context->surface_get_height(surface);
}
+int RenderingDevice::screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen) const {
+ _THREAD_SAFE_METHOD_
+
+ HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
+ ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), ERR_CANT_CREATE, "A swap chain was not created for the screen.");
+
+ return driver->swap_chain_get_pre_rotation_degrees(it->value);
+}
+
RenderingDevice::FramebufferFormatID RenderingDevice::screen_get_framebuffer_format(DisplayServer::WindowID p_screen) const {
_THREAD_SAFE_METHOD_
@@ -4441,6 +4449,117 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
dl->state.draw_count++;
}
+void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) {
+ ERR_RENDER_THREAD_GUARD();
+
+ DrawList *dl = _get_draw_list_ptr(p_list);
+ ERR_FAIL_NULL(dl);
+
+ Buffer *buffer = storage_buffer_owner.get_or_null(p_buffer);
+ ERR_FAIL_NULL(buffer);
+
+ ERR_FAIL_COND_MSG(!buffer->usage.has_flag(RDD::BUFFER_USAGE_INDIRECT_BIT), "Buffer provided was not created to do indirect dispatch.");
+
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
+#endif
+
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(!dl->validation.pipeline_active,
+ "No render pipeline was set before attempting to draw.");
+ if (dl->validation.pipeline_vertex_format != INVALID_ID) {
+ // Pipeline uses vertices, validate format.
+ ERR_FAIL_COND_MSG(dl->validation.vertex_format == INVALID_ID,
+ "No vertex array was bound, and render pipeline expects vertices.");
+ // Make sure format is right.
+ ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format != dl->validation.vertex_format,
+ "The vertex format used to create the pipeline does not match the vertex format bound.");
+ }
+
+ if (dl->validation.pipeline_push_constant_size > 0) {
+ // Using push constants, check that they were supplied.
+ ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_supplied,
+ "The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
+ }
+#endif
+
+#ifdef DEBUG_ENABLED
+ for (uint32_t i = 0; i < dl->state.set_count; i++) {
+ if (dl->state.sets[i].pipeline_expected_format == 0) {
+ // Nothing expected by this pipeline.
+ continue;
+ }
+
+ if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) {
+ if (dl->state.sets[i].uniform_set_format == 0) {
+ ERR_FAIL_MSG(vformat("Uniforms were never supplied for set (%d) at the time of drawing, which are required by the pipeline.", i));
+ } else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) {
+ UniformSet *us = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set);
+ ERR_FAIL_MSG(vformat("Uniforms supplied for set (%d):\n%s\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(us->shader_id, us->shader_set), _shader_uniform_debug(dl->state.pipeline_shader)));
+ } else {
+ ERR_FAIL_MSG(vformat("Uniforms supplied for set (%s, which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n%s", i, _shader_uniform_debug(dl->state.pipeline_shader)));
+ }
+ }
+ }
+#endif
+
+ // Prepare descriptor sets if the API doesn't use pipeline barriers.
+ if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
+ for (uint32_t i = 0; i < dl->state.set_count; i++) {
+ if (dl->state.sets[i].pipeline_expected_format == 0) {
+ // Nothing expected by this pipeline.
+ continue;
+ }
+
+ draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i);
+ }
+ }
+
+ // Bind descriptor sets.
+ for (uint32_t i = 0; i < dl->state.set_count; i++) {
+ if (dl->state.sets[i].pipeline_expected_format == 0) {
+ continue; // Nothing expected by this pipeline.
+ }
+ if (!dl->state.sets[i].bound) {
+ // All good, see if this requires re-binding.
+ draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i);
+
+ UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set);
+ _uniform_set_update_shared(uniform_set);
+
+ draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
+
+ dl->state.sets[i].bound = true;
+ }
+ }
+
+ if (p_use_indices) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(!dl->validation.index_array_count,
+ "Draw command requested indices, but no index buffer was set.");
+
+ ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices,
+ "The usage of restart indices in index buffer does not match the render primitive in the pipeline.");
+#endif
+
+ ERR_FAIL_COND_MSG(p_offset + 20 > buffer->size, "Offset provided (+20) is past the end of buffer.");
+
+ draw_graph.add_draw_list_draw_indexed_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride);
+ } else {
+ ERR_FAIL_COND_MSG(p_offset + 16 > buffer->size, "Offset provided (+16) is past the end of buffer.");
+
+ draw_graph.add_draw_list_draw_indirect(buffer->driver_id, p_offset, p_draw_count, p_stride);
+ }
+
+ dl->state.draw_count++;
+
+ if (buffer->draw_tracker != nullptr) {
+ draw_graph.add_draw_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
+ }
+
+ _check_transfer_worker_buffer(buffer);
+}
+
void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) {
ERR_RENDER_THREAD_GUARD();
@@ -6553,6 +6672,12 @@ void RenderingDevice::finalize() {
ERR_FAIL_COND(reverse_dependency_map.size());
}
+void RenderingDevice::_set_max_fps(int p_max_fps) {
+ for (const KeyValue<DisplayServer::WindowID, RDD::SwapChainID> &it : screen_swap_chains) {
+ driver->swap_chain_set_max_fps(it.value, p_max_fps);
+ }
+}
+
RenderingDevice *RenderingDevice::create_local_device() {
RenderingDevice *rd = memnew(RenderingDevice);
rd->initialize(context);
@@ -6651,6 +6776,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_set_push_constant", "draw_list", "buffer", "size_bytes"), &RenderingDevice::_draw_list_set_push_constant);
ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("draw_list_draw_indirect", "draw_list", "use_indices", "buffer", "offset", "draw_count", "stride"), &RenderingDevice::draw_list_draw_indirect, DEFVAL(0), DEFVAL(1), DEFVAL(0));
ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2()));
ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
@@ -7260,6 +7386,10 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_PASS);
}
+void RenderingDevice::make_current() {
+ render_thread_id = Thread::get_caller_id();
+}
+
RenderingDevice::~RenderingDevice() {
finalize();
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 71ffbfbd88..9939df976f 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1083,6 +1083,7 @@ public:
Error screen_prepare_for_drawing(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
int screen_get_width(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
int screen_get_height(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
+ int screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
FramebufferFormatID screen_get_framebuffer_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
Error screen_free(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
@@ -1186,6 +1187,7 @@ public:
void draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size);
void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0);
+ void draw_list_draw_indirect(DrawListID p_list, bool p_use_indices, RID p_buffer, uint32_t p_offset = 0, uint32_t p_draw_count = 1, uint32_t p_stride = 0);
void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect);
void draw_list_disable_scissor(DrawListID p_list);
@@ -1427,6 +1429,8 @@ public:
Error initialize(RenderingContextDriver *p_context, DisplayServer::WindowID p_main_window = DisplayServer::INVALID_WINDOW_ID);
void finalize();
+ void _set_max_fps(int p_max_fps);
+
void free(RID p_id);
/****************/
@@ -1496,6 +1500,8 @@ public:
static RenderingDevice *get_singleton();
+ void make_current();
+
RenderingDevice();
~RenderingDevice();
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index d9ca286b15..e41a56b0a3 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -31,7 +31,10 @@
#include "rendering_device_binds.h"
Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) {
- ERR_FAIL_NULL_V(RenderingDevice::get_singleton(), ERR_UNAVAILABLE);
+ ERR_FAIL_NULL_V_MSG(
+ RenderingDevice::get_singleton(),
+ ERR_UNAVAILABLE,
+ "Cannot import custom .glsl shaders when running without a RenderingDevice. This can happen if you are using the headless more or the Compatibility backend.");
Vector<String> lines = p_text.split("\n");
diff --git a/servers/rendering/rendering_device_driver.cpp b/servers/rendering/rendering_device_driver.cpp
index 9ff7b83215..c1a3f34af8 100644
--- a/servers/rendering/rendering_device_driver.cpp
+++ b/servers/rendering/rendering_device_driver.cpp
@@ -376,6 +376,8 @@ uint64_t RenderingDeviceDriver::api_trait_get(ApiTrait p_trait) {
return true;
case API_TRAIT_USE_GENERAL_IN_COPY_QUEUES:
return false;
+ case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS:
+ return false;
default:
ERR_FAIL_V(0);
}
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index 637d52c060..d2d14676db 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -120,9 +120,9 @@ struct VersatileResourceTemplate {
class RenderingDeviceDriver : public RenderingDeviceCommons {
public:
struct ID {
- size_t id = 0;
+ uint64_t id = 0;
_ALWAYS_INLINE_ ID() = default;
- _ALWAYS_INLINE_ ID(size_t p_id) :
+ _ALWAYS_INLINE_ ID(uint64_t p_id) :
id(p_id) {}
};
@@ -138,11 +138,9 @@ public:
_ALWAYS_INLINE_ bool operator!=(const m_name##ID &p_other) const { return id != p_other.id; } \
_ALWAYS_INLINE_ m_name##ID(const m_name##ID &p_other) : ID(p_other.id) {} \
_ALWAYS_INLINE_ explicit m_name##ID(uint64_t p_int) : ID(p_int) {} \
- _ALWAYS_INLINE_ explicit m_name##ID(void *p_ptr) : ID((size_t)p_ptr) {} \
+ _ALWAYS_INLINE_ explicit m_name##ID(void *p_ptr) : ID((uint64_t)p_ptr) {} \
_ALWAYS_INLINE_ m_name##ID() = default; \
- }; \
- /* Ensure type-punnable to pointer. Makes some things easier.*/ \
- static_assert(sizeof(m_name##ID) == sizeof(void *));
+ };
// Id types declared before anything else to prevent cyclic dependencies between the different concerns.
DEFINE_ID(Buffer);
@@ -454,9 +452,16 @@ public:
// Retrieve the render pass that can be used to draw on the swap chain's framebuffers.
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) = 0;
+ // Retrieve the rotation in degrees to apply as a pre-transform. Usually 0 on PC. May be 0, 90, 180 & 270 on Android.
+ virtual int swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) { return 0; }
+
// Retrieve the format used by the swap chain's framebuffers.
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) = 0;
+ // Tells the swapchain the max_fps so it can use the proper frame pacing.
+ // Android uses this with Swappy library. Some implementations or platforms may ignore this hint.
+ virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) {}
+
// Wait until all rendering associated to the swap chain is finished before deleting it.
virtual void swap_chain_free(SwapChainID p_swap_chain) = 0;
@@ -752,6 +757,7 @@ public:
API_TRAIT_SECONDARY_VIEWPORT_SCISSOR,
API_TRAIT_CLEARS_WITH_COPY_ENGINE,
API_TRAIT_USE_GENERAL_IN_COPY_QUEUES,
+ API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS,
};
enum ShaderChangeInvalidation {
diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp
index 0ecd818805..ec2f336f3c 100644
--- a/servers/rendering/rendering_device_graph.cpp
+++ b/servers/rendering/rendering_device_graph.cpp
@@ -34,7 +34,6 @@
#define FORCE_FULL_ACCESS_BITS 0
#define PRINT_RESOURCE_TRACKER_TOTAL 0
#define PRINT_COMMAND_RECORDING 0
-#define INSERT_BREADCRUMBS 1
RenderingDeviceGraph::RenderingDeviceGraph() {
driver_honors_barriers = false;
@@ -141,6 +140,25 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage
#endif
}
+bool RenderingDeviceGraph::_check_command_intersection(ResourceTracker *p_resource_tracker, int32_t p_previous_command_index, int32_t p_command_index) const {
+ if (p_resource_tracker->usage != RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE && p_resource_tracker->usage != RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE) {
+ // We don't check possible intersections for usages that aren't consecutive color or depth writes.
+ return true;
+ }
+
+ const uint32_t previous_command_data_offset = command_data_offsets[p_previous_command_index];
+ const uint32_t current_command_data_offset = command_data_offsets[p_command_index];
+ const RecordedDrawListCommand &previous_draw_list_command = *reinterpret_cast<const RecordedDrawListCommand *>(&command_data[previous_command_data_offset]);
+ const RecordedDrawListCommand &current_draw_list_command = *reinterpret_cast<const RecordedDrawListCommand *>(&command_data[current_command_data_offset]);
+ if (previous_draw_list_command.type != RecordedCommand::TYPE_DRAW_LIST || current_draw_list_command.type != RecordedCommand::TYPE_DRAW_LIST) {
+ // We don't check possible intersections if both commands aren't draw lists.
+ return true;
+ }
+
+ // We check if the region used by both draw lists have an intersection.
+ return previous_draw_list_command.region.intersects(current_draw_list_command.region);
+}
+
int32_t RenderingDeviceGraph::_add_to_command_list(int32_t p_command_index, int32_t p_list_index) {
DEV_ASSERT(p_command_index < int32_t(command_count));
DEV_ASSERT(p_list_index < int32_t(command_list_nodes.size()));
@@ -426,11 +444,9 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
#if USE_BUFFER_BARRIERS
_add_buffer_barrier_to_command(resource_tracker->buffer_driver_id, resource_tracker->usage_access, new_usage_access, r_command->buffer_barrier_index, r_command->buffer_barrier_count);
#endif
- // FIXME: Memory barriers are currently pushed regardless of whether buffer barriers are being used or not. Refer to the comment on the
- // definition of USE_BUFFER_BARRIERS for the reason behind this. This can be fixed to be one case or the other once it's been confirmed
- // the buffer and memory barrier behavior discrepancy has been solved.
- r_command->memory_barrier.src_access = resource_tracker->usage_access;
- r_command->memory_barrier.dst_access = new_usage_access;
+ // Memory barriers are pushed regardless of buffer barriers being used or not.
+ r_command->memory_barrier.src_access = r_command->memory_barrier.src_access | resource_tracker->usage_access;
+ r_command->memory_barrier.dst_access = r_command->memory_barrier.dst_access | new_usage_access;
} else {
DEV_ASSERT(false && "Resource tracker does not contain a valid buffer or texture ID.");
}
@@ -450,10 +466,12 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
if (different_usage) {
// Even if the usage of the resource isn't a write usage explicitly, a different usage implies a transition and it should therefore be considered a write.
- write_usage = true;
+ // In the case of buffers however, this is not exactly necessary if the driver does not consider different buffer usages as different states.
+ write_usage = write_usage || bool(resource_tracker->texture_driver_id) || driver_buffers_require_transitions;
resource_tracker->usage = new_resource_usage;
}
+ bool command_intersection_failed = false;
if (search_tracker->write_command_or_list_index >= 0) {
if (search_tracker->write_command_list_enabled) {
// Make this command adjacent to any commands that wrote to this resource and intersect with the slice if it applies.
@@ -465,7 +483,7 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
if (!resource_has_parent || search_tracker_rect.intersects(write_list_node.subresources)) {
if (write_list_node.command_index == p_command_index) {
ERR_FAIL_COND_MSG(!resource_has_parent, "Command can't have itself as a dependency.");
- } else {
+ } else if (_check_command_intersection(resource_tracker, write_list_node.command_index, p_command_index)) {
// Command is dependent on this command. Add this command to the adjacency list of the write command.
_add_adjacent_command(write_list_node.command_index, p_command_index, r_command);
@@ -481,6 +499,8 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
write_list_index = write_list_node.next_list_index;
continue;
}
+ } else {
+ command_intersection_failed = true;
}
}
@@ -491,14 +511,16 @@ void RenderingDeviceGraph::_add_command_to_graph(ResourceTracker **p_resource_tr
// The index is just the latest command index that wrote to the resource.
if (search_tracker->write_command_or_list_index == p_command_index) {
ERR_FAIL_MSG("Command can't have itself as a dependency.");
- } else {
+ } else if (_check_command_intersection(resource_tracker, search_tracker->write_command_or_list_index, p_command_index)) {
_add_adjacent_command(search_tracker->write_command_or_list_index, p_command_index, r_command);
+ } else {
+ command_intersection_failed = true;
}
}
}
if (write_usage) {
- if (resource_has_parent) {
+ if (resource_has_parent || command_intersection_failed) {
if (!search_tracker->write_command_list_enabled && search_tracker->write_command_or_list_index >= 0) {
// Write command list was not being used but there was a write command recorded. Add a new node with the entire parent resource's subresources and the recorded command index to the list.
const RDD::TextureSubresourceRange &tracker_subresources = search_tracker->texture_subresources;
@@ -709,6 +731,16 @@ void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command
driver->command_render_draw_indexed(p_command_buffer, draw_indexed_instruction->index_count, draw_indexed_instruction->instance_count, draw_indexed_instruction->first_index, 0, 0);
instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction);
} break;
+ case DrawListInstruction::TYPE_DRAW_INDIRECT: {
+ const DrawListDrawIndirectInstruction *draw_indirect_instruction = reinterpret_cast<const DrawListDrawIndirectInstruction *>(instruction);
+ driver->command_render_draw_indirect(p_command_buffer, draw_indirect_instruction->buffer, draw_indirect_instruction->offset, draw_indirect_instruction->draw_count, draw_indirect_instruction->stride);
+ instruction_data_cursor += sizeof(DrawListDrawIndirectInstruction);
+ } break;
+ case DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT: {
+ const DrawListDrawIndexedIndirectInstruction *draw_indexed_indirect_instruction = reinterpret_cast<const DrawListDrawIndexedIndirectInstruction *>(instruction);
+ driver->command_render_draw_indexed_indirect(p_command_buffer, draw_indexed_indirect_instruction->buffer, draw_indexed_indirect_instruction->offset, draw_indexed_indirect_instruction->draw_count, draw_indexed_indirect_instruction->stride);
+ instruction_data_cursor += sizeof(DrawListDrawIndexedIndirectInstruction);
+ } break;
case DrawListInstruction::TYPE_EXECUTE_COMMANDS: {
const DrawListExecuteCommandsInstruction *execute_commands_instruction = reinterpret_cast<const DrawListExecuteCommandsInstruction *>(instruction);
driver->command_buffer_execute_secondary(p_command_buffer, execute_commands_instruction->command_buffer);
@@ -833,7 +865,7 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC
const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command);
const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count);
-#if INSERT_BREADCRUMBS
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
driver->command_insert_breadcrumb(r_command_buffer, draw_list_command->breadcrumb);
#endif
driver->command_begin_render_pass(r_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values);
@@ -1190,6 +1222,16 @@ void RenderingDeviceGraph::_print_draw_list(const uint8_t *p_instruction_data, u
print_line("\tDRAW INDICES", draw_indexed_instruction->index_count, "INSTANCES", draw_indexed_instruction->instance_count, "FIRST INDEX", draw_indexed_instruction->first_index);
instruction_data_cursor += sizeof(DrawListDrawIndexedInstruction);
} break;
+ case DrawListInstruction::TYPE_DRAW_INDIRECT: {
+ const DrawListDrawIndirectInstruction *draw_indirect_instruction = reinterpret_cast<const DrawListDrawIndirectInstruction *>(instruction);
+ print_line("\tDRAW INDIRECT BUFFER ID", itos(draw_indirect_instruction->buffer.id), "OFFSET", draw_indirect_instruction->offset, "DRAW COUNT", draw_indirect_instruction->draw_count, "STRIDE", draw_indirect_instruction->stride);
+ instruction_data_cursor += sizeof(DrawListDrawIndirectInstruction);
+ } break;
+ case DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT: {
+ const DrawListDrawIndexedIndirectInstruction *draw_indexed_indirect_instruction = reinterpret_cast<const DrawListDrawIndexedIndirectInstruction *>(instruction);
+ print_line("\tDRAW INDEXED INDIRECT BUFFER ID", itos(draw_indexed_indirect_instruction->buffer.id), "OFFSET", draw_indexed_indirect_instruction->offset, "DRAW COUNT", draw_indexed_indirect_instruction->draw_count, "STRIDE", draw_indexed_indirect_instruction->stride);
+ instruction_data_cursor += sizeof(DrawListDrawIndexedIndirectInstruction);
+ } break;
case DrawListInstruction::TYPE_EXECUTE_COMMANDS: {
print_line("\tEXECUTE COMMANDS");
instruction_data_cursor += sizeof(DrawListExecuteCommandsInstruction);
@@ -1299,6 +1341,7 @@ void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Dev
driver_honors_barriers = driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS);
driver_clears_with_copy_engine = driver->api_trait_get(RDD::API_TRAIT_CLEARS_WITH_COPY_ENGINE);
+ driver_buffers_require_transitions = driver->api_trait_get(RDD::API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS);
}
void RenderingDeviceGraph::finalize() {
@@ -1416,7 +1459,9 @@ void RenderingDeviceGraph::add_buffer_update(RDD::BufferID p_dst, ResourceTracke
void RenderingDeviceGraph::add_compute_list_begin(RDD::BreadcrumbMarker p_phase, uint32_t p_breadcrumb_data) {
compute_instruction_list.clear();
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
compute_instruction_list.breadcrumb = p_breadcrumb_data | (p_phase & ((1 << 16) - 1));
+#endif
compute_instruction_list.index++;
}
@@ -1512,7 +1557,9 @@ void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass,
draw_instruction_list.render_pass = p_render_pass;
draw_instruction_list.framebuffer = p_framebuffer;
draw_instruction_list.region = p_region;
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
draw_instruction_list.breadcrumb = p_breadcrumb;
+#endif
draw_instruction_list.clear_values.resize(p_clear_values.size());
for (uint32_t i = 0; i < p_clear_values.size(); i++) {
draw_instruction_list.clear_values[i] = p_clear_values[i];
@@ -1608,6 +1655,26 @@ void RenderingDeviceGraph::add_draw_list_draw_indexed(uint32_t p_index_count, ui
instruction->first_index = p_first_index;
}
+void RenderingDeviceGraph::add_draw_list_draw_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) {
+ DrawListDrawIndirectInstruction *instruction = reinterpret_cast<DrawListDrawIndirectInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndirectInstruction)));
+ instruction->type = DrawListInstruction::TYPE_DRAW_INDIRECT;
+ instruction->buffer = p_buffer;
+ instruction->offset = p_offset;
+ instruction->draw_count = p_draw_count;
+ instruction->stride = p_stride;
+ draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT);
+}
+
+void RenderingDeviceGraph::add_draw_list_draw_indexed_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride) {
+ DrawListDrawIndexedIndirectInstruction *instruction = reinterpret_cast<DrawListDrawIndexedIndirectInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListDrawIndexedIndirectInstruction)));
+ instruction->type = DrawListInstruction::TYPE_DRAW_INDEXED_INDIRECT;
+ instruction->buffer = p_buffer;
+ instruction->offset = p_offset;
+ instruction->draw_count = p_draw_count;
+ instruction->stride = p_stride;
+ draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_DRAW_INDIRECT_BIT);
+}
+
void RenderingDeviceGraph::add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer) {
DrawListExecuteCommandsInstruction *instruction = reinterpret_cast<DrawListExecuteCommandsInstruction *>(_allocate_draw_list_instruction(sizeof(DrawListExecuteCommandsInstruction)));
instruction->type = DrawListInstruction::TYPE_EXECUTE_COMMANDS;
@@ -1723,7 +1790,9 @@ void RenderingDeviceGraph::add_draw_list_end() {
command->framebuffer = draw_instruction_list.framebuffer;
command->command_buffer_type = command_buffer_type;
command->region = draw_instruction_list.region;
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
command->breadcrumb = draw_instruction_list.breadcrumb;
+#endif
command->clear_values_count = draw_instruction_list.clear_values.size();
RDD::RenderPassClearValue *clear_values = command->clear_values();
diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h
index 0534d4ee1e..9ddd70bc80 100644
--- a/servers/rendering/rendering_device_graph.h
+++ b/servers/rendering/rendering_device_graph.h
@@ -69,6 +69,8 @@ public:
TYPE_CLEAR_ATTACHMENTS,
TYPE_DRAW,
TYPE_DRAW_INDEXED,
+ TYPE_DRAW_INDIRECT,
+ TYPE_DRAW_INDEXED_INDIRECT,
TYPE_EXECUTE_COMMANDS,
TYPE_NEXT_SUBPASS,
TYPE_SET_BLEND_CONSTANTS,
@@ -221,14 +223,18 @@ private:
};
struct ComputeInstructionList : InstructionList {
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
uint32_t breadcrumb;
+#endif
};
struct DrawInstructionList : InstructionList {
RDD::RenderPassID render_pass;
RDD::FramebufferID framebuffer;
Rect2i region;
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
uint32_t breadcrumb;
+#endif
LocalVector<RDD::RenderPassClearValue> clear_values;
};
@@ -317,7 +323,9 @@ private:
RDD::FramebufferID framebuffer;
RDD::CommandBufferType command_buffer_type;
Rect2i region;
+#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
uint32_t breadcrumb = 0;
+#endif
uint32_t clear_values_count = 0;
_FORCE_INLINE_ RDD::RenderPassClearValue *clear_values() {
@@ -466,6 +474,20 @@ private:
uint32_t first_index = 0;
};
+ struct DrawListDrawIndirectInstruction : DrawListInstruction {
+ RDD::BufferID buffer;
+ uint32_t offset = 0;
+ uint32_t draw_count = 0;
+ uint32_t stride = 0;
+ };
+
+ struct DrawListDrawIndexedIndirectInstruction : DrawListInstruction {
+ RDD::BufferID buffer;
+ uint32_t offset = 0;
+ uint32_t draw_count = 0;
+ uint32_t stride = 0;
+ };
+
struct DrawListEndRenderPassInstruction : DrawListInstruction {
// No contents.
};
@@ -615,6 +637,7 @@ private:
BarrierGroup barrier_group;
bool driver_honors_barriers : 1;
bool driver_clears_with_copy_engine : 1;
+ bool driver_buffers_require_transitions : 1;
WorkaroundsState workarounds_state;
TightLocalVector<Frame> frames;
uint32_t frame = 0;
@@ -626,6 +649,7 @@ private:
static bool _is_write_usage(ResourceUsage p_usage);
static RDD::TextureLayout _usage_to_image_layout(ResourceUsage p_usage);
static RDD::BarrierAccessBits _usage_to_access_bits(ResourceUsage p_usage);
+ bool _check_command_intersection(ResourceTracker *p_resource_tracker, int32_t p_previous_command_index, int32_t p_command_index) const;
int32_t _add_to_command_list(int32_t p_command_index, int32_t p_list_index);
void _add_adjacent_command(int32_t p_previous_command_index, int32_t p_command_index, RecordedCommand *r_command);
int32_t _add_to_slice_read_list(int32_t p_command_index, Rect2i p_subresources, int32_t p_list_index);
@@ -678,6 +702,8 @@ public:
void add_draw_list_clear_attachments(VectorView<RDD::AttachmentClear> p_attachments_clear, VectorView<Rect2i> p_attachments_clear_rect);
void add_draw_list_draw(uint32_t p_vertex_count, uint32_t p_instance_count);
void add_draw_list_draw_indexed(uint32_t p_index_count, uint32_t p_instance_count, uint32_t p_first_index);
+ void add_draw_list_draw_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride);
+ void add_draw_list_draw_indexed_indirect(RDD::BufferID p_buffer, uint32_t p_offset, uint32_t p_draw_count, uint32_t p_stride);
void add_draw_list_execute_commands(RDD::CommandBufferID p_command_buffer);
void add_draw_list_next_subpass(RDD::CommandBufferType p_command_buffer_type);
void add_draw_list_set_blend_constants(const Color &p_color);
diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h
index 4c277ac215..34f11924ce 100644
--- a/servers/rendering/rendering_method.h
+++ b/servers/rendering/rendering_method.h
@@ -168,6 +168,7 @@ public:
virtual void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
+ virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0;
virtual RID environment_get_sky(RID p_env) const = 0;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 20f1f9ad6f..2ec693cbbf 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -370,6 +370,8 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const {
void RenderingServerDefault::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
server_thread = Thread::get_caller_id();
server_task_id = p_pump_task_id;
+ // This is needed because the main RD is created on the main thread.
+ RenderingDevice::get_singleton()->make_current();
}
void RenderingServerDefault::_thread_exit() {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 225a67fb52..5c3ee513c7 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -443,6 +443,7 @@ public:
FUNC2(light_set_cull_mask, RID, uint32_t)
FUNC5(light_set_distance_fade, RID, bool, float, float, float)
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
+ FUNC2(light_set_shadow_caster_mask, RID, uint32_t)
FUNC2(light_set_bake_mode, RID, LightBakeMode)
FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t)
@@ -785,10 +786,8 @@ public:
FUNC2(environment_set_canvas_max_layer, RID, int)
FUNC6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource)
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
FUNC2(environment_set_camera_feed_id, RID, int)
-#endif
+
FUNC6(environment_set_ssr, RID, bool, int, float, float, float)
FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 119ac677eb..f52963f98f 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -489,7 +489,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
struct_code += _typestr(m->datatype);
}
struct_code += " ";
- struct_code += m->name;
+ struct_code += _mkid(m->name);
if (m->array_size > 0) {
struct_code += "[";
struct_code += itos(m->array_size);
@@ -1448,7 +1448,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
} break;
case SL::Node::NODE_TYPE_MEMBER: {
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
- code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name;
+ String name;
+ if (mnode->basetype == SL::TYPE_STRUCT) {
+ name = _mkid(mnode->name);
+ } else {
+ name = mnode->name;
+ }
+ code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + name;
if (mnode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index b6770c773c..7c4128b0e3 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -356,7 +356,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_CF_BREAK, "break", CF_BLOCK, {}, {} },
{ TK_CF_CONTINUE, "continue", CF_BLOCK, {}, {} },
{ TK_CF_RETURN, "return", CF_BLOCK, {}, {} },
- { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "fragment" } },
+ { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "vertex" } },
// function specifier keywords
@@ -3565,28 +3565,33 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
int argcount = args.size();
- if (p_function_info.stage_functions.has(name)) {
- //stage based function
- const StageFunctionInfo &sf = p_function_info.stage_functions[name];
- if (argcount != sf.arguments.size()) {
- _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size()));
- return false;
- }
- //validate arguments
- for (int i = 0; i < argcount; i++) {
- if (args[i] != sf.arguments[i].type) {
- _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type)));
- return false;
- }
- }
+ if (stages) {
+ // Stage functions can be used in custom functions as well, that why need to check them all.
+ for (const KeyValue<StringName, FunctionInfo> &E : *stages) {
+ if (E.value.stage_functions.has(name)) {
+ // Stage-based function.
+ const StageFunctionInfo &sf = E.value.stage_functions[name];
+ if (argcount != sf.arguments.size()) {
+ _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size()));
+ return false;
+ }
+ // Validate arguments.
+ for (int i = 0; i < argcount; i++) {
+ if (args[i] != sf.arguments[i].type) {
+ _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type)));
+ return false;
+ }
+ }
- if (r_ret_type) {
- *r_ret_type = sf.return_type;
- }
- if (r_ret_type_str) {
- *r_ret_type_str = "";
+ if (r_ret_type) {
+ *r_ret_type = sf.return_type;
+ }
+ if (r_ret_type_str) {
+ *r_ret_type_str = "";
+ }
+ return true;
+ }
}
- return true;
}
bool failed_builtin = false;
@@ -5937,22 +5942,35 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
calls_info[current_function].calls.push_back(&calls_info[name]);
}
- int idx = 0;
bool is_builtin = false;
- while (frag_only_func_defs[idx].name) {
- if (frag_only_func_defs[idx].name == name) {
- // If a built-in function not found for the current shader type, then it shouldn't be parsed further.
- if (!is_supported_frag_only_funcs) {
- _set_error(vformat(RTR("Built-in function '%s' is not supported for the '%s' shader type."), name, shader_type_identifier));
- return nullptr;
+ if (is_supported_frag_only_funcs && stages) {
+ for (const KeyValue<StringName, FunctionInfo> &E : *stages) {
+ if (E.value.stage_functions.has(name)) {
+ // Register usage of the restricted stage function.
+ calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos())));
+ is_builtin = true;
+ break;
}
- // Register usage of the restricted function.
- calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos())));
- is_builtin = true;
- break;
}
- idx++;
+ }
+
+ if (!is_builtin) {
+ int idx = 0;
+ while (frag_only_func_defs[idx].name) {
+ if (frag_only_func_defs[idx].name == name) {
+ // If a built-in function not found for the current shader type, then it shouldn't be parsed further.
+ if (!is_supported_frag_only_funcs) {
+ _set_error(vformat(RTR("Built-in function '%s' is not supported for the '%s' shader type."), name, shader_type_identifier));
+ return nullptr;
+ }
+ // Register usage of the restricted function.
+ calls_info[current_function].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>(name, CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, _get_tkpos())));
+ is_builtin = true;
+ break;
+ }
+ idx++;
+ }
}
// Recursively checks for the restricted function call.
@@ -8581,6 +8599,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
block = block->parent_block;
}
} else if (tk.type == TK_CF_DISCARD) {
+ if (!is_discard_supported) {
+ _set_error(vformat(RTR("Use of '%s' is not supported for the '%s' shader type."), "discard", shader_type_identifier));
+ return ERR_PARSE_ERROR;
+ }
+
//check return type
BlockNode *b = p_block;
while (b && !b->parent_function) {
@@ -8592,7 +8615,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (!b->parent_function->can_discard) {
- _set_error(vformat(RTR("Use of '%s' is not allowed here."), "discard"));
+ _set_error(vformat(RTR("'%s' cannot be used within the '%s' processor function."), "discard", b->parent_function->name));
return ERR_PARSE_ERROR;
}
@@ -8601,6 +8624,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
+
+ calls_info[b->parent_function->name].uses_restricted_items.push_back(Pair<StringName, CallInfo::Item>("discard", CallInfo::Item(CallInfo::Item::ITEM_TYPE_BUILTIN, pos)));
+
if (tk.type != TK_SEMICOLON) {
_set_expected_after_error(";", "discard");
return ERR_PARSE_ERROR;
@@ -8838,7 +8864,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions;
- is_supported_frag_only_funcs = shader_type_identifier == "canvas_item" || shader_type_identifier == "spatial" || shader_type_identifier == "sky";
+
+ is_discard_supported = shader_type_identifier == "canvas_item" || shader_type_identifier == "spatial";
+ is_supported_frag_only_funcs = is_discard_supported || shader_type_identifier == "sky";
const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
@@ -10332,6 +10360,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
+ } else {
+ func_node->can_discard = is_discard_supported; // Allow use it for custom functions (in supported shader types).
}
if (!function_overload_count.has(name)) {
@@ -10922,10 +10952,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
break; // Ignore hint keywords (parsed below).
}
if (keyword_list[i].flags & keyword_completion_context) {
- if (keyword_list[i].excluded_shader_types.has(shader_type_identifier)) {
- continue;
- }
- if (!keyword_list[i].functions.is_empty() && !keyword_list[i].functions.has(current_function)) {
+ if (keyword_list[i].excluded_shader_types.has(shader_type_identifier) || keyword_list[i].excluded_functions.has(current_function)) {
continue;
}
ScriptLanguage::CodeCompletionOption option(keyword_list[i].text, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
@@ -11160,9 +11187,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
int idx = 0;
bool low_end = RenderingServer::get_singleton()->is_low_end();
- if (stages && stages->has(skip_function)) {
- for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[skip_function].stage_functions) {
- matches.insert(String(E.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ if (stages) {
+ // Stage functions can be used in custom functions as well, that why need to check them all.
+ for (const KeyValue<StringName, FunctionInfo> &E : *stages) {
+ for (const KeyValue<StringName, StageFunctionInfo> &F : E.value.stage_functions) {
+ if (F.value.skip_function == skip_function && stages->has(skip_function)) {
+ continue;
+ }
+ matches.insert(String(F.key), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ }
}
}
@@ -11292,9 +11325,15 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
return OK;
}
- if (stages && stages->has(block_function)) {
- for (const KeyValue<StringName, StageFunctionInfo> &E : (*stages)[block_function].stage_functions) {
- if (completion_function == E.key) {
+ if (stages) {
+ // Stage functions can be used in custom functions as well, that why need to check them all.
+ for (const KeyValue<StringName, FunctionInfo> &S : *stages) {
+ for (const KeyValue<StringName, StageFunctionInfo> &E : S.value.stage_functions) {
+ // No need to check for the skip function here.
+ if (completion_function != E.key) {
+ continue;
+ }
+
calltip += get_datatype_name(E.value.return_type);
calltip += " ";
calltip += E.key;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index fb0a526230..4dade4d79f 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -859,6 +859,7 @@ public:
Vector<Argument> arguments;
DataType return_type = TYPE_VOID;
+ String skip_function;
};
struct ModeInfo {
@@ -934,7 +935,7 @@ private:
const char *text;
uint32_t flags;
const Vector<String> excluded_shader_types;
- const Vector<String> functions;
+ const Vector<String> excluded_functions;
};
static const KeyWord keyword_list[];
@@ -1150,6 +1151,7 @@ private:
const HashMap<StringName, FunctionInfo> *stages = nullptr;
bool is_supported_frag_only_funcs = false;
+ bool is_discard_supported = false;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
@@ -1211,7 +1213,7 @@ public:
struct ShaderCompileInfo {
HashMap<StringName, FunctionInfo> functions;
Vector<ModeInfo> render_modes;
- VaryingFunctionNames varying_function_names = VaryingFunctionNames();
+ VaryingFunctionNames varying_function_names;
HashSet<String> shader_types;
GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr;
bool is_include = false;
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
index 0e41a178b5..88ea74cdfc 100644
--- a/servers/rendering/shader_preprocessor.cpp
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -816,6 +816,11 @@ void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
}
if (state->defines.has(label)) {
+ if (state->defines[label]->is_builtin) {
+ set_error(vformat(RTR("Cannot use '%s' on built-in define."), "undef"), line);
+ return;
+ }
+
memdelete(state->defines[label]);
state->defines.erase(label);
}
@@ -1324,6 +1329,35 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
pp_state.current_filename = p_filename;
pp_state.save_regions = r_regions != nullptr;
}
+
+ // Built-in defines.
+ {
+ static HashMap<StringName, String> defines;
+
+ if (defines.is_empty()) {
+ const String rendering_method = OS::get_singleton()->get_current_rendering_method();
+
+ if (rendering_method == "forward_plus") {
+ defines["CURRENT_RENDERER"] = _MKSTR(2);
+ } else if (rendering_method == "mobile") {
+ defines["CURRENT_RENDERER"] = _MKSTR(1);
+ } else { // gl_compatibility
+ defines["CURRENT_RENDERER"] = _MKSTR(0);
+ }
+
+ defines["RENDERER_COMPATIBILITY"] = _MKSTR(0);
+ defines["RENDERER_MOBILE"] = _MKSTR(1);
+ defines["RENDERER_FORWARD_PLUS"] = _MKSTR(2);
+ }
+
+ for (const KeyValue<StringName, String> &E : defines) {
+ Define *define = memnew(Define);
+ define->is_builtin = true;
+ define->body = E.value;
+ pp_state.defines[E.key] = define;
+ }
+ }
+
Error err = preprocess(&pp_state, p_code, r_result);
if (err != OK) {
if (r_error_text) {
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
index 0a90aec958..b3d9594bcb 100644
--- a/servers/rendering/shader_preprocessor.h
+++ b/servers/rendering/shader_preprocessor.h
@@ -132,6 +132,7 @@ private:
struct Define {
Vector<String> arguments;
String body;
+ bool is_builtin = false;
};
struct Branch {
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index f498c0bf93..821009f07c 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -63,6 +63,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
@@ -96,8 +98,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MAIN_CAM_INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = constt(ShaderLanguage::TYPE_VEC3);
@@ -159,9 +159,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EYE_OFFSET"] = constt(ShaderLanguage::TYPE_VEC3);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT);
-
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["MODEL_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
@@ -203,8 +200,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CLIP_SPACE_FAR"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true;
@@ -284,6 +279,7 @@ ShaderTypes::ShaderTypes() {
{
ShaderLanguage::StageFunctionInfo func;
+ func.skip_function = "vertex";
func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("sdf_pos", ShaderLanguage::TYPE_VEC2));
func.return_type = ShaderLanguage::TYPE_FLOAT; //whether it could emit
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf"] = func;
@@ -297,6 +293,7 @@ ShaderTypes::ShaderTypes() {
{
ShaderLanguage::StageFunctionInfo func;
+ func.skip_function = "vertex";
func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("uv", ShaderLanguage::TYPE_VEC2));
func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["screen_uv_to_sdf"] = func;
diff --git a/servers/rendering/storage/camera_attributes_storage.h b/servers/rendering/storage/camera_attributes_storage.h
index 6fbcd3da7d..afb8ad23cf 100644
--- a/servers/rendering/storage/camera_attributes_storage.h
+++ b/servers/rendering/storage/camera_attributes_storage.h
@@ -72,8 +72,8 @@ public:
RendererCameraAttributes();
~RendererCameraAttributes();
- CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); };
- bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); };
+ CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); }
+ bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); }
RID camera_attributes_allocate();
void camera_attributes_initialize(RID p_rid);
diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp
index 1bbb5da6bb..e7556f9000 100644
--- a/servers/rendering/storage/environment_storage.cpp
+++ b/servers/rendering/storage/environment_storage.cpp
@@ -189,6 +189,18 @@ RS::EnvironmentReflectionSource RendererEnvironmentStorage::environment_get_refl
return env->reflection_source;
}
+void RendererEnvironmentStorage::environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL(env);
+ env->camera_feed_id = p_camera_feed_id;
+}
+
+int RendererEnvironmentStorage::environment_get_camera_feed_id(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL_V(env, -1);
+ return env->camera_feed_id;
+}
+
// Tonemap
void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) {
diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h
index 9f78808ff7..6fdc047ba2 100644
--- a/servers/rendering/storage/environment_storage.h
+++ b/servers/rendering/storage/environment_storage.h
@@ -57,6 +57,7 @@ private:
float ambient_light_energy = 1.0;
float ambient_sky_contribution = 1.0;
RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
+ int camera_feed_id = 0;
// Tonemap
RS::EnvironmentToneMapper tone_mapper;
@@ -181,10 +182,8 @@ public:
void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value);
void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
-// FIXME: Disabled during Vulkan refactoring, should be ported.
-#if 0
void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
-#endif
+ int environment_get_camera_feed_id(RID p_env) const;
RS::EnvironmentBG environment_get_background(RID p_env) const;
RID environment_get_sky(RID p_env) const;
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 6a0adfa596..1e149e3a97 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -59,6 +59,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) = 0;
+ virtual uint32_t light_get_shadow_caster_mask(RID p_light) const = 0;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp
index 96e6492854..6d18ae2f77 100644
--- a/servers/rendering/storage/render_scene_buffers.cpp
+++ b/servers/rendering/storage/render_scene_buffers.cpp
@@ -81,7 +81,7 @@ void RenderSceneBuffersExtension::_bind_methods() {
void RenderSceneBuffersExtension::configure(const RenderSceneBuffersConfiguration *p_config) {
GDVIRTUAL_CALL(_configure, p_config);
-};
+}
void RenderSceneBuffersExtension::set_fsr_sharpness(float p_fsr_sharpness) {
GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness);