summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp46
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h99
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp992
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h77
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp22
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h8
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp27
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp249
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h20
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp17
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp43
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp30
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h4
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl17
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl21
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl50
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl9
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl17
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp31
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp1
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp34
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp77
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h38
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp20
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h9
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp4
45 files changed, 1050 insertions, 1068 deletions
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 73a0c652a4..959a752fba 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -74,7 +74,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
cluster_debug.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_debug.shader);
}
- { // SPHERE
+ { // Sphere mesh data.
static const uint32_t icosphere_vertex_count = 42;
static const float icosphere_vertices[icosphere_vertex_count * 3] = {
0, 0, -1, 0.7236073, -0.5257253, -0.4472195, -0.276388, -0.8506492, -0.4472199, -0.8944262, 0, -0.4472156, -0.276388, 0.8506492, -0.4472199, 0.7236073, 0.5257253, -0.4472195, 0.276388, -0.8506492, 0.4472199, -0.7236073, -0.5257253, 0.4472195, -0.7236073, 0.5257253, 0.4472195, 0.276388, 0.8506492, 0.4472199, 0.8944262, 0, 0.4472156, 0, 0, 1, -0.1624555, -0.4999952, -0.8506544, 0.4253227, -0.3090114, -0.8506542, 0.2628688, -0.8090116, -0.5257377, 0.8506479, 0, -0.5257359, 0.4253227, 0.3090114, -0.8506542, -0.5257298, 0, -0.8506517, -0.6881894, -0.4999969, -0.5257362, -0.1624555, 0.4999952, -0.8506544, -0.6881894, 0.4999969, -0.5257362, 0.2628688, 0.8090116, -0.5257377, 0.9510579, -0.3090126, 0, 0.9510579, 0.3090126, 0, 0, -1, 0, 0.5877856, -0.8090167, 0, -0.9510579, -0.3090126, 0, -0.5877856, -0.8090167, 0, -0.5877856, 0.8090167, 0, -0.9510579, 0.3090126, 0, 0.5877856, 0.8090167, 0, 0, 1, 0, 0.6881894, -0.4999969, 0.5257362, -0.2628688, -0.8090116, 0.5257377, -0.8506479, 0, 0.5257359, -0.2628688, 0.8090116, 0.5257377, 0.6881894, 0.4999969, 0.5257362, 0.1624555, -0.4999952, 0.8506544, 0.5257298, 0, 0.8506517, -0.4253227, -0.3090114, 0.8506542, -0.4253227, 0.3090114, 0.8506542, 0.1624555, 0.4999952, 0.8506544
@@ -118,7 +118,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
sphere_overfit = 1.0 / min_d;
}
- { // CONE
+ { // Cone mesh data.
static const uint32_t cone_vertex_count = 99;
static const float cone_vertices[cone_vertex_count * 3] = {
0, 1, -1, 0.1950903, 0.9807853, -1, 0.3826835, 0.9238795, -1, 0.5555703, 0.8314696, -1, 0.7071068, 0.7071068, -1, 0.8314697, 0.5555702, -1, 0.9238795, 0.3826834, -1, 0.9807853, 0.1950903, -1, 1, 0, -1, 0.9807853, -0.1950902, -1, 0.9238796, -0.3826833, -1, 0.8314697, -0.5555702, -1, 0.7071068, -0.7071068, -1, 0.5555702, -0.8314697, -1, 0.3826833, -0.9238796, -1, 0.1950901, -0.9807853, -1, -3.25841e-7, -1, -1, -0.1950907, -0.9807852, -1, -0.3826839, -0.9238793, -1, -0.5555707, -0.8314693, -1, -0.7071073, -0.7071063, -1, -0.83147, -0.5555697, -1, -0.9238799, -0.3826827, -1, 0, 0, 0, -0.9807854, -0.1950894, -1, -1, 9.65599e-7, -1, -0.9807851, 0.1950913, -1, -0.9238791, 0.3826845, -1, -0.8314689, 0.5555713, -1, -0.7071059, 0.7071077, -1, -0.5555691, 0.8314704, -1, -0.3826821, 0.9238801, -1, -0.1950888, 0.9807856, -1
@@ -172,7 +172,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
cone_overfit = 1.0 / min_d;
}
- { // BOX
+ { // Box mesh data.
static const uint32_t box_vertex_count = 8;
static const float box_vertices[box_vertex_count * 3] = {
-1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1
@@ -219,8 +219,9 @@ ClusterBuilderSharedDataRD::~ClusterBuilderSharedDataRD() {
void ClusterBuilderRD::_clear() {
if (cluster_buffer.is_null()) {
- return; //nothing to clear
+ return;
}
+
RD::get_singleton()->free(cluster_buffer);
RD::get_singleton()->free(cluster_render_buffer);
RD::get_singleton()->free(element_buffer);
@@ -254,7 +255,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
cluster_screen_size.height = (p_screen_size.height - 1) / cluster_size + 1;
max_elements_by_type = p_max_elements;
- if (max_elements_by_type % 32) { //need to be 32 aligned
+ if (max_elements_by_type % 32) { // Needs to be aligned to 32.
max_elements_by_type += 32 - (max_elements_by_type % 32);
}
@@ -264,7 +265,8 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
uint32_t element_tag_bits_size = render_element_max / 32;
uint32_t element_tag_depth_bits_size = render_element_max;
- cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // tag bits (element was used) and tag depth (depth range in which it was used)
+
+ cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // Tag bits (element was used) and tag depth (depth range in which it was used).
cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size);
cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size);
@@ -379,9 +381,9 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projecti
projection = p_cam_projection;
z_near = projection.get_z_near();
z_far = projection.get_z_far();
- orthogonal = p_cam_projection.is_orthogonal();
+ camera_orthogonal = p_cam_projection.is_orthogonal();
adjusted_projection = projection;
- if (!orthogonal) {
+ if (!camera_orthogonal) {
adjusted_projection.adjust_perspective_znear(0.0001);
}
@@ -390,7 +392,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projecti
projection = correction * projection;
adjusted_projection = correction * adjusted_projection;
- //reset counts
+ // Reset counts.
render_element_count = 0;
for (uint32_t i = 0; i < ELEMENT_TYPE_MAX; i++) {
cluster_count_by_type[i] = 0;
@@ -402,14 +404,14 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_command_begin_label("Bake Light Cluster");
- //clear cluster buffer
+ // Clear cluster buffer.
RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
if (render_element_count > 0) {
- //clear render buffer
+ // Clear render buffer.
RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, RD::BARRIER_MASK_RASTER);
- { //fill state uniform
+ { // Fill state uniform.
StateUniform state;
@@ -425,13 +427,13 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
- //update instances
+ // Update instances.
RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
RENDER_TIMESTAMP("Render 3D Cluster Elements");
- //render elements
+ // Render elements.
{
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {};
@@ -447,8 +449,16 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array);
} break;
case ELEMENT_TYPE_SPOT_LIGHT: {
- RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array);
+ // If the spot angle is above a certain threshold, use a sphere instead of a cone for building the clusters
+ // since the cone gets too flat/large (spot angle close to 90 degrees) or
+ // can't even cover the affected area of the light (spot angle above 90 degrees).
+ if (render_elements[i].has_wide_spot_angle) {
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->sphere_vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array);
+ } else {
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array);
+ }
} break;
case ELEMENT_TYPE_DECAL:
case ELEMENT_TYPE_REFLECTION_PROBE: {
@@ -465,7 +475,7 @@ void ClusterBuilderRD::bake_cluster() {
}
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE);
}
- //store elements
+ // Store elements.
RENDER_TIMESTAMP("Pack 3D Cluster Elements");
{
@@ -509,7 +519,7 @@ void ClusterBuilderRD::debug(ElementType p_element) {
push_constant.cluster_screen_size[1] = cluster_screen_size.y;
push_constant.cluster_shift = get_shift_from_power_of_2(cluster_size);
push_constant.cluster_type = p_element;
- push_constant.orthogonal = orthogonal;
+ push_constant.orthogonal = camera_orthogonal;
push_constant.z_far = z_far;
push_constant.z_near = z_near;
push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 0b20a5d7ee..3ca7af70ca 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -43,13 +43,13 @@ class ClusterBuilderSharedDataRD {
RID sphere_vertex_array;
RID sphere_index_buffer;
RID sphere_index_array;
- float sphere_overfit = 0.0; //because an icosphere is not a perfect sphere, we need to enlarge it to cover the sphere area
+ float sphere_overfit = 0.0; // Because an icosphere is not a perfect sphere, we need to enlarge it to cover the sphere area.
RID cone_vertex_buffer;
RID cone_vertex_array;
RID cone_index_buffer;
RID cone_index_array;
- float cone_overfit = 0.0; //because an cone mesh is not a perfect sphere, we need to enlarge it to cover the actual cone area
+ float cone_overfit = 0.0; // Because an cone mesh is not a perfect cone, we need to enlarge it to cover the actual cone area.
RID box_vertex_buffer;
RID box_vertex_array;
@@ -73,6 +73,7 @@ class ClusterBuilderSharedDataRD {
ClusterRenderShaderRD cluster_render_shader;
RID shader_version;
RID shader;
+
enum PipelineVersion {
PIPELINE_NORMAL,
PIPELINE_MSAA,
@@ -85,10 +86,11 @@ class ClusterBuilderSharedDataRD {
struct ClusterStore {
struct PushConstant {
uint32_t cluster_render_data_size; // how much data for a single cluster takes
- uint32_t max_render_element_count_div_32; //divided by 32
+ uint32_t max_render_element_count_div_32; // divided by 32
uint32_t cluster_screen_size[2];
- uint32_t render_element_count_div_32; //divided by 32
- uint32_t max_cluster_element_count_div_32; //divided by 32
+ uint32_t render_element_count_div_32; // divided by 32
+ uint32_t max_cluster_element_count_div_32; // divided by 32
+
uint32_t pad1;
uint32_t pad2;
};
@@ -111,6 +113,7 @@ class ClusterBuilderSharedDataRD {
uint32_t orthogonal;
uint32_t max_cluster_element_count_div_32;
+
uint32_t pad1;
uint32_t pad2;
};
@@ -128,6 +131,8 @@ public:
class ClusterBuilderRD {
public:
+ static constexpr float WIDE_SPOT_ANGLE_THRESHOLD_DEG = 60.0f;
+
enum LightType {
LIGHT_TYPE_OMNI,
LIGHT_TYPE_SPOT
@@ -144,21 +149,20 @@ public:
ELEMENT_TYPE_DECAL,
ELEMENT_TYPE_REFLECTION_PROBE,
ELEMENT_TYPE_MAX,
-
};
private:
ClusterBuilderSharedDataRD *shared = nullptr;
struct RenderElementData {
- uint32_t type; //0-4
+ uint32_t type; // 0-4
uint32_t touches_near;
uint32_t touches_far;
uint32_t original_index;
- float transform_inv[12]; //transposed transform for less space
+ float transform_inv[12]; // Transposed transform for less space.
float scale[3];
- uint32_t pad;
- };
+ uint32_t has_wide_spot_angle;
+ }; // Keep aligned to 32 bytes.
uint32_t cluster_count_by_type[ELEMENT_TYPE_MAX] = {};
uint32_t max_elements_by_type = 0;
@@ -172,7 +176,7 @@ private:
Projection projection;
float z_far = 0;
float z_near = 0;
- bool orthogonal = false;
+ bool camera_orthogonal = false;
enum Divisor {
DIVISOR_1,
@@ -188,26 +192,27 @@ private:
Size2i cluster_screen_size;
RID framebuffer;
- RID cluster_render_buffer; //used for creating
- RID cluster_buffer; //used for rendering
- RID element_buffer; //used for storing, to hint element touches far plane or near plane
+ RID cluster_render_buffer; // Used for creating.
+ RID cluster_buffer; // Used for rendering.
+ RID element_buffer; // Used for storing, to hint element touches far plane or near plane.
uint32_t cluster_render_buffer_size = 0;
uint32_t cluster_buffer_size = 0;
RID cluster_render_uniform_set;
RID cluster_store_uniform_set;
- //persistent data
+ // Persistent data.
void _clear();
struct StateUniform {
float projection[16];
float inv_z_far;
- uint32_t screen_to_clusters_shift; // shift to obtain coordinates in block indices
- uint32_t cluster_screen_width; //
- uint32_t cluster_data_size; // how much data for a single cluster takes
+ uint32_t screen_to_clusters_shift; // Shift to obtain coordinates in block indices.
+ uint32_t cluster_screen_width;
+ uint32_t cluster_data_size; // How much data is needed for a single cluster.
uint32_t cluster_depth_offset;
+
uint32_t pad0;
uint32_t pad1;
uint32_t pad2;
@@ -224,10 +229,10 @@ public:
_FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
if (p_type == LIGHT_TYPE_SPOT && cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
RenderElementData &e = render_elements[render_element_count];
@@ -242,15 +247,14 @@ public:
radius *= p_radius;
if (p_type == LIGHT_TYPE_OMNI) {
- radius *= shared->sphere_overfit; // overfit icosphere
+ radius *= shared->sphere_overfit; // Overfit icosphere.
- //omni
float depth = -xform.origin.z;
- if (orthogonal) {
+ if (camera_orthogonal) {
e.touches_near = (depth - radius) < z_near;
} else {
- //contains camera inside light
- float radius2 = radius * shared->sphere_overfit; // overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex)
+ // Contains camera inside light.
+ float radius2 = radius * shared->sphere_overfit; // Overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex)
e.touches_near = xform.origin.length_squared() < radius2 * radius2;
}
@@ -265,12 +269,11 @@ public:
cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
- } else {
- //spot
- radius *= shared->cone_overfit; // overfit icosphere
+ } else /*LIGHT_TYPE_SPOT */ {
+ radius *= shared->cone_overfit; // Overfit icosphere
real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius;
- //approximate, probably better to use a cone support function
+ // Approximate, probably better to use a cone support function.
float max_d = -1e20;
float min_d = 1e20;
#define CONE_MINMAX(m_x, m_y) \
@@ -285,14 +288,13 @@ public:
CONE_MINMAX(-1, -1);
CONE_MINMAX(1, -1);
- if (orthogonal) {
+ if (camera_orthogonal) {
e.touches_near = min_d < z_near;
} else {
- //contains camera inside light
Plane base_plane(-xform.basis.get_column(Vector3::AXIS_Z), xform.origin);
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
- //inside, check angle
+ // Contains camera inside light, check angle.
float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit
} else {
@@ -302,12 +304,23 @@ public:
e.touches_far = max_d > z_far;
- e.scale[0] = len * shared->cone_overfit;
- e.scale[1] = len * shared->cone_overfit;
- e.scale[2] = radius;
+ // If the spot angle is above the threshold, use a sphere instead of a cone for building the clusters
+ // since the cone gets too flat/large (spot angle close to 90 degrees) or
+ // can't even cover the affected area of the light (spot angle above 90 degrees).
+ if (p_spot_aperture > WIDE_SPOT_ANGLE_THRESHOLD_DEG) {
+ e.scale[0] = radius;
+ e.scale[1] = radius;
+ e.scale[2] = radius;
+ e.has_wide_spot_angle = true;
+ } else {
+ e.scale[0] = len * shared->cone_overfit;
+ e.scale[1] = len * shared->cone_overfit;
+ e.scale[2] = radius;
+ e.has_wide_spot_angle = false;
+ }
e.type = ELEMENT_TYPE_SPOT_LIGHT;
- e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index
+ e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; // Use omni light since they share index.
RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
@@ -317,19 +330,19 @@ public:
render_element_count++;
}
- _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_extents) {
+ _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_size) {
if (p_box_type == BOX_TYPE_DECAL && cluster_count_by_type[ELEMENT_TYPE_DECAL] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
if (p_box_type == BOX_TYPE_REFLECTION_PROBE && cluster_count_by_type[ELEMENT_TYPE_REFLECTION_PROBE] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
RenderElementData &e = render_elements[render_element_count];
Transform3D xform = view_xform * p_transform;
- //extract scale and scale the matrix by it, makes things simpler
- Vector3 scale = p_half_extents;
+ // Extract scale and scale the matrix by it, makes things simpler.
+ Vector3 scale = p_half_size;
for (uint32_t i = 0; i < 3; i++) {
float s = xform.basis.rows[i].length();
scale[i] *= s;
@@ -339,10 +352,10 @@ public:
float box_depth = Math::abs(xform.basis.xform_inv(Vector3(0, 0, -1)).dot(scale));
float depth = -xform.origin.z;
- if (orthogonal) {
+ if (camera_orthogonal) {
e.touches_near = depth - box_depth < z_near;
} else {
- //contains camera inside box
+ // Contains camera inside box.
Vector3 inside = xform.xform_inv(Vector3(0, 0, 0)).abs();
e.touches_near = inside.x < scale.x && inside.y < scale.y && inside.z < scale.z;
}
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index 2b5d36d686..9389f8149e 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -411,12 +411,21 @@ SSEffects::~SSEffects() {
/* SS Downsampler */
-void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection) {
+void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ uint32_t view_count = p_render_buffers->get_view_count();
+ Size2i full_screen_size = p_render_buffers->get_internal_size();
+ Size2i size((full_screen_size.x + 1) / 2, (full_screen_size.y + 1) / 2);
+
+ // Make sure our buffers exist, buffers are automatically cleared if view count or size changes.
+ if (!p_render_buffers->has_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH)) {
+ p_render_buffers->create_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, RD::DATA_FORMAT_R16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, size, view_count * 4, 5);
+ }
+
// Downsample and deinterleave the depth buffer for SSAO and SSIL
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -447,48 +456,35 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
}
}
+ RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
int depth_index = use_half_size ? 1 : 0;
RD::get_singleton()->draw_command_begin_label("Downsample Depth");
- if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
- if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) {
- RD::get_singleton()->free(ss_effects.downsample_uniform_set);
- ss_effects.downsample_uniform_set = RID();
- }
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_depth_mipmaps[depth_index + 1]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_depth_mipmaps[depth_index + 2]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.append_id(p_depth_mipmaps[depth_index + 3]);
- uniforms.push_back(u);
- }
- if (use_full_mips) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.append_id(p_depth_mipmaps[4]);
- uniforms.push_back(u);
+ RID downsample_uniform_set;
+ if (use_mips) {
+ // Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared.
+ // This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame.
+ Vector<RD::Uniform> u_depths;
+
+ // Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips.
+ // That means we're filling all 5 levels.
+ // In this scenario `depth_index` will be 0.
+ for (int i = 0; i < (use_full_mips ? 4 : 3); i++) {
+ RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index + i + 1, 4, 1);
+
+ RD::Uniform u_depth;
+ u_depth.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u_depth.binding = i;
+ u_depth.append_id(depth_mipmap);
+ u_depths.push_back(u_depth);
}
- ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
+
+ // This before only used SS_EFFECTS_DOWNSAMPLE_MIPMAP or SS_EFFECTS_DOWNSAMPLE_FULL_MIPS
+ downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);
}
- float depth_linearize_mul = -p_projection.columns[3][2];
+ float depth_linearize_mul = -p_projection.columns[3][2] * 0.5;
float depth_linearize_add = p_projection.columns[2][2];
if (depth_linearize_mul * depth_linearize_add < 0) {
depth_linearize_add = -depth_linearize_add;
@@ -501,25 +497,30 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_
ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
}
- ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
- ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
+ ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / full_screen_size.x;
+ ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / full_screen_size.y;
ss_effects.downsample_push_constant.radius_sq = 1.0;
- RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer }));
- RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] }));
+ RID depth_texture = p_render_buffers->get_depth_texture(p_view);
+ RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index, 4, 1);
+
+ RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture }));
+ RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap }));
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1);
if (use_mips) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, downsample_uniform_set, 2);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
- Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
+ if (use_half_size) {
+ size.x = MAX(1, size.x >> 1);
+ size.y = MAX(1, size.y >> 1);
+ }
RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -543,7 +544,7 @@ void SSEffects::ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_ha
ssil_fadeout_to = p_fadeout_to;
}
-void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
+void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const RID *p_ssil_slices, const RID *p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
@@ -578,12 +579,13 @@ void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
-void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) {
+void SSEffects::ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings) {
if (p_ssil_buffers.half_size != ssil_half_size) {
- ssil_free(p_ssil_buffers);
+ p_render_buffers->clear_context(RB_SCOPE_SSIL);
}
- if (ssil_half_size) {
+ p_ssil_buffers.half_size = ssil_half_size;
+ if (p_ssil_buffers.half_size) {
p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
@@ -595,104 +597,59 @@ void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const S
p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
}
- if (p_ssil_buffers.ssil_final.is_null()) {
- {
- p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = p_settings.full_screen_size.x;
- tf.height = p_settings.full_screen_size.y;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture");
- RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
- if (p_ssil_buffers.last_frame.is_null()) {
- tf.mipmaps = 6;
- p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance");
- RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
- for (uint32_t i = 0; i < 6; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i);
- p_ssil_buffers.last_frame_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
- }
- }
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = p_ssil_buffers.buffer_width;
- tf.height = p_ssil_buffers.buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0);
- p_ssil_buffers.deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
- }
- }
+ uint32_t view_count = p_render_buffers->get_view_count();
+ Size2i full_size = Size2i(p_ssil_buffers.buffer_width, p_ssil_buffers.buffer_height);
+ Size2i half_size = Size2i(p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height);
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = p_ssil_buffers.buffer_width;
- tf.height = p_ssil_buffers.buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0);
- p_ssil_buffers.pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
- }
- }
+ // We create our intermediate and final results as render buffers.
+ // These are automatically cached and cleaned up when our viewport resizes
+ // or when our viewport gets destroyed.
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = p_ssil_buffers.buffer_width;
- tf.height = p_ssil_buffers.buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0);
- p_ssil_buffers.edges_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
- }
- }
+ if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_FINAL)) { // We don't strictly have to check if it exists but we only want to clear it when we create it...
+ RID final = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_FINAL, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT);
+ RD::get_singleton()->texture_clear(final, Color(0, 0, 0, 0), 0, 1, 0, view_count);
+ }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = p_ssil_buffers.half_buffer_width;
- tf.height = p_ssil_buffers.half_buffer_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map");
- p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong");
- }
- p_ssil_buffers.half_size = ssil_half_size;
+ if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) {
+ RID last_frame = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_LAST_FRAME, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT, RD::TEXTURE_SAMPLES_1, p_settings.full_screen_size, 0, 6);
+ RD::get_singleton()->texture_clear(last_frame, Color(0, 0, 0, 0), 0, 6, 0, view_count);
}
+
+ // As we're not clearing these, and render buffers will return the cached texture if it already exists,
+ // we don't first check has_texture here
+
+ p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_DEINTERLEAVED, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
+ p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
+ p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_EDGES, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
+ p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
+ p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
}
-void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) {
+void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
+
+ // Obtain our (cached) buffer slices for the view we are rendering.
+ RID last_frame = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, p_view, 0, 1, 6);
+ RID deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);
+ RID deinterleaved_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, 4 * p_view, 0, 4, 1);
+ RID edges = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, 4 * p_view, 0, 4, 1);
+ RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, p_view, 0);
+ RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, p_view, 0);
+
+ RID deinterleaved_slices[4];
+ RID deinterleaved_pong_slices[4];
+ RID edges_slices[4];
+ for (uint32_t i = 0; i < 4; i++) {
+ deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4 + i, 0);
+ deinterleaved_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);
+ edges_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, p_view * 4 + i, 0);
+ }
+
//Store projection info before starting the compute list
SSILProjectionUniforms projection_uniforms;
store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
@@ -701,7 +658,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
- RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER);
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -711,8 +668,14 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
- ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
- ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
+ ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
+ if (ssil_half_size) {
+ ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
+ ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
+ }
+ ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;
+ ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;
float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
@@ -723,9 +686,6 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.gather_push_constant.z_far = p_projection.get_z_far();
ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
- ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
ssil.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
@@ -749,78 +709,69 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);
ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;
- if (p_ssil_buffers.projection_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_mipmap_sampler);
- u.append_id(p_ssil_buffers.last_frame);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 1;
- u.append_id(ssil.projection_uniform_buffer);
- uniforms.push_back(u);
- }
- p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
+ // We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.
+ // It also ensures that we're reusing the right cached entry in a multiview situation without us having to
+ // remember each instance of the uniform set.
+
+ RID projection_uniform_set;
+ {
+ RD::Uniform u_last_frame;
+ u_last_frame.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_last_frame.binding = 0;
+ u_last_frame.append_id(default_mipmap_sampler);
+ u_last_frame.append_id(last_frame);
+
+ RD::Uniform u_projection;
+ u_projection.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u_projection.binding = 1;
+ u_projection.append_id(ssil.projection_uniform_buffer);
+
+ projection_uniform_set = uniform_set_cache->get_cache(shader, 3, u_last_frame, u_projection);
}
- if (p_ssil_buffers.gather_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_ssil_buffers.depth_texture_view);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
+ RID gather_uniform_set;
+ {
+ RID depth_texture_view = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, ssil_half_size ? 1 : 0, 4, 4);
+
+ RD::Uniform u_depth_texture_view;
+ u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_depth_texture_view.binding = 0;
+ u_depth_texture_view.append_id(ss_effects.mirror_sampler);
+ u_depth_texture_view.append_id(depth_texture_view);
+
+ RD::Uniform u_normal_buffer;
+ u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u_normal_buffer.binding = 1;
+ u_normal_buffer.append_id(p_normal_buffer);
+
+ RD::Uniform u_gather_constants_buffer;
+ u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u_gather_constants_buffer.binding = 2;
+ u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);
+
+ gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);
}
- if (p_ssil_buffers.importance_map_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ssil_buffers.pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_ssil_buffers.importance_map[0]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
+ RID importance_map_uniform_set;
+ {
+ RD::Uniform u_pong;
+ u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u_pong.binding = 0;
+ u_pong.append_id(deinterleaved_pong);
+
+ RD::Uniform u_importance_map;
+ u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_importance_map.binding = 1;
+ u_importance_map.append_id(default_sampler);
+ u_importance_map.append_id(importance_map);
+
+ RD::Uniform u_load_counter;
+ u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u_load_counter.binding = 2;
+ u_load_counter.append_id(ssil.importance_map_load_counter);
+
+ RID shader_adaptive = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER_ADAPTIVE);
+ importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);
}
if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {
@@ -828,38 +779,42 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
+
//base pass
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
- gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+ gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
//generate importance map
- RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
- RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] }));
+ RID gen_imp_shader = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 0);
+ RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ssil_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
// process Importance Map A
- RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] }));
- RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] }));
+ RID proc_imp_shader_a = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 1);
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
// process Importance Map B
- RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] }));
+ RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2);
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
@@ -872,7 +827,7 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
}
- gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+ gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
RD::get_singleton()->draw_command_end_label(); //Gather
}
@@ -895,6 +850,8 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
}
}
+ RID blur_shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, blur_pipeline - SSIL_BLUR_PASS);
+
for (int i = 0; i < 4; i++) {
if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
continue;
@@ -903,30 +860,30 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
if (pass % 2 == 0) {
if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);
} else {
- RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);
}
- RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1);
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_pong_slice), 1);
} else {
if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);
} else {
- RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);
}
- RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1);
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_slice), 1);
}
- RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2);
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 2, u_edges_slice), 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
@@ -961,18 +918,19 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
- RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final }));
+ RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0);
+ RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {
- RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved }));
+ RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
} else {
- RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);
}
- RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges }));
+ RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
@@ -990,34 +948,6 @@ void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers
RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
}
-void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) {
- if (p_ssil_buffers.ssil_final.is_valid()) {
- RD::get_singleton()->free(p_ssil_buffers.ssil_final);
- RD::get_singleton()->free(p_ssil_buffers.deinterleaved);
- RD::get_singleton()->free(p_ssil_buffers.pong);
- RD::get_singleton()->free(p_ssil_buffers.edges);
- RD::get_singleton()->free(p_ssil_buffers.importance_map[0]);
- RD::get_singleton()->free(p_ssil_buffers.importance_map[1]);
- RD::get_singleton()->free(p_ssil_buffers.last_frame);
-
- p_ssil_buffers.ssil_final = RID();
- p_ssil_buffers.deinterleaved = RID();
- p_ssil_buffers.pong = RID();
- p_ssil_buffers.edges = RID();
- p_ssil_buffers.deinterleaved_slices.clear();
- p_ssil_buffers.pong_slices.clear();
- p_ssil_buffers.edges_slices.clear();
- p_ssil_buffers.importance_map[0] = RID();
- p_ssil_buffers.importance_map[1] = RID();
- p_ssil_buffers.last_frame = RID();
- p_ssil_buffers.last_frame_slices.clear();
-
- p_ssil_buffers.gather_uniform_set = RID();
- p_ssil_buffers.importance_map_uniform_set = RID();
- p_ssil_buffers.projection_uniform_set = RID();
- }
-}
-
/* SSAO */
void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
@@ -1029,13 +959,13 @@ void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_ha
ssao_fadeout_to = p_fadeout_to;
}
-void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
+void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const RID *p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
}
RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
@@ -1062,11 +992,12 @@ void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
-void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) {
+void SSEffects::ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings) {
if (p_ssao_buffers.half_size != ssao_half_size) {
- ssao_free(p_ssao_buffers);
+ p_render_buffers->clear_context(RB_SCOPE_SSAO);
}
+ p_ssao_buffers.half_size = ssao_half_size;
if (ssao_half_size) {
p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
@@ -1079,79 +1010,45 @@ void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const S
p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
}
- if (p_ssao_buffers.ao_deinterleaved.is_null()) {
- {
- p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = p_ssao_buffers.buffer_width;
- tf.height = p_ssao_buffers.buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0);
- p_ssao_buffers.ao_deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
- }
- }
+ uint32_t view_count = p_render_buffers->get_view_count();
+ Size2i full_size = Size2i(p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height);
+ Size2i half_size = Size2i(p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height);
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = p_ssao_buffers.buffer_width;
- tf.height = p_ssao_buffers.buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0);
- p_ssao_buffers.ao_pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
- }
- }
+ // As we're not clearing these, and render buffers will return the cached texture if it already exists,
+ // we don't first check has_texture here
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = p_ssao_buffers.buffer_width;
- tf.height = p_ssao_buffers.buffer_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map");
- p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong");
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = p_settings.full_screen_size.x;
- tf.height = p_settings.full_screen_size.y;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final");
- }
- p_ssao_buffers.half_size = ssao_half_size;
- }
+ p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_DEINTERLEAVED, RD::DATA_FORMAT_R8G8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
+ p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, RD::DATA_FORMAT_R8G8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
+ p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
+ p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
+ p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_FINAL, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1);
}
-void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) {
+void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ // Obtain our (cached) buffer slices for the view we are rendering.
+ RID ao_deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);
+ RID ao_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4, 0, 4, 1);
+ RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, p_view, 0);
+ RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, p_view, 0);
+ RID ao_final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, p_view, 0);
+
+ RID ao_deinterleaved_slices[4];
+ RID ao_pong_slices[4];
+ for (uint32_t i = 0; i < 4; i++) {
+ ao_deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4 + i, 0);
+ ao_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);
+ }
+
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
/* FIRST PASS */
- RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0);
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER);
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
@@ -1162,8 +1059,14 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
- ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
- ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
+ ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
+ if (ssao_half_size) {
+ ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
+ ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
+ }
+ ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;
+ ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;
float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
@@ -1172,9 +1075,6 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
- ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
ssao.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
@@ -1201,60 +1101,52 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);
ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;
- if (p_ssao_buffers.gather_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_ssao_buffers.depth_texture_view);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0);
- RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set");
+ // We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.
+ // It also ensures that we're reusing the right cached entry in a multiview situation without us having to
+ // remember each instance of the uniform set.
+ RID gather_uniform_set;
+ {
+ RID depth_texture_view = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, ssao_half_size ? 1 : 0, 4, 4);
+
+ RD::Uniform u_depth_texture_view;
+ u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_depth_texture_view.binding = 0;
+ u_depth_texture_view.append_id(ss_effects.mirror_sampler);
+ u_depth_texture_view.append_id(depth_texture_view);
+
+ RD::Uniform u_normal_buffer;
+ u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u_normal_buffer.binding = 1;
+ u_normal_buffer.append_id(p_normal_buffer);
+
+ RD::Uniform u_gather_constants_buffer;
+ u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u_gather_constants_buffer.binding = 2;
+ u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);
+
+ gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);
}
- if (p_ssao_buffers.importance_map_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ssao_buffers.ao_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_ssao_buffers.importance_map[0]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
- RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set");
+ RID importance_map_uniform_set;
+ {
+ RD::Uniform u_pong;
+ u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u_pong.binding = 0;
+ u_pong.append_id(ao_pong);
+
+ RD::Uniform u_importance_map;
+ u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u_importance_map.binding = 1;
+ u_importance_map.append_id(default_sampler);
+ u_importance_map.append_id(importance_map);
+
+ RD::Uniform u_load_counter;
+ u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u_load_counter.binding = 2;
+ u_load_counter.append_id(ssao.importance_map_load_counter);
+
+ RID shader_adaptive = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER_ADAPTIVE);
+ importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);
}
if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {
@@ -1266,41 +1158,44 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
//base pass
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
- gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID());
+ gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID());
//generate importance map
+ RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
- RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0);
+ RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ao_pong_with_sampler), 0);
- RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//process importance map A
+ RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
- RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0);
- RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
//process Importance Map B
+ RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
- RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
@@ -1312,7 +1207,7 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
}
- gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set);
+ gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set);
RD::get_singleton()->draw_command_end_label(); // Gather SSAO
}
@@ -1344,29 +1239,30 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
continue;
}
+ RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
if (pass % 2 == 0) {
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);
} else {
- RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);
}
- RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1);
+ RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_pong_slices), 1);
} else {
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);
} else {
- RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);
}
- RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1);
+ RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_slices), 1);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
@@ -1400,17 +1296,18 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
interleave_pipeline = SSAO_INTERLEAVE_SMART;
}
+ RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
- RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0);
+ RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0);
if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {
- RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);
} else {
- RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
@@ -1426,116 +1323,43 @@ void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_bu
RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
}
-void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) {
- if (p_ssao_buffers.ao_final.is_valid()) {
- RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved);
- RD::get_singleton()->free(p_ssao_buffers.ao_pong);
- RD::get_singleton()->free(p_ssao_buffers.ao_final);
-
- RD::get_singleton()->free(p_ssao_buffers.importance_map[0]);
- RD::get_singleton()->free(p_ssao_buffers.importance_map[1]);
-
- p_ssao_buffers.ao_deinterleaved = RID();
- p_ssao_buffers.ao_pong = RID();
- p_ssao_buffers.ao_final = RID();
- p_ssao_buffers.importance_map[0] = RID();
- p_ssao_buffers.importance_map[1] = RID();
- p_ssao_buffers.ao_deinterleaved_slices.clear();
- p_ssao_buffers.ao_pong_slices.clear();
-
- p_ssao_buffers.gather_uniform_set = RID();
- p_ssao_buffers.importance_map_uniform_set = RID();
- }
-}
-
/* Screen Space Reflection */
void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
ssr_roughness_quality = p_quality;
}
-void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count) {
- // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view.
- if (p_ssr_buffers.size != p_screen_size || p_ssr_buffers.roughness_quality != ssr_roughness_quality) {
- ssr_free(p_ssr_buffers);
+void SSEffects::ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format) {
+ if (p_ssr_buffers.roughness_quality != ssr_roughness_quality) {
+ // Buffers will already be cleared if view count or viewport size has changed, also cleared them if we change roughness.
+ p_render_buffers->clear_context(RB_SCOPE_SSR);
}
- if (p_ssr_buffers.output.is_valid()) {
- // already allocated
- return;
- }
-
- p_ssr_buffers.size = p_screen_size;
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ p_ssr_buffers.size = Size2i(internal_size.x / 2, internal_size.y / 2);
p_ssr_buffers.roughness_quality = ssr_roughness_quality;
- if (p_ssr_buffers.depth_scaled.is_null()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = p_screen_size.x;
- tf.height = p_screen_size.y;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.array_layers = 1;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled");
+ // We are using barriers so we do not need to allocate textures for both views on anything but output...
- tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ p_render_buffers->create_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED, RD::DATA_FORMAT_R32_SFLOAT, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);
+ p_render_buffers->create_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED, RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);
- p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled");
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_render_buffers->has_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS)) {
+ p_render_buffers->create_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 2); // 2 layers, for our two blur stages
}
- if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = p_screen_size.x;
- tf.height = p_screen_size.y;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.array_layers = 1;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0");
- p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1");
- }
-
- if (p_ssr_buffers.intermediate.is_null()) {
- RD::TextureFormat tf;
- tf.format = p_color_format;
- tf.width = p_screen_size.x;
- tf.height = p_screen_size.y;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.array_layers = 1;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate");
-
- if (p_view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.array_layers = p_view_count;
- } else {
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.array_layers = 1;
- }
-
- p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output");
-
- for (uint32_t v = 0; v < p_view_count; v++) {
- p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0);
- }
- }
+ p_render_buffers->create_texture(RB_SCOPE_SSR, RB_INTERMEDIATE, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);
+ p_render_buffers->create_texture(RB_SCOPE_SSR, RB_OUTPUT, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size);
}
-void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) {
+void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Vector3 *p_eye_offsets) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ uint32_t view_count = p_render_buffers->get_view_count();
+
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
{
@@ -1546,7 +1370,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));
}
- for (uint32_t v = 0; v < p_view_count; v++) {
+ for (uint32_t v = 0; v < view_count; v++) {
store_camera(p_projections[v], scene_data.projection[v]);
store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
@@ -1559,13 +1383,27 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
}
uint32_t pipeline_specialization = 0;
- if (p_view_count > 1) {
+ if (view_count > 1) {
pipeline_specialization |= SSR_MULTIVIEW;
}
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- for (uint32_t v = 0; v < p_view_count; v++) {
+ for (uint32_t v = 0; v < view_count; v++) {
+ // get buffers we need to use for this view
+ RID diffuse_slice = p_render_buffers->get_internal_texture(v);
+ RID depth_slice = p_render_buffers->get_depth_texture(v);
+ RID depth_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED);
+ RID normal_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED);
+ RID intermediate = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_INTERMEDIATE);
+ RID output = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_OUTPUT, v, 0);
+
+ RID blur_radius[2];
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ blur_radius[0] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 0, 0);
+ blur_radius[1] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 1, 0);
+ }
+
RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v));
{ //scale color and depth to half
@@ -1577,34 +1415,29 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.camera_z_near = p_projections[v].get_z_near();
push_constant.orthogonal = p_projections[v].is_orthogonal();
push_constant.filter = false; //enabling causes arctifacts
- push_constant.screen_size[0] = p_screen_size.x;
- push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.screen_size[0] = p_ssr_buffers.size.x;
+ push_constant.screen_size[1] = p_ssr_buffers.size.y;
RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);
- RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] }));
+ RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, diffuse_slice }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);
- RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] }));
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_slice }));
RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);
- if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2);
- } else {
- RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
- }
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
- RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
- RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled }));
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ normal_scaled }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -1619,15 +1452,15 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.camera_z_far = p_projections[v].get_z_far();
push_constant.camera_z_near = p_projections[v].get_z_near();
push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.screen_size[0] = p_screen_size.x;
- push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.screen_size[0] = p_ssr_buffers.size.x;
+ push_constant.screen_size[1] = p_ssr_buffers.size.y;
push_constant.curve_fade_in = p_fade_in;
push_constant.distance_fade = p_fade_out;
push_constant.num_steps = p_max_steps;
push_constant.depth_tolerance = p_tolerance;
push_constant.use_half_res = true;
- push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]);
- push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]);
+ push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);
push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
@@ -1639,35 +1472,30 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+ // read from intermediate
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0);
+
if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- // read from output slices (our scale wrote into these)
- RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
- RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_scale_depth), 0);
-
- // write to intermediate (our roughness pass will output into output slices)
- RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
- RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1);
+ // write to output and blur radius
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output, u_blur_radius), 1);
} else {
- // read from intermediate (our scale wrote into these)
- RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
- RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0);
-
- // We are not performing our blur so go directly to output.
- RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ // We are only writing output
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1);
}
- RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2);
RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
RD::get_singleton()->draw_command_end_label();
}
@@ -1682,8 +1510,8 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.view_index = v;
push_constant.orthogonal = p_projections[v].is_orthogonal();
push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
- push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]);
- push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]);
+ push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);
push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
push_constant.vertical = 0;
@@ -1698,8 +1526,8 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.increment = 1;
}
- push_constant.screen_size[0] = p_screen_size.width;
- push_constant.screen_size[1] = p_screen_size.height;
+ push_constant.screen_size[0] = p_ssr_buffers.size.width;
+ push_constant.screen_size[1] = p_ssr_buffers.size.height;
// Horizontal pass
@@ -1709,25 +1537,25 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
- RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
-
- RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
- RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0);
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_blur_radius), 0);
- RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
- RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
- RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] }));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2);
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
+ RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate, u_blur_radius2), 2);
- RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled }));
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
// Vertical pass
@@ -1739,16 +1567,16 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
push_constant.vertical = 1;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius2), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
- if (v != p_view_count - 1) {
+ if (v != view_count - 1) {
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
@@ -1761,36 +1589,6 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R
RD::get_singleton()->compute_list_end();
}
-void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
- for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
- p_ssr_buffers.output_slices[v] = RID();
- }
-
- if (p_ssr_buffers.output.is_valid()) {
- RD::get_singleton()->free(p_ssr_buffers.output);
- p_ssr_buffers.output = RID();
- }
-
- if (p_ssr_buffers.intermediate.is_valid()) {
- RD::get_singleton()->free(p_ssr_buffers.intermediate);
- p_ssr_buffers.intermediate = RID();
- }
-
- if (p_ssr_buffers.blur_radius[0].is_valid()) {
- RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]);
- RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]);
- p_ssr_buffers.blur_radius[0] = RID();
- p_ssr_buffers.blur_radius[1] = RID();
- }
-
- if (p_ssr_buffers.depth_scaled.is_valid()) {
- RD::get_singleton()->free(p_ssr_buffers.depth_scaled);
- p_ssr_buffers.depth_scaled = RID();
- RD::get_singleton()->free(p_ssr_buffers.normal_scaled);
- p_ssr_buffers.normal_scaled = RID();
- }
-}
-
/* Subsurface scattering */
void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
index bac1d9b786..8585277e19 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.h
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -48,6 +48,26 @@
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
+#define RB_SCOPE_SSDS SNAME("rb_ssds")
+#define RB_SCOPE_SSIL SNAME("rb_ssil")
+#define RB_SCOPE_SSAO SNAME("rb_ssao")
+#define RB_SCOPE_SSR SNAME("rb_ssr")
+
+#define RB_LINEAR_DEPTH SNAME("linear_depth")
+#define RB_FINAL SNAME("final")
+#define RB_LAST_FRAME SNAME("last_frame")
+#define RB_DEINTERLEAVED SNAME("deinterleaved")
+#define RB_DEINTERLEAVED_PONG SNAME("deinterleaved_pong")
+#define RB_EDGES SNAME("edges")
+#define RB_IMPORTANCE_MAP SNAME("importance_map")
+#define RB_IMPORTANCE_PONG SNAME("importance_pong")
+
+#define RB_DEPTH_SCALED SNAME("depth_scaled")
+#define RB_NORMAL_SCALED SNAME("normal_scaled")
+#define RB_BLUR_RADIUS SNAME("blur_radius")
+#define RB_INTERMEDIATE SNAME("intermediate")
+#define RB_OUTPUT SNAME("output")
+
class RenderSceneBuffersRD;
namespace RendererRD {
@@ -64,7 +84,7 @@ public:
/* SS Downsampler */
- void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection);
+ void downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection);
/* SSIL */
void ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
@@ -75,23 +95,6 @@ public:
int buffer_height;
int half_buffer_width;
int half_buffer_height;
-
- RID ssil_final;
- RID deinterleaved;
- Vector<RID> deinterleaved_slices;
- RID pong;
- Vector<RID> pong_slices;
- RID edges;
- Vector<RID> edges_slices;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID last_frame;
- Vector<RID> last_frame_slices;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- RID projection_uniform_set;
};
struct SSILSettings {
@@ -103,9 +106,8 @@ public:
Size2i full_screen_size;
};
- void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
- void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings);
- void ssil_free(SSILRenderBuffers &p_ssil_buffers);
+ void ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings);
+ void screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings);
/* SSAO */
void ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
@@ -116,17 +118,6 @@ public:
int buffer_height;
int half_buffer_width;
int half_buffer_height;
-
- RID ao_deinterleaved;
- Vector<RID> ao_deinterleaved_slices;
- RID ao_pong;
- Vector<RID> ao_pong_slices;
- RID ao_final;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
};
struct SSAOSettings {
@@ -140,9 +131,8 @@ public:
Size2i full_screen_size;
};
- void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
- void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings);
- void ssao_free(SSAORenderBuffers &p_ssao_buffers);
+ void ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings);
+ void generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings);
/* Screen Space Reflection */
void ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
@@ -150,18 +140,10 @@ public:
struct SSRRenderBuffers {
Size2i size;
RenderingServer::EnvironmentSSRRoughnessQuality roughness_quality = RenderingServer::ENV_SSR_ROUGHNESS_QUALITY_DISABLED;
-
- RID normal_scaled;
- RID depth_scaled;
- RID blur_radius[2];
- RID intermediate;
- RID output;
- RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS];
};
- void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count);
- void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
- void ssr_free(SSRRenderBuffers &p_ssr_buffers);
+ void ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format);
+ void screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Vector3 *p_eye_offsets);
/* subsurface scattering */
void sss_set_quality(RS::SubSurfaceScatteringQuality p_quality);
@@ -223,7 +205,6 @@ private:
SSEffectsDownsamplePushConstant downsample_push_constant;
SsEffectsDownsampleShaderRD downsample_shader;
RID downsample_shader_version;
- RID downsample_uniform_set;
bool used_half_size_last_frame = false;
bool used_mips_last_frame = false;
bool used_full_mips_last_frame = false;
@@ -332,7 +313,7 @@ private:
RID pipelines[SSIL_MAX];
} ssil;
- void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
+ void gather_ssil(RD::ComputeListID p_compute_list, const RID *p_ssil_slices, const RID *p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
/* SSAO */
@@ -426,7 +407,7 @@ private:
RID pipelines[SSAO_MAX];
} ssao;
- void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
+ void gather_ssao(RD::ComputeListID p_compute_list, const RID *p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
/* Screen Space Reflection */
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
index 2787693aeb..4253ea8610 100644
--- a/servers/rendering/renderer_rd/environment/fog.cpp
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -82,11 +82,11 @@ void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
-void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
+void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) {
FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
ERR_FAIL_COND(!fog_volume);
- fog_volume->extents = p_extents;
+ fog_volume->size = p_size;
fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
@@ -120,8 +120,8 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const {
case RS::FOG_VOLUME_SHAPE_CYLINDER:
case RS::FOG_VOLUME_SHAPE_BOX: {
AABB aabb;
- aabb.position = -fog_volume->extents;
- aabb.size = fog_volume->extents * 2;
+ aabb.position = -fog_volume->size / 2;
+ aabb.size = fog_volume->size;
return aabb;
}
default: {
@@ -131,10 +131,10 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const {
}
}
-Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const {
+Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const {
const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
ERR_FAIL_COND_V(!fog_volume, Vector3());
- return fog_volume->extents;
+ return fog_volume->size;
}
////////////////////////////////////////////////////////////////////////////////
@@ -210,7 +210,7 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay
actions.renames["WORLD_POSITION"] = "world.xyz";
actions.renames["OBJECT_POSITION"] = "params.position";
actions.renames["UVW"] = "uvw";
- actions.renames["EXTENTS"] = "params.extents";
+ actions.renames["SIZE"] = "params.size";
actions.renames["ALBEDO"] = "albedo";
actions.renames["DENSITY"] = "density";
actions.renames["EMISSION"] = "emission";
@@ -643,7 +643,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
Vector3 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_extents(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.
@@ -683,9 +683,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
push_constant.position[0] = position.x;
push_constant.position[1] = position.y;
push_constant.position[2] = position.z;
- push_constant.extents[0] = extents.x;
- push_constant.extents[1] = extents.y;
- push_constant.extents[2] = extents.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;
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
index eb0a2fc7b5..0b6bcc29fb 100644
--- a/servers/rendering/renderer_rd/environment/fog.h
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -53,7 +53,7 @@ private:
struct FogVolume {
RID material;
- Vector3 extents = Vector3(1, 1, 1);
+ Vector3 size = Vector3(2, 2, 2);
RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
@@ -83,7 +83,7 @@ private:
float position[3];
float pad;
- float extents[3];
+ float size[3];
float pad2;
int32_t corner[3];
@@ -239,12 +239,12 @@ public:
Dependency *fog_volume_get_dependency(RID p_fog_volume) const;
virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
- virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override;
+ virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override;
virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
RID fog_volume_get_material(RID p_fog_volume) const;
virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
- Vector3 fog_volume_get_extents(RID p_fog_volume) const;
+ Vector3 fog_volume_get_size(RID p_fog_volume) const;
/* FOG VOLUMES INSTANCE */
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 7e02f98ce9..7fff349b3c 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -347,7 +347,10 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
tf.array_layers = 6;
tf.mipmaps = p_low_quality ? 7 : mipmaps - 1;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
@@ -571,7 +574,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1; // half res
if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
- if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
+ if (reflection.layers.size() && reflection.layers[0].views.size() >= 2 && reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
u.append_id(reflection.layers[0].views[1]);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
@@ -591,7 +594,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2; // quarter res
if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
- if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
+ if (reflection.layers.size() && reflection.layers[0].views.size() >= 3 && reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
u.append_id(reflection.layers[0].views[2]);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
@@ -1320,7 +1323,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
// Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader.
- if (shader_data->uses_quarter_res) {
+ if (shader_data->uses_quarter_res && roughness_layers >= 3) {
RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
@@ -1337,9 +1340,11 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
+ } else if (shader_data->uses_quarter_res && roughness_layers < 3) {
+ ERR_PRINT_ED("Cannot use quarter res buffer in sky shader when roughness layers is less than 3. Please increase rendering/reflections/sky_reflections/roughness_layers.");
}
- if (shader_data->uses_half_res) {
+ if (shader_data->uses_half_res && roughness_layers >= 2) {
RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
@@ -1356,6 +1361,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
+ } else if (shader_data->uses_half_res && roughness_layers < 2) {
+ ERR_PRINT_ED("Cannot use half res buffer in sky shader when roughness layers is less than 2. Please increase rendering/reflections/sky_reflections/roughness_layers.");
}
RD::DrawListID cubemap_draw_list;
@@ -1627,7 +1634,10 @@ void SkyRD::update_dirty_skys() {
tf.mipmaps = mipmaps;
tf.width = w;
tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -1642,7 +1652,10 @@ void SkyRD::update_dirty_skys() {
tf.mipmaps = MIN(mipmaps, layers);
tf.width = w;
tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
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 ad63d3fd4b..6d5e55ee6a 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -30,6 +30,7 @@
#include "render_forward_clustered.h"
#include "core/config/project_settings.h"
+#include "core/object/worker_thread_pool.h"
#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
@@ -108,6 +109,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() {
// JIC, should already have been cleared
if (render_buffers) {
render_buffers->clear_context(RB_SCOPE_FORWARD_CLUSTERED);
+ render_buffers->clear_context(RB_SCOPE_SSDS);
+ render_buffers->clear_context(RB_SCOPE_SSIL);
+ render_buffers->clear_context(RB_SCOPE_SSAO);
+ render_buffers->clear_context(RB_SCOPE_SSR);
}
if (cluster_builder) {
@@ -118,21 +123,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() {
if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) {
RD::get_singleton()->free(render_sdfgi_uniform_set);
}
-
- if (ss_effects_data.linear_depth.is_valid()) {
- RD::get_singleton()->free(ss_effects_data.linear_depth);
- ss_effects_data.linear_depth = RID();
- ss_effects_data.linear_depth_slices.clear();
- }
-
- if (ss_effects_data.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects_data.downsample_uniform_set)) {
- RD::get_singleton()->free(ss_effects_data.downsample_uniform_set);
- ss_effects_data.downsample_uniform_set = RID();
- }
-
- RenderForwardClustered::get_singleton()->get_ss_effects()->ssao_free(ss_effects_data.ssao);
- RenderForwardClustered::get_singleton()->get_ss_effects()->ssil_free(ss_effects_data.ssil);
- RenderForwardClustered::get_singleton()->get_ss_effects()->ssr_free(ss_effects_data.ssr);
}
void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RenderSceneBuffersRD *p_render_buffers) {
@@ -667,7 +657,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
scene_state.ubo.ss_effects_flags = 0;
- } else if (is_environment(p_render_data->environment)) {
+ } else if (p_render_data->reflection_probe.is_null() && is_environment(p_render_data->environment)) {
scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment);
scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment);
uint32_t ss_flags = 0;
@@ -1232,9 +1222,9 @@ void RenderForwardClustered::_update_volumetric_fog(Ref<RenderSceneBuffersRD> p_
/* Lighting */
-void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) {
+void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) {
if (current_cluster_builder != nullptr) {
- current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_extents);
+ current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_size);
}
}
@@ -1244,15 +1234,15 @@ void RenderForwardClustered::setup_added_light(const RS::LightType p_type, const
}
}
-void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) {
+void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) {
if (current_cluster_builder != nullptr) {
- current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_extents);
+ current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_size);
}
}
/* Render scene */
-void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) {
+void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections) {
ERR_FAIL_NULL(ss_effects);
ERR_FAIL_COND(p_render_buffers.is_null());
ERR_FAIL_COND(p_environment.is_null());
@@ -1271,11 +1261,14 @@ void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_bu
settings.sharpness = environment_get_ssao_sharpness(p_environment);
settings.full_screen_size = p_render_buffers->get_internal_size();
- ss_effects->ssao_allocate_buffers(rb_data->ss_effects_data.ssao, settings, rb_data->ss_effects_data.linear_depth);
- ss_effects->generate_ssao(rb_data->ss_effects_data.ssao, p_normal_buffer, p_projection, settings);
+ ss_effects->ssao_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssao, settings);
+
+ for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+ ss_effects->generate_ssao(p_render_buffers, rb_data->ss_effects_data.ssao, v, p_normal_buffers[v], p_projections[v], settings);
+ }
}
-void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) {
+void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections, const Transform3D &p_transform) {
ERR_FAIL_NULL(ss_effects);
ERR_FAIL_COND(p_render_buffers.is_null());
ERR_FAIL_COND(p_environment.is_null());
@@ -1292,36 +1285,46 @@ void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_bu
settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment);
settings.full_screen_size = p_render_buffers->get_internal_size();
- Projection correction;
- correction.set_depth_correction(true);
- Projection projection = correction * p_projection;
+ ss_effects->ssil_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssil, settings);
+
Transform3D transform = p_transform;
transform.set_origin(Vector3(0.0, 0.0, 0.0));
- Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projection * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse();
- ss_effects->ssil_allocate_buffers(rb_data->ss_effects_data.ssil, settings, rb_data->ss_effects_data.linear_depth);
- ss_effects->screen_space_indirect_lighting(rb_data->ss_effects_data.ssil, p_normal_buffer, p_projection, last_frame_projection, settings);
- rb_data->ss_effects_data.last_frame_projection = projection;
+ for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+ Projection correction;
+ correction.set_depth_correction(true);
+ Projection projection = correction * p_projections[v];
+ Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projections[v] * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse();
+
+ ss_effects->screen_space_indirect_lighting(p_render_buffers, rb_data->ss_effects_data.ssil, v, p_normal_buffers[v], p_projections[v], last_frame_projection, settings);
+
+ rb_data->ss_effects_data.last_frame_projections[v] = projection;
+ }
rb_data->ss_effects_data.last_frame_transform = transform;
}
void RenderForwardClustered::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) {
ERR_FAIL_COND(p_render_buffers.is_null());
- Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
- ERR_FAIL_COND(rb_data.is_null());
-
- if (rb_data->ss_effects_data.ssil.last_frame.is_valid()) {
+ if (p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) {
Size2i size = p_render_buffers->get_internal_size();
- RID texture = p_render_buffers->get_internal_texture();
- copy_effects->copy_to_rect(texture, rb_data->ss_effects_data.ssil.last_frame, Rect2i(0, 0, size.x, size.y));
-
- int width = size.x;
- int height = size.y;
- for (int i = 0; i < rb_data->ss_effects_data.ssil.last_frame_slices.size() - 1; i++) {
- width = MAX(1, width >> 1);
- height = MAX(1, height >> 1);
- copy_effects->make_mipmap(rb_data->ss_effects_data.ssil.last_frame_slices[i], rb_data->ss_effects_data.ssil.last_frame_slices[i + 1], Size2i(width, height));
+ uint32_t mipmaps = p_render_buffers->get_texture_format(RB_SCOPE_SSIL, RB_LAST_FRAME).mipmaps;
+ for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+ RID source = p_render_buffers->get_internal_texture(v);
+ RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, v, 0);
+ copy_effects->copy_to_rect(source, dest, Rect2i(0, 0, size.x, size.y));
+
+ int width = size.x;
+ int height = size.y;
+ for (uint32_t m = 1; m < mipmaps; m++) {
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
+
+ source = dest;
+ dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, v, m);
+
+ copy_effects->make_mipmap(source, dest, Size2i(width, height));
+ }
}
}
}
@@ -1421,41 +1424,23 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
}
if (rb_data.is_valid() && ss_effects) {
- if (p_use_ssao || p_use_ssil) {
- Size2i size = rb->get_internal_size();
+ // Note, in multiview we're allocating buffers for each eye/view we're rendering.
+ // This should allow most of the processing to happen in parallel even if we're doing
+ // drawcalls per eye/view. It will all sync up at the barrier.
- bool invalidate_uniform_set = false;
- if (rb_data->ss_effects_data.linear_depth.is_null()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = (size.x + 1) / 2;
- tf.height = (size.y + 1) / 2;
- tf.mipmaps = 5;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb_data->ss_effects_data.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb_data->ss_effects_data.linear_depth, "SS Effects Depth");
- for (uint32_t i = 0; i < tf.mipmaps; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb_data->ss_effects_data.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY);
- rb_data->ss_effects_data.linear_depth_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " ");
- }
- invalidate_uniform_set = true;
+ if (p_use_ssao || p_use_ssil) {
+ // Convert our depth buffer data to linear data in
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ ss_effects->downsample_depth(rb, v, p_render_data->scene_data->view_projection[v]);
}
- RID depth_texture = rb->get_depth_texture();
- ss_effects->downsample_depth(depth_texture, rb_data->ss_effects_data.linear_depth_slices, invalidate_uniform_set, size, p_render_data->scene_data->cam_projection);
- }
-
- if (p_use_ssao) {
- // TODO make these proper stereo
- _process_ssao(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection);
- }
+ if (p_use_ssao) {
+ _process_ssao(rb, p_render_data->environment, p_normal_roughness_slices, p_render_data->scene_data->view_projection);
+ }
- if (p_use_ssil) {
- // TODO make these proper stereo
- _process_ssil(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform);
+ if (p_use_ssil) {
+ _process_ssil(rb, p_render_data->environment, p_normal_roughness_slices, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform);
+ }
}
}
@@ -1514,17 +1499,11 @@ void RenderForwardClustered::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buf
ERR_FAIL_COND(p_environment.is_null());
ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment));
- Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2);
- ss_effects->ssr_allocate_buffers(rb_data->ss_effects_data.ssr, _render_buffers_get_color_format(), half_size, view_count);
+ ss_effects->ssr_allocate_buffers(p_render_buffers, rb_data->ss_effects_data.ssr, _render_buffers_get_color_format());
+ ss_effects->screen_space_reflection(p_render_buffers, rb_data->ss_effects_data.ssr, p_normal_slices, p_metallic_slices, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), p_projections, p_eye_offsets);
- RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS];
- RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS];
- for (uint32_t v = 0; v < view_count; v++) {
- texture_slices[v] = p_render_buffers->get_internal_texture(v);
- depth_slices[v] = p_render_buffers->get_depth_texture(v);
- }
- ss_effects->screen_space_reflection(rb_data->ss_effects_data.ssr, texture_slices, p_normal_slices, p_metallic_slices, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), view_count, p_projections, p_eye_offsets);
- copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), rb_data->ss_effects_data.ssr.output, view_count);
+ RID output = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_OUTPUT);
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), output, view_count);
}
void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) {
@@ -1550,16 +1529,18 @@ void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buf
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- Ref<RenderSceneBuffersRD> rb;
+ ERR_FAIL_NULL(p_render_data);
+
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
Ref<RenderBufferDataForwardClustered> rb_data;
- if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = p_render_data->render_buffers;
- if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
- // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
- // This will not be available when rendering reflection probes.
- rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
- }
+ if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
+ // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
}
+ bool is_reflection_probe = p_render_data->reflection_probe.is_valid();
+
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
//first of all, make a new render pass
@@ -1588,18 +1569,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
p_render_data->voxel_gi_count = 0;
- if (rb.is_valid()) {
- if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
- Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
- if (sdfgi.is_valid()) {
- sdfgi->update_cascades();
- sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
- sdfgi->update_light();
- }
+ if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ if (sdfgi.is_valid()) {
+ sdfgi->update_cascades();
+ sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
+ sdfgi->update_light();
}
-
- gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
}
+
+ gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
} else {
ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
current_cluster_builder = nullptr;
@@ -1618,7 +1597,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
// check if we need motion vectors
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
p_render_data->scene_data->calculate_motion_vectors = true;
- } else if (rb.is_valid() && rb->get_use_taa()) {
+ } else if (!is_reflection_probe && rb->get_use_taa()) {
p_render_data->scene_data->calculate_motion_vectors = true;
} else {
p_render_data->scene_data->calculate_motion_vectors = false;
@@ -1641,9 +1620,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sdfgi = false;
bool using_voxelgi = false;
bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0;
- bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
+ bool using_ssil = !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
@@ -1657,7 +1636,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
reverse_cull = true; // for some reason our views are inverted
- } else if (rb.is_valid()) {
+ } else {
screen_size = rb->get_internal_size();
if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
@@ -1685,8 +1664,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
color_only_framebuffer = rb_data->get_color_only_fb();
- } else {
- ERR_FAIL(); //bug?
}
p_render_data->scene_data->emissive_exposure_normalization = -1.0;
@@ -1695,7 +1672,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
_setup_voxelgis(*p_render_data->voxel_gi_instances);
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@@ -1707,7 +1684,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
- if (rb.is_valid() && !p_render_data->reflection_probe.is_valid()) {
+ if (!is_reflection_probe) {
if (using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
} else if (p_render_data->environment.is_valid()) {
@@ -1739,7 +1716,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
- bool using_sss = rb_data.is_valid() && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
+ bool using_sss = rb_data.is_valid() && !is_reflection_probe && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
if (using_sss && !using_separate_specular) {
using_separate_specular = true;
@@ -1772,7 +1749,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1782,7 +1759,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1791,7 +1768,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
- if (rb.is_valid()) {
+ if (!is_reflection_probe) {
RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
}
@@ -1812,7 +1789,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Setup Sky");
// Setup our sky render information for this frame/viewport
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
Vector3 eye_offset;
Projection correction;
correction.set_depth_correction(true);
@@ -1849,7 +1826,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
- bool using_ssao = depth_pre_pass && rb.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
+ bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
bool continue_depth = false;
if (depth_pre_pass) { //depth pre pass
@@ -1881,7 +1858,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi);
}
- if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)");
RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)");
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) {
@@ -1915,7 +1892,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
p_render_data->scene_data->opaque_prepass_threshold = 0.0f;
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, rb.is_valid());
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true);
RENDER_TIMESTAMP("Render Opaque Pass");
@@ -1996,7 +1973,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
}
- if (rb.is_valid() && !can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (!can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
// Handle views individual, might want to look at rewriting our resolve to do both layers in one pass.
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v));
@@ -2008,7 +1985,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
- if (rb.is_valid() && !can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (!can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
}
@@ -2054,7 +2031,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
{
uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
@@ -2131,14 +2108,16 @@ void RenderForwardClustered::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD
RID render_target = p_render_buffers->get_render_target();
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb_data->ss_effects_data.ssao.ao_final.is_valid()) {
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && p_render_buffers->has_texture(RB_SCOPE_SSAO, RB_FINAL)) {
+ RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, 0, 0);
Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true);
+ copy_effects->copy_to_fb_rect(final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true);
}
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb_data->ss_effects_data.ssil.ssil_final.is_valid()) {
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_FINAL)) {
+ RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, 0, 0);
Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
+ copy_effects->copy_to_fb_rect(final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
}
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
@@ -2617,8 +2596,8 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu
render_list[RENDER_LIST_SECONDARY].sort_by_key();
_fill_instance_data(RENDER_LIST_SECONDARY);
- Vector3 half_extents = p_bounds.size * 0.5;
- Vector3 center = p_bounds.position + half_extents;
+ Vector3 half_size = p_bounds.size * 0.5;
+ Vector3 center = p_bounds.position + half_size;
Vector<RID> sbs = {
p_albedo_texture,
@@ -2646,16 +2625,16 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu
fb_size.x = p_size[right_axis];
fb_size.y = p_size[up_axis];
- scene_data.cam_transform.origin = center + axis * half_extents;
+ scene_data.cam_transform.origin = center + axis * half_size;
scene_data.cam_transform.basis.set_column(0, right);
scene_data.cam_transform.basis.set_column(1, up);
scene_data.cam_transform.basis.set_column(2, axis);
//print_line("pass: " + itos(i) + " xform " + scene_data.cam_transform);
- float h_size = half_extents[right_axis];
- float v_size = half_extents[up_axis];
- float d_size = half_extents[i] * 2.0;
+ float h_size = half_size[right_axis];
+ float v_size = half_size[up_axis];
+ float d_size = half_size[i] * 2.0;
scene_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size);
//print_line("pass: " + itos(i) + " cam hsize: " + rtos(h_size) + " vsize: " + rtos(v_size) + " dsize " + rtos(d_size));
@@ -3060,7 +3039,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID aot = rb_data.is_valid() ? rb_data->get_ao_texture() : RID();
+ RID aot = rb.is_valid() && rb->has_texture(RB_SCOPE_SSAO, RB_FINAL) ? rb->get_texture(RB_SCOPE_SSAO, RB_FINAL) : RID();
RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
@@ -3146,7 +3125,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RD::Uniform u;
u.binding = 20;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID ssil = rb_data.is_valid() ? rb_data->get_ssil_texture() : RID();
+ RID ssil = rb.is_valid() && rb->has_texture(RB_SCOPE_SSIL, RB_FINAL) ? rb->get_texture(RB_SCOPE_SSIL, RB_FINAL) : RID();
RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
@@ -3768,6 +3747,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata)->data->dirty_dependencies = true;
} break;
case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
@@ -3782,6 +3762,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
}
void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata)->data->dirty_dependencies = true;
}
RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 9245f1b13a..e07d2f2258 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -104,16 +104,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
ClusterBuilderRD *cluster_builder = nullptr;
struct SSEffectsData {
- RID linear_depth;
- Vector<RID> linear_depth_slices;
-
- RID downsample_uniform_set;
-
- Projection last_frame_projection;
+ Projection last_frame_projections[RendererSceneRender::MAX_RENDER_VIEWS];
Transform3D last_frame_transform;
- RendererRD::SSEffects::SSAORenderBuffers ssao;
RendererRD::SSEffects::SSILRenderBuffers ssil;
+ RendererRD::SSEffects::SSAORenderBuffers ssao;
RendererRD::SSEffects::SSRRenderBuffers ssr;
} ss_effects_data;
@@ -155,9 +150,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB);
RID get_specular_only_fb();
- RID get_ao_texture() const { return ss_effects_data.ssao.ao_final; }
- RID get_ssil_texture() const { return ss_effects_data.ssil.ssil_final; }
-
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
virtual void free_data() override;
};
@@ -600,8 +592,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
/* Render Scene */
- void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
- void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
+ void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections);
+ void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const RID *p_normal_buffers, const Projection *p_projections, const Transform3D &p_transform);
void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers);
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
@@ -640,9 +632,9 @@ public:
RendererRD::SSEffects *get_ss_effects() { return ss_effects; }
/* callback from updating our lighting UBOs, used to populate cluster builder */
- virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) override;
+ virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) override;
virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) override;
- virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) override;
+ virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) override;
virtual void base_uniforms_changed() override;
_FORCE_INLINE_ virtual void update_uniform_sets() override {
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 412406c0b4..3b3979b198 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
@@ -353,6 +353,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
int variant = shader_version + shader_flags;
+
+ if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(variant)) {
+ continue;
+ }
+
RID shader_variant = shader_singleton->shader.version_get_shader(version, variant);
color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
@@ -503,7 +508,14 @@ void SceneShaderForwardClustered::init(const String p_defines) {
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, false);
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, false);
- // TODO Add a way to enable/disable color pass flags
+
+ // Disable Color Passes
+ for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
+ // Selectively disable any shader pass that includes Multiview.
+ if ((i & SHADER_COLOR_PASS_FLAG_MULTIVIEW)) {
+ shader.set_variant_enabled(i + SHADER_VERSION_COLOR_PASS, false);
+ }
+ }
}
}
@@ -625,6 +637,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
+ actions.renames["EYE_OFFSET"] = "eye_offset";
//for light
actions.renames["VIEW"] = "view";
@@ -717,6 +730,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
+ actions.check_multiview_samplers = true; // make sure we check sampling multiview textures
+
compiler.initialize(actions);
}
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 25204f1abf..45fe067a6f 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -30,6 +30,7 @@
#include "render_forward_mobile.h"
#include "core/config/project_settings.h"
+#include "core/object/worker_thread_pool.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
@@ -593,12 +594,10 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size();
+ //prepare shadow rendering
if (render_shadows) {
RENDER_TIMESTAMP("Render Shadows");
- }
- //prepare shadow rendering
- if (render_shadows) {
_render_shadow_begin();
//render directional shadows
@@ -640,16 +639,18 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- Ref<RenderSceneBuffersRD> rb;
+ ERR_FAIL_NULL(p_render_data);
+
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
+
Ref<RenderBufferDataForwardMobile> rb_data;
- if (p_render_data->render_buffers.is_valid()) {
- rb = p_render_data->render_buffers;
- if (rb->has_custom_data(RB_SCOPE_MOBILE)) {
- // Our forward mobile custom data buffer will only be available when we're rendering our normal view.
- // This will not be available when rendering reflection probes.
- rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
- }
+ if (rb->has_custom_data(RB_SCOPE_MOBILE)) {
+ // Our forward mobile custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
}
+ bool is_reflection_probe = p_render_data->reflection_probe.is_valid();
RENDER_TIMESTAMP("Prepare 3D Scene");
@@ -697,7 +698,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
}
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
@@ -754,7 +755,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@@ -832,7 +833,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Setup Sky");
// Setup our sky render information for this frame/viewport
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
Vector3 eye_offset;
Projection correction;
correction.set_depth_correction(true);
@@ -896,7 +897,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, p_render_data->render_buffers.is_valid());
if (using_subpass_transparent && using_subpass_post_process) {
RENDER_TIMESTAMP("Render Opaque + Transparent + Tonemap");
@@ -1025,7 +1026,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
- // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ // _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
@@ -1065,9 +1066,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_disable_clear_request(p_render_data);
}
- if (rb.is_valid()) {
- _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
- }
+ _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
}
/* these are being called from RendererSceneRenderRD::_pre_opaque_render */
@@ -1924,7 +1923,6 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
- Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers;
RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID();
RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID();
@@ -2237,6 +2235,9 @@ RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base
ginstance->data->base = p_base;
ginstance->data->base_type = type;
+ ginstance->data->dependency_tracker.userdata = ginstance;
+ ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
+ ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
ginstance->_mark_dirty();
@@ -2673,6 +2674,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata)->data->dirty_dependencies = true;
} break;
case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
@@ -2687,6 +2689,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe
}
void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata)->data->dirty_dependencies = true;
}
/* misc */
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 3d1d78c63d..cc4a7dfa47 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
@@ -517,6 +517,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
+ actions.renames["EYE_OFFSET"] = "eye_offset";
//for light
actions.renames["VIEW"] = "view";
@@ -609,6 +610,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
+ actions.check_multiview_samplers = true; // make sure we check sampling multiview textures
compiler.initialize(actions);
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 638fe44266..f102bc0650 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -1431,6 +1431,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c);
if (cm->mesh_instance.is_valid()) {
mesh_storage->mesh_instance_check_for_update(cm->mesh_instance);
+ mesh_storage->mesh_instance_set_canvas_item_transform(cm->mesh_instance, canvas_transform_inverse * ci->final_transform);
update_skeletons = true;
}
}
@@ -1549,6 +1550,9 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
if (cl->texture == p_texture) {
return;
}
+
+ ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture));
+
if (cl->texture.is_valid()) {
texture_storage->texture_remove_from_decal_atlas(cl->texture);
}
@@ -2630,6 +2634,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
// Default CanvasGroup shader.
shader_type canvas_item;
+render_mode unshaded;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
@@ -2657,6 +2662,7 @@ void fragment() {
// Default clip children shader.
shader_type canvas_item;
+render_mode unshaded;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 2a87c4fa8d..efd961fd89 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -253,6 +253,11 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
+ if (!rb->has_internal_texture()) {
+ // We're likely rendering reflection probes where we can't use our backbuffers.
+ return;
+ }
+
RD::get_singleton()->draw_command_begin_label("Copy screen texture");
rb->allocate_blur_textures();
@@ -275,7 +280,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
for (int i = 1; i < mipmaps; i++) {
RID source = dest;
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
- Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
+ Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i);
if (can_use_storage) {
copy_effects->make_mipmap(source, dest, msize);
@@ -292,6 +297,11 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
+ if (!rb->has_depth_texture()) {
+ // We're likely rendering reflection probes where we can't use our backbuffers.
+ return;
+ }
+
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
// note, this only creates our back depth texture if we haven't already created it.
@@ -321,9 +331,13 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_NULL(p_render_data);
+
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
+ ERR_FAIL_COND_MSG(p_render_data->reflection_probe.is_valid(), "Post processes should not be applied on reflection probes.");
+
// Glow, auto exposure and DoF (if enabled).
Size2i internal_size = rb->get_internal_size();
@@ -434,7 +448,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
float luminance_multiplier = _render_buffers_get_luminance_multiplier();
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
for (int i = 0; i < (max_glow_level + 1); i++) {
- Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
+ Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i);
if (i == 0) {
RID luminance_texture;
@@ -488,7 +502,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i];
}
- Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
+ Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0);
tonemap.glow_texture_size.x = msize.width;
tonemap.glow_texture_size.y = msize.height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
@@ -918,11 +932,9 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
// getting this here now so we can direct call a bunch of things more easily
- Ref<RenderSceneBuffersRD> rb;
- if (p_render_buffers.is_valid()) {
- rb = p_render_buffers; // cast it...
- ERR_FAIL_COND(rb.is_null());
- }
+ ERR_FAIL_COND(p_render_buffers.is_null());
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND(rb.is_null());
// setup scene data
RenderSceneDataRD scene_data;
@@ -1098,6 +1110,8 @@ float RendererSceneRenderRD::screen_space_roughness_limiter_get_limit() const {
}
TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {
+ ERR_FAIL_COND_V_MSG(p_image_size.width <= 0, TypedArray<Image>(), "Image width must be greater than 0.");
+ ERR_FAIL_COND_V_MSG(p_image_size.height <= 0, TypedArray<Image>(), "Image height must be greater than 0.");
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
tf.width = p_image_size.width; // Always 64x64
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 6fa2f7a570..7c43021eb0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -204,9 +204,9 @@ public:
/* LIGHTING */
- virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents){};
+ virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size){};
virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture){};
- virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents){};
+ virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size){};
/* GI */
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 533a912a34..c85ece6366 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -33,6 +33,7 @@
#include "core/io/compression.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
+#include "core/object/worker_thread_pool.h"
#include "core/version.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/rendering_device.h"
diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
index 134aae5ce7..4f81e36c58 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
@@ -56,7 +56,7 @@ vec4 screen_space_to_view_space_depth(vec4 p_depth) {
float depth_linearize_mul = params.z_near;
float depth_linearize_add = params.z_far;
- // Optimised version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar"
+ // Optimized version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar"
// Set your depth_linearize_mul and depth_linearize_add to:
// depth_linearize_mul = ( cameraClipFar * cameraClipNear) / ( cameraClipFar - cameraClipNear );
@@ -161,17 +161,11 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid)
still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y;
p_output_coord /= 2;
- groupMemoryBarrier();
- barrier();
if (still_alive) {
+ // Use the previous average, not ideal, but still not bad.
float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0];
- float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8];
- float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0];
- float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8];
-
- float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11));
- imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg));
+ imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00));
}
#endif
}
@@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) {
void main() {
#ifdef USE_HALF_BUFFERS
+// Half buffers means that we divide depth into two half res buffers (we only capture 1/4 of pixels).
#ifdef USE_HALF_SIZE
float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x;
float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x;
@@ -219,11 +214,11 @@ void main() {
vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size;
vec4 samples = textureGather(source_depth, uv);
-#endif
+#endif //USE_HALF_SIZE
#ifdef GENERATE_MIPS
prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy);
#else
prepare_depths(samples, gl_GlobalInvocationID.xy);
#endif
-#endif
+#endif //USE_HALF_BUFFERS
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
index 2a87e273bc..ffaa6872c9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
@@ -221,7 +221,7 @@ void SSAOTap(const int p_quality_level, inout float r_obscurance_sum, inout floa
// snap to pixel center (more correct obscurance math, avoids artifacts)
sample_offset = round(sample_offset);
- // calculate MIP based on the sample distance from the centre, similar to as described
+ // calculate MIP based on the sample distance from the center, similar to as described
// in http://graphics.cs.williams.edu/papers/SAOHPG12/.
float mip_level = (p_quality_level < SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset);
@@ -259,7 +259,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
// get this pixel's viewspace depth
pix_z = valuesUL.y;
- // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0)
+ // get left right top bottom neighboring pixels for edge detection (gets compiled out on quality_level == 0)
pix_left_z = valuesUL.x;
pix_top_z = valuesUL.z;
pix_right_z = valuesBR.z;
@@ -304,7 +304,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
float obscurance_sum = 0.0;
float weight_sum = 0.0;
- // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
+ // edge mask for between this and left/right/top/bottom neighbor pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0);
// Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats
@@ -318,7 +318,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
if (!p_adaptive_base && (p_quality_level >= SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET)) {
// disable in case of quality level 4 (reference)
if (p_quality_level != 4) {
- //approximate neighbouring pixels positions (actually just deltas or "positions - pix_center_pos" )
+ //approximate neighboring pixels positions (actually just deltas or "positions - pix_center_pos" )
vec3 normalized_viewspace_dir = vec3(pix_center_pos.xy / pix_center_pos.zz, 1.0);
vec3 pixel_left_delta = vec3(-pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_left_z - pix_center_pos.z);
vec3 pixel_right_delta = vec3(+pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_right_z - pix_center_pos.z);
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
index 04f98964e8..d234ab4417 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
@@ -80,7 +80,7 @@ void main() {
#ifdef PROCESS_MAPA
vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
@@ -98,7 +98,7 @@ void main() {
#ifdef PROCESS_MAPB
vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
index f6a9a92fac..45cc62d361 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
@@ -60,8 +60,8 @@ void main() {
int mx = int(pix_pos.x % 2);
int my = int(pix_pos.y % 2);
int index_center = mx + my * 2; // center index
- int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal
- int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical
+ int index_horizontal = (1 - mx) + my * 2; // neighboring, horizontal
+ int index_vertical = mx + (1 - my) * 2; // neighboring, vertical
int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal
vec2 center_val = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0).xy;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
index 513791dfbf..de7b97953f 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
@@ -234,7 +234,7 @@ void SSILTap(const int p_quality_level, inout vec3 r_color_sum, inout float r_ob
// snap to pixel center (more correct obscurance math, avoids artifacts)
sample_offset = round(sample_offset);
- // calculate MIP based on the sample distance from the centre, similar to as described
+ // calculate MIP based on the sample distance from the center, similar to as described
// in http://graphics.cs.williams.edu/papers/SAOHPG12/.
float mip_level = (p_quality_level < SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset);
@@ -272,7 +272,7 @@ void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, o
// get this pixel's viewspace depth
pix_z = valuesUL.y;
- // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0)
+ // get left right top bottom neighboring pixels for edge detection (gets compiled out on quality_level == 0)
pix_left_z = valuesUL.x;
pix_top_z = valuesUL.z;
pix_right_z = valuesBR.z;
@@ -318,7 +318,7 @@ void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, o
float obscurance_sum = 0.0;
float weight_sum = 0.0;
- // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
+ // edge mask for between this and left/right/top/bottom neighbor pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0);
// Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
index 47c56571f6..f48e6c4341 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
@@ -124,14 +124,14 @@ void main() {
vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size;
- vec4 centre = textureLod(source_ssil, uv, 0.0);
+ vec4 center = textureLod(source_ssil, uv, 0.0);
vec4 value = textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x * 3, -half_pixel.y)), 0.0) * 0.2;
value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x, -half_pixel.y * 3)), 0.0) * 0.2;
value += textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x, +half_pixel.y * 3)), 0.0) * 0.2;
value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x * 3, +half_pixel.y)), 0.0) * 0.2;
- vec4 sampled = value + centre * 0.2;
+ vec4 sampled = value + center * 0.2;
#else
#ifdef MODE_SMART
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
index 6b6b02739d..193e3458ab 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
@@ -82,7 +82,7 @@ void main() {
#ifdef PROCESS_MAPA
vec2 uv = (vec2(ssC) + 0.5) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
@@ -100,7 +100,7 @@ void main() {
#ifdef PROCESS_MAPB
vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
index 9e86ac0cf0..ed85b8ee4c 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
@@ -62,8 +62,8 @@ void main() {
int mx = int(pix_pos.x % 2);
int my = int(pix_pos.y % 2);
int index_center = mx + my * 2; // center index
- int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal
- int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical
+ int index_horizontal = (1 - mx) + my * 2; // neighboring, horizontal
+ int index_vertical = mx + (1 - my) * 2; // neighboring, vertical
int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal
vec4 color = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0);
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
index 9f7449b8aa..06709f65d3 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
@@ -24,7 +24,7 @@ struct ProcessVoxel {
uint albedo; // rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors.
uint light; // rgbe8985 encoded total saved light, extra 2 bits for neighbors.
uint light_aniso; // 55555 light anisotropy, extra 2 bits for neighbors.
- //total neighbours: 26
+ //total neighbors: 26
};
#ifdef MODE_PROCESS_STATIC
@@ -443,10 +443,10 @@ void main() {
imageStore(dst_aniso1, positioni, vec4(aniso1, 0.0, 0.0));
imageStore(dst_light, positioni, uvec4(light_total_rgbe));
- //also fill neighbours, so light interpolation during the indirect pass works
+ //also fill neighbors, so light interpolation during the indirect pass works
- //recover the neighbour list from the leftover bits
- uint neighbours = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24);
+ //recover the neighbor list from the leftover bits
+ uint neighbors = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24);
const uint max_neighbours = 26;
const ivec3 neighbour_positions[max_neighbours] = ivec3[](
@@ -478,7 +478,7 @@ void main() {
ivec3(1, 1, 1));
for (uint i = 0; i < max_neighbours; i++) {
- if (bool(neighbours & (1 << i))) {
+ if (bool(neighbors & (1 << i))) {
ivec3 neighbour_pos = positioni + neighbour_positions[i];
imageStore(dst_light, neighbour_pos, uvec4(light_total_rgbe));
imageStore(dst_aniso0, neighbour_pos, aniso0);
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
index bce98f4054..dd35ae3b73 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
@@ -102,10 +102,10 @@ dispatch_data;
struct ProcessVoxel {
uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours
- uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
- uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
- //total neighbours: 26
+ uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors
+ uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbors
+ uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbors
+ //total neighbors: 26
};
layout(set = 0, binding = 11, std430) restrict buffer writeonly ProcessVoxels {
@@ -135,10 +135,10 @@ dispatch_data;
struct ProcessVoxel {
uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours
- uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
- uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
- //total neighbours: 26
+ uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors
+ uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbors
+ uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbors
+ //total neighbors: 26
};
layout(set = 0, binding = 6, std430) restrict buffer readonly ProcessVoxels {
@@ -1016,14 +1016,14 @@ void main() {
store_positions[index].albedo = rgb >> 1; //store as it comes (555) to avoid precision loss (and move away the alpha bit)
store_positions[index].albedo |= (facing & 0x3F) << 15; // store facing in bits 15-21
- store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbours with remaining albedo
- store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbours with position
+ store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbors with remaining albedo
+ store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbors with position
store_positions[index].light = imageLoad(src_light, pos).r;
store_positions[index].light_aniso = imageLoad(src_light_aniso, pos).r;
- //add neighbours
- store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbours with light
- store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbours with aniso
+ //add neighbors
+ store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbors with light
+ store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbors with aniso
}
groupMemoryBarrier();
diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
index 4658afd02d..8e4f5762fd 100644
--- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
@@ -37,7 +37,7 @@ layout(push_constant, std430) uniform Params {
vec3 position;
float pad;
- vec3 extents;
+ vec3 size;
float pad2;
ivec3 corner;
@@ -184,36 +184,37 @@ void main() {
vec4 local_pos = params.transform * world;
local_pos.xyz /= local_pos.w;
+ vec3 half_size = params.size / 2.0;
float sdf = -1.0;
if (params.shape == 0) {
// Ellipsoid
// https://www.shadertoy.com/view/tdS3DG
- float k0 = length(local_pos.xyz / params.extents);
- float k1 = length(local_pos.xyz / (params.extents * params.extents));
+ float k0 = length(local_pos.xyz / half_size);
+ float k1 = length(local_pos.xyz / (half_size * half_size));
sdf = k0 * (k0 - 1.0) / k1;
} else if (params.shape == 1) {
// Cone
// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
- // Compute the cone angle automatically to fit within the volume's extents.
- float inv_height = 1.0 / max(0.001, params.extents.y);
- float radius = 1.0 / max(0.001, (min(params.extents.x, params.extents.z) * 0.5));
+ // Compute the cone angle automatically to fit within the volume's size.
+ float inv_height = 1.0 / max(0.001, half_size.y);
+ float radius = 1.0 / max(0.001, (min(half_size.x, half_size.z) * 0.5));
float hypotenuse = sqrt(radius * radius + inv_height * inv_height);
float rsin = radius / hypotenuse;
float rcos = inv_height / hypotenuse;
vec2 c = vec2(rsin, rcos);
float q = length(local_pos.xz);
- sdf = max(dot(c, vec2(q, local_pos.y - params.extents.y)), -params.extents.y - local_pos.y);
+ sdf = max(dot(c, vec2(q, local_pos.y - half_size.y)), -half_size.y - local_pos.y);
} else if (params.shape == 2) {
// Cylinder
// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
- vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(params.extents.x, params.extents.z), params.extents.y);
+ vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(half_size.x, half_size.z), half_size.y);
sdf = min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
} else if (params.shape == 3) {
// Box
// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
- vec3 q = abs(local_pos.xyz) - params.extents;
+ vec3 q = abs(local_pos.xyz) - half_size;
sdf = length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}
@@ -222,7 +223,7 @@ void main() {
#ifndef SDF_USED
cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf);
#endif
- uvw = clamp((local_pos.xyz + params.extents) / (2.0 * params.extents), 0.0, 1.0);
+ uvw = clamp((local_pos.xyz + half_size) / params.size, 0.0, 1.0);
}
if (cull_mask > 0.0) {
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 d32e6d717f..c8ad1f0312 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
@@ -118,13 +118,13 @@ layout(location = 10) out flat uint instance_index_interp;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-vec3 normal_roughness_uv(vec2 uv) {
+vec3 multiview_uv(vec2 uv) {
return vec3(uv, ViewIndex);
}
#else // USE_MULTIVIEW
// Set to zero, not supported in non stereo
#define ViewIndex 0
-vec2 normal_roughness_uv(vec2 uv) {
+vec2 multiview_uv(vec2 uv) {
return uv;
}
#endif //USE_MULTIVIEW
@@ -315,9 +315,11 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime
#ifdef USE_MULTIVIEW
mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
+ vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
#else
mat4 projection_matrix = scene_data.projection_matrix;
mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+ vec3 eye_offset = vec3(0.0, 0.0, 0.0);
#endif //USE_MULTIVIEW
//using world coordinates
@@ -550,13 +552,13 @@ layout(location = 10) in flat uint instance_index_interp;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-vec3 normal_roughness_uv(vec2 uv) {
+vec3 multiview_uv(vec2 uv) {
return vec3(uv, ViewIndex);
}
#else // USE_MULTIVIEW
// Set to zero, not supported in non stereo
#define ViewIndex 0
-vec2 normal_roughness_uv(vec2 uv) {
+vec2 multiview_uv(vec2 uv) {
return uv;
}
#endif //USE_MULTIVIEW
@@ -722,8 +724,10 @@ void fragment_shader(in SceneData scene_data) {
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
#ifdef USE_MULTIVIEW
- vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz);
+ vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
+ vec3 view = -normalize(vertex_interp - eye_offset);
#else
+ vec3 eye_offset = vec3(0.0, 0.0, 0.0);
vec3 view = -normalize(vertex_interp);
#endif
vec3 albedo = vec3(1.0);
@@ -1305,24 +1309,26 @@ void fragment_shader(in SceneData scene_data) {
}
if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
-
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- vec3 ref_vec = normalize(reflect(-view, normal));
- ref_vec = mix(ref_vec, normal, roughness * roughness);
+ // Make vertex orientation the world one, but still align to camera.
+ vec3 cam_pos = mat3(scene_data.inv_view_matrix) * vertex;
+ vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normal;
+ vec3 ref_vec = mat3(scene_data.inv_view_matrix) * normalize(reflect(-view, normal));
+
//find arbitrary tangent and bitangent, then build a matrix
- vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
- vec3 tangent = normalize(cross(v0, normal));
- vec3 bitangent = normalize(cross(tangent, normal));
- mat3 normal_mat = mat3(tangent, bitangent, normal);
+ vec3 v0 = abs(cam_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, cam_normal));
+ vec3 bitangent = normalize(cross(tangent, cam_normal));
+ mat3 normal_mat = mat3(tangent, bitangent, cam_normal);
vec4 amb_accum = vec4(0.0);
vec4 spec_accum = vec4(0.0);
- voxel_gi_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ voxel_gi_compute(index1, cam_pos, cam_normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
uint index2 = instances.data[instance_index].gi_offset >> 16;
if (index2 != 0xFFFF) {
- voxel_gi_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ voxel_gi_compute(index2, cam_pos, cam_normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
}
if (amb_accum.a > 0.0) {
@@ -1351,8 +1357,8 @@ void fragment_shader(in SceneData scene_data) {
#endif // USE_MULTIVIEW
for (int i = 0; i < 4; i++) {
- const vec2 neighbours[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
- vec2 neighbour_coord = base_coord + neighbours[i] * scene_data.screen_pixel_size;
+ const vec2 neighbors[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
+ vec2 neighbour_coord = base_coord + neighbors[i] * scene_data.screen_pixel_size;
#ifdef USE_MULTIVIEW
float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0);
#else // USE_MULTIVIEW
@@ -1384,7 +1390,11 @@ void fragment_shader(in SceneData scene_data) {
#endif // !USE_LIGHTMAP
if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) {
+#ifdef USE_MULTIVIEW
+ float ssao = texture(sampler2DArray(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(screen_uv, ViewIndex)).r;
+#else
float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
+#endif
ao = min(ao, ssao);
ao_light_affect = mix(ao_light_affect, max(ao_light_affect, implementation_data.ssao_light_affect), implementation_data.ssao_ao_affect);
}
@@ -1467,7 +1477,11 @@ void fragment_shader(in SceneData scene_data) {
ambient_light *= ao;
if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) {
+#ifdef USE_MULTIVIEW
+ vec4 ssil = textureLod(sampler2DArray(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(screen_uv, ViewIndex), 0.0);
+#else
vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0);
+#endif // USE_MULTIVIEW
ambient_light *= 1.0 - ssil.a;
ambient_light += ssil.rgb * albedo.rgb;
}
@@ -1798,7 +1812,7 @@ void fragment_shader(in SceneData scene_data) {
shadow = float(shadow1 >> ((i - 4u) * 8u) & 0xFFu) / 255.0;
}
- shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;
+ shadow = mix(1.0, shadow, directional_lights.data[i].shadow_opacity);
#endif
blur_shadow(shadow);
@@ -2082,7 +2096,7 @@ void fragment_shader(in SceneData scene_data) {
float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
- //store as 8985 to have 2 extra neighbour bits
+ //store as 8985 to have 2 extra neighbor bits
uint light_rgbe = ((uint(sRed) & 0x1FFu) >> 1) | ((uint(sGreen) & 0x1FFu) << 8) | (((uint(sBlue) & 0x1FFu) >> 1) << 17) | ((uint(exps) & 0x1Fu) << 25);
imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
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 1f524313f2..043bba1e4e 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
@@ -271,21 +271,23 @@ layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid;
#define multiviewSampler sampler2D
#else
-layout(set = 1, binding = 10) uniform texture2D depth_buffer;
-layout(set = 1, binding = 11) uniform texture2D color_buffer;
-
#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 10) uniform texture2DArray depth_buffer;
+layout(set = 1, binding = 11) uniform texture2DArray color_buffer;
layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer;
+layout(set = 1, binding = 13) uniform texture2DArray ao_buffer;
layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer;
layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer;
#define multiviewSampler sampler2DArray
#else // USE_MULTIVIEW
+layout(set = 1, binding = 10) uniform texture2D depth_buffer;
+layout(set = 1, binding = 11) uniform texture2D color_buffer;
layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer;
+layout(set = 1, binding = 13) uniform texture2D ao_buffer;
layout(set = 1, binding = 14) uniform texture2D ambient_buffer;
layout(set = 1, binding = 15) uniform texture2D reflection_buffer;
#define multiviewSampler sampler2D
#endif
-layout(set = 1, binding = 13) uniform texture2D ao_buffer;
layout(set = 1, binding = 16) uniform texture2DArray sdfgi_lightprobe_texture;
layout(set = 1, binding = 17) uniform texture3D sdfgi_occlusion_cascades;
@@ -311,7 +313,11 @@ voxel_gi_instances;
layout(set = 1, binding = 19) uniform texture3D volumetric_fog_texture;
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 20) uniform texture2DArray ssil_buffer;
+#else
layout(set = 1, binding = 20) uniform texture2D ssil_buffer;
+#endif // USE_MULTIVIEW
#endif
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 5e64d4e651..a8b28bbd4f 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
@@ -112,9 +112,15 @@ layout(location = 9) out highp float dp_clip;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif
+vec3 multiview_uv(vec2 uv) {
+ return vec3(uv, ViewIndex);
+}
#else
// Set to zero, not supported in non stereo
#define ViewIndex 0
+vec2 multiview_uv(vec2 uv) {
+ return uv;
+}
#endif //USE_MULTIVIEW
invariant gl_Position;
@@ -308,9 +314,11 @@ void main() {
#ifdef USE_MULTIVIEW
mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
+ vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
#else
mat4 projection_matrix = scene_data.projection_matrix;
mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+ vec3 eye_offset = vec3(0.0, 0.0, 0.0);
#endif //USE_MULTIVIEW
//using world coordinates
@@ -523,9 +531,15 @@ layout(location = 9) highp in float dp_clip;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif
+vec3 multiview_uv(vec2 uv) {
+ return vec3(uv, ViewIndex);
+}
#else
// Set to zero, not supported in non stereo
#define ViewIndex 0
+vec2 multiview_uv(vec2 uv) {
+ return uv;
+}
#endif //USE_MULTIVIEW
//defines to keep compatibility with vertex
@@ -659,8 +673,10 @@ void main() {
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
#ifdef USE_MULTIVIEW
- vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz);
+ vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz;
+ vec3 view = -normalize(vertex_interp - eye_offset);
#else
+ vec3 eye_offset = vec3(0.0, 0.0, 0.0);
vec3 view = -normalize(vertex_interp);
#endif
vec3 albedo = vec3(1.0);
@@ -1515,6 +1531,8 @@ void main() {
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+
+ shadow = mix(1.0, shadow, directional_lights.data[i].shadow_opacity);
#endif
blur_shadow(shadow);
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 631ff0575b..78b39a356d 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
@@ -154,8 +154,15 @@ layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas;
// this needs to change to providing just the lightmap we're using..
layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 9) uniform highp texture2DArray depth_buffer;
+layout(set = 1, binding = 10) uniform mediump texture2DArray color_buffer;
+#define multiviewSampler sampler2DArray
+#else
layout(set = 1, binding = 9) uniform highp texture2D depth_buffer;
layout(set = 1, binding = 10) uniform mediump texture2D color_buffer;
+#define multiviewSampler sampler2D
+#endif // USE_MULTIVIEW
/* Set 2 Skeleton & Instancing (can change per item) */
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index b30b0c8169..9dda62c28d 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -794,8 +794,13 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float light_length = length(light_rel_vec);
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
vec3 spot_dir = spot_lights.data[idx].direction;
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[idx].cone_angle);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[idx].cone_angle));
+
+ // This conversion to a highp float is crucial to prevent light leaking
+ // due to precision errors in the following calculations (cone angle is mediump).
+ highp float cone_angle = spot_lights.data[idx].cone_angle;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
+
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
float light_attenuation = spot_attenuation;
vec3 color = spot_lights.data[idx].color;
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index f5b233cca0..59c161548c 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -51,6 +51,15 @@ layout(push_constant, std430) uniform Params {
bool normalized_blend_shapes;
uint pad0;
uint pad1;
+
+ vec2 skeleton_transform_x;
+ vec2 skeleton_transform_y;
+
+ vec2 skeleton_transform_offset;
+ vec2 inverse_transform_x;
+
+ vec2 inverse_transform_y;
+ vec2 inverse_transform_offset;
}
params;
@@ -158,8 +167,12 @@ void main() {
m += mat4(bone_transforms.data[bones_23.x], bone_transforms.data[bones_23.x + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x;
m += mat4(bone_transforms.data[bones_23.y], bone_transforms.data[bones_23.y + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y;
- //reverse order because its transposed
- vertex = (vec4(vertex, 0.0, 1.0) * m).xy;
+ mat4 skeleton_matrix = mat4(vec4(params.skeleton_transform_x, 0.0, 0.0), vec4(params.skeleton_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(params.skeleton_transform_offset, 0.0, 1.0));
+ mat4 inverse_matrix = mat4(vec4(params.inverse_transform_x, 0.0, 0.0), vec4(params.inverse_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(params.inverse_transform_offset, 0.0, 1.0));
+
+ m = skeleton_matrix * transpose(m) * inverse_matrix;
+
+ vertex = (m * vec4(vertex, 0.0, 1.0)).xy;
}
uint dst_offset = index * params.vertex_stride;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 33e35a7a64..e65d842a67 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -232,6 +232,8 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
return;
}
+ ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture));
+
if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
}
@@ -387,6 +389,13 @@ uint64_t LightStorage::light_get_version(RID p_light) const {
return light->version;
}
+uint32_t LightStorage::light_get_cull_mask(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->cull_mask;
+}
+
AABB LightStorage::light_get_aabb(RID p_light) const {
const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, AABB());
@@ -1064,14 +1073,14 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan
reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
-void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
- if (reflection_probe->extents == p_extents) {
+ if (reflection_probe->size == p_size) {
return;
}
- reflection_probe->extents = p_extents;
+ reflection_probe->size = p_size;
reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
@@ -1143,8 +1152,8 @@ AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
ERR_FAIL_COND_V(!reflection_probe, AABB());
AABB aabb;
- aabb.position = -reflection_probe->extents;
- aabb.size = reflection_probe->extents * 2.0;
+ aabb.position = -reflection_probe->size / 2;
+ aabb.size = reflection_probe->size;
return aabb;
}
@@ -1163,11 +1172,11 @@ uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {
return reflection_probe->cull_mask;
}
-Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const {
+Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
- return reflection_probe->extents;
+ return reflection_probe->size;
}
Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {
@@ -1464,7 +1473,6 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
fb.push_back(atlas->depth_buffer);
atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
- atlas->render_buffers->cleanup();
atlas->render_buffers->configure_for_reflections(Size2i(atlas->size, atlas->size));
}
@@ -1553,6 +1561,11 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
if (rpi->processing_side == 6) {
rpi->processing_side = 0;
rpi->processing_layer++;
+ if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
+ rpi->rendering = false;
+ rpi->processing_layer = 1;
+ return true;
+ }
}
return false;
@@ -1668,7 +1681,7 @@ void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, c
ReflectionData &reflection_ubo = reflections[i];
- Vector3 extents = probe->extents;
+ Vector3 extents = probe->size / 2;
rpi->cull_mask = probe->cull_mask;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index f7c8b8833b..c36d1ef503 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -226,7 +226,7 @@ private:
Color ambient_color;
float ambient_color_energy = 1.0;
float max_distance = 0;
- Vector3 extents = Vector3(1, 1, 1);
+ Vector3 size = Vector3(20, 20, 20);
Vector3 origin_offset;
bool interior = false;
bool box_projection = false;
@@ -517,13 +517,6 @@ public:
return light->color;
}
- _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->cull_mask;
- }
-
_FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) {
const Light *light = light_owner.get_or_null(p_light);
return light->distance_fade;
@@ -575,6 +568,7 @@ public:
virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
virtual uint64_t light_get_version(RID p_light) const override;
+ virtual uint32_t light_get_cull_mask(RID p_light) const override;
Dependency *light_get_dependency(RID p_light) const;
@@ -791,7 +785,7 @@ public:
virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
- virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
+ virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override;
virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
@@ -805,7 +799,7 @@ public:
virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
- virtual Vector3 reflection_probe_get_extents(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_size(RID p_probe) const override;
virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index d631a89dd2..6f67d628a9 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -2803,6 +2803,7 @@ void MaterialStorage::material_set_render_priority(RID p_material, int priority)
if (material->data) {
material->data->set_render_priority(priority);
}
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
bool MaterialStorage::material_is_animated(RID p_material) {
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index 0ac5557659..ac217d9a49 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -323,13 +323,13 @@ public:
// http://andrewthall.org/papers/df64_qf128.pdf
#ifdef REAL_T_IS_DOUBLE
- static _FORCE_INLINE_ void split_double(double a, float *ahi, float *alo) {
+ static _FORCE_INLINE_ void split_double(double a, float *a_hi, float *a_lo) {
const double SPLITTER = (1 << 29) + 1;
double t = a * SPLITTER;
- double thi = t - (t - a);
- double tlo = a - thi;
- *ahi = (float)thi;
- *alo = (float)tlo;
+ double t_hi = t - (t - a);
+ double t_lo = a - t_hi;
+ *a_hi = (float)t_hi;
+ *a_lo = (float)t_lo;
}
#endif
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 46a0d85ba8..96618c3352 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -586,6 +586,8 @@ void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_COND(!mesh);
mesh->custom_aabb = p_aabb;
+
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const {
@@ -842,7 +844,7 @@ void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int
}
void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
- for (const RendererRD::MeshStorage::MeshInstance::Surface surface : mi->surfaces) {
+ for (const RendererRD::MeshStorage::MeshInstance::Surface &surface : mi->surfaces) {
if (surface.versions) {
for (uint32_t j = 0; j < surface.version_count; j++) {
RD::get_singleton()->free(surface.versions[j].vertex_array);
@@ -930,6 +932,11 @@ void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
}
}
+void MeshStorage::mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ mi->canvas_item_transform_2d = p_transform;
+}
+
void MeshStorage::update_mesh_instances() {
while (dirty_mesh_instance_weights.first()) {
MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
@@ -981,6 +988,25 @@ void MeshStorage::update_mesh_instances() {
push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2;
+ Transform2D transform = Transform2D();
+ if (sk && sk->use_2d) {
+ transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d;
+ }
+ push_constant.skeleton_transform_x[0] = transform.columns[0][0];
+ push_constant.skeleton_transform_x[1] = transform.columns[0][1];
+ push_constant.skeleton_transform_y[0] = transform.columns[1][0];
+ push_constant.skeleton_transform_y[1] = transform.columns[1][1];
+ push_constant.skeleton_transform_offset[0] = transform.columns[2][0];
+ push_constant.skeleton_transform_offset[1] = transform.columns[2][1];
+
+ Transform2D inverse_transform = transform.affine_inverse();
+ push_constant.inverse_transform_x[0] = inverse_transform.columns[0][0];
+ push_constant.inverse_transform_x[1] = inverse_transform.columns[0][1];
+ push_constant.inverse_transform_y[0] = inverse_transform.columns[1][0];
+ push_constant.inverse_transform_y[1] = inverse_transform.columns[1][1];
+ push_constant.inverse_transform_offset[0] = inverse_transform.columns[2][0];
+ push_constant.inverse_transform_offset[1] = inverse_transform.columns[2][1];
+
push_constant.blend_shape_count = mi->mesh->blend_shape_count;
push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED;
push_constant.pad0 = 0;
@@ -1779,8 +1805,12 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible
}
if (multimesh->data_cache.size()) {
- //there is a data cache..
+ // There is a data cache, but we may need to update some sections.
_multimesh_mark_all_dirty(multimesh, false, true);
+ int start = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
+ for (int i = start; i < p_visible; i++) {
+ _multimesh_mark_dirty(multimesh, i, true);
+ }
}
multimesh->visible_instances = p_visible;
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index b62da5fd7b..c921523941 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -178,6 +178,7 @@ private:
bool weights_dirty = false;
SelfList<MeshInstance> weight_update_list;
SelfList<MeshInstance> array_update_list;
+ Transform2D canvas_item_transform_2d;
MeshInstance() :
weight_update_list(this), array_update_list(this) {}
};
@@ -256,6 +257,14 @@ private:
uint32_t normalized_blend_shapes;
uint32_t pad0;
uint32_t pad1;
+ float skeleton_transform_x[2];
+ float skeleton_transform_y[2];
+
+ float skeleton_transform_offset[2];
+ float inverse_transform_x[2];
+
+ float inverse_transform_y[2];
+ float inverse_transform_offset[2];
};
enum {
@@ -548,6 +557,7 @@ public:
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
+ virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override;
virtual void update_mesh_instances() override;
/* MULTIMESH API */
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index f4c3e769a8..00fb8acca8 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -1145,7 +1145,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
return;
}
- if (particles->particle_buffer.is_null()) {
+ if (particles->particle_buffer.is_null() || particles->trail_bind_pose_uniform_set.is_null()) {
return; //particles have not processed yet
}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
index 31377a10a0..f5d6404f01 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -50,25 +50,19 @@ void RenderSceneBuffersRD::_bind_methods() {
// ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
// ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
- ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice);
- ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
+ ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice);
+ ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
}
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
ERR_FAIL_COND(p_named_texture.texture.is_null());
- uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps;
- p_named_texture.sizes.resize(size);
+ p_named_texture.sizes.resize(p_named_texture.format.mipmaps);
Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
-
for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
- for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) {
- uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
-
- p_named_texture.sizes.ptrw()[index] = mipmap_size;
- }
+ p_named_texture.sizes.ptrw()[mipmap] = mipmap_size;
mipmap_size.width = MAX(1, mipmap_size.width >> 1);
mipmap_size.height = MAX(1, mipmap_size.height >> 1);
@@ -251,7 +245,7 @@ RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const Stri
}
RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
- // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation.
+ // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimization.
NTKey key(p_context, p_texture_name);
@@ -324,7 +318,7 @@ const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringNam
return named_textures[key].format;
}
-RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
+RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps) {
NTKey key(p_context, p_texture_name);
// check if this is a known texture
@@ -334,36 +328,41 @@ RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const S
// check if we're in bounds
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
+ ERR_FAIL_COND_V(p_layers == 0, RID());
+ ERR_FAIL_COND_V(p_layer + p_layers > named_texture.format.array_layers, RID());
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
+ ERR_FAIL_COND_V(p_mipmaps == 0, RID());
+ ERR_FAIL_COND_V(p_mipmap + p_mipmaps > named_texture.format.mipmaps, RID());
- // if we don't have multiple layers or mipmaps, we can just return our texture as is
- if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
+ // asking the whole thing? just return the original
+ if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps) {
return named_texture.texture;
}
- // get our index and make sure we have enough entries in our slices vector
- uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
- while (named_texture.slices.size() <= int(index)) {
- named_texture.slices.push_back(RID());
+ // see if we have this
+ NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps);
+ if (named_texture.slices.has(slice_key)) {
+ return named_texture.slices[slice_key];
}
- // create our slice if we don't have it already
- if (named_texture.slices[index].is_null()) {
- named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
+ // create our slice
+ RID &slice = named_texture.slices[slice_key];
+ slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers);
- Array arr;
- arr.push_back(p_context);
- arr.push_back(p_texture_name);
- arr.push_back(itos(p_layer));
- arr.push_back(itos(p_mipmap));
- RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
- }
+ Array arr;
+ arr.push_back(p_context);
+ arr.push_back(p_texture_name);
+ arr.push_back(itos(p_layer));
+ arr.push_back(itos(p_layers));
+ arr.push_back(itos(p_mipmap));
+ arr.push_back(itos(p_mipmaps));
+ RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}").format(arr));
// and return our slice
- return named_texture.slices[index];
+ return slice;
}
-Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
+Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap) {
NTKey key(p_context, p_texture_name);
// check if this is a known texture
@@ -372,14 +371,10 @@ Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context,
ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
// check if we're in bounds
- ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i());
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
- // get our index
- uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
-
- // and return our size
- return named_texture.sizes[index];
+ // return our size
+ return named_texture.sizes[p_mipmap];
}
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
@@ -490,6 +485,16 @@ Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const String
// Depth texture
+bool RenderSceneBuffersRD::has_depth_texture() {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID depth = texture_storage->render_target_get_override_depth(render_target);
+ if (depth.is_valid()) {
+ return true;
+ } else {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
+ }
+}
+
RID RenderSceneBuffersRD::get_depth_texture() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID depth = texture_storage->render_target_get_override_depth(render_target);
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
index dc849fd56a..9a299a3415 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -93,7 +93,6 @@ private:
}
static uint32_t hash(const NTKey &p_val) {
- // FIXME, properly hash two stringnames together
uint32_t h = p_val.context.hash();
h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
return hash_fmix32(h);
@@ -106,6 +105,33 @@ private:
}
};
+ struct NTSliceKey {
+ uint32_t layer;
+ uint32_t layers;
+ uint32_t mipmap;
+ uint32_t mipmaps;
+
+ bool operator==(const NTSliceKey &p_val) const {
+ return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps);
+ }
+
+ static uint32_t hash(const NTSliceKey &p_val) {
+ uint32_t h = hash_murmur3_one_32(p_val.layer);
+ h = hash_murmur3_one_32(p_val.layers, h);
+ h = hash_murmur3_one_32(p_val.mipmap, h);
+ h = hash_murmur3_one_32(p_val.mipmaps, h);
+ return hash_fmix32(h);
+ }
+
+ NTSliceKey() {}
+ NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) {
+ layer = p_layer;
+ layers = p_layers;
+ mipmap = p_mipmap;
+ mipmaps = p_mipmaps;
+ }
+ };
+
struct NamedTexture {
// Cache the data used to create our texture
RD::TextureFormat format;
@@ -113,7 +139,7 @@ private:
// Our texture objects, slices are lazy (i.e. only created when requested).
RID texture;
- Vector<RID> slices;
+ mutable HashMap<NTSliceKey, RID, NTSliceKey> slices;
Vector<Size2i> sizes;
};
@@ -154,8 +180,8 @@ public:
RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
- RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
- Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
+ RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1);
+ Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap);
void clear_context(const StringName &p_context);
@@ -185,6 +211,9 @@ public:
// For our internal textures we provide some easy access methods.
+ _FORCE_INLINE_ bool has_internal_texture() const {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
+ }
_FORCE_INLINE_ RID get_internal_texture() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
}
@@ -192,6 +221,7 @@ public:
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
}
+ bool has_depth_texture();
RID get_depth_texture();
RID get_depth_texture(const uint32_t p_layer);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index e8d9f486bb..0ee9b28826 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -422,8 +422,7 @@ TextureStorage::TextureStorage() {
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
tformat.texture_type = RD::TEXTURE_TYPE_2D;
if (!RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
- tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.format = RD::DATA_FORMAT_R8_UNORM;
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
}
Vector<uint8_t> pv;
@@ -1854,10 +1853,10 @@ void TextureStorage::decal_free(RID p_rid) {
decal_owner.free(p_rid);
}
-void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+void TextureStorage::decal_set_size(RID p_decal, const Vector3 &p_size) {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
- decal->extents = p_extents;
+ decal->size = p_size;
decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
@@ -1907,7 +1906,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers;
- decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL);
}
void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
@@ -1950,7 +1949,14 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND_V(!decal, AABB());
- return AABB(-decal->extents, decal->extents * 2.0);
+ return AABB(-decal->size / 2, decal->size);
+}
+
+uint32_t TextureStorage::decal_get_cull_mask(RID p_decal) const {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND_V(!decal, 0);
+
+ return decal->cull_mask;
}
Dependency *TextureStorage::decal_get_dependency(RID p_decal) {
@@ -2313,7 +2319,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
DecalData &dd = decals[i];
- Vector3 decal_extents = decal->extents;
+ Vector3 decal_extents = decal->size / 2;
Transform3D scale_xform;
scale_xform.basis.scale(decal_extents);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index ea0df0b459..c16f5274ad 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -235,7 +235,7 @@ private:
} decal_atlas;
struct Decal {
- Vector3 extents = Vector3(1, 1, 1);
+ Vector3 size = Vector3(2, 2, 2);
RID textures[RS::DECAL_TEXTURE_MAX];
float emission_energy = 1.0;
float albedo_mix = 1.0;
@@ -561,7 +561,7 @@ public:
virtual void decal_initialize(RID p_decal) override;
virtual void decal_free(RID p_rid) override;
- virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
+ virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override;
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
@@ -577,9 +577,9 @@ public:
virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
- _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
+ _FORCE_INLINE_ Vector3 decal_get_size(RID p_decal) {
const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->extents;
+ return decal->size;
}
_FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
@@ -638,6 +638,7 @@ public:
}
virtual AABB decal_get_aabb(RID p_decal) const override;
+ virtual uint32_t decal_get_cull_mask(RID p_decal) const override;
Dependency *decal_get_dependency(RID p_decal);
/* DECAL INSTANCE API */
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
index d2f5e6f224..cabac4e9ee 100644
--- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
@@ -286,6 +286,10 @@ bool Utilities::has_os_feature(const String &p_feature) const {
return true;
}
+ if (p_feature == "astc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
return false;
}