summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h2
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h1
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp4
-rw-r--r--servers/rendering/renderer_compositor.cpp1
-rw-r--r--servers/rendering/renderer_compositor.h3
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h8
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.cpp475
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h120
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp687
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h220
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp29
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h3
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp783
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h217
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp8
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp4
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h50
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h46
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp88
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h15
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp59
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp348
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h80
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp31
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h19
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h73
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl21
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/blur_raster.glsl)18
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl (renamed from servers/rendering/renderer_rd/shaders/bokeh_dof.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl (renamed from servers/rendering/renderer_rd/shaders/copy.glsl)2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl (renamed from servers/rendering/renderer_rd/shaders/copy_to_fb.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/tonemap.glsl47
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp122
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h9
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp172
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h12
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp28
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h7
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp49
-rw-r--r--servers/rendering/renderer_scene_cull.cpp18
-rw-r--r--servers/rendering/renderer_scene_cull.h2
-rw-r--r--servers/rendering/renderer_scene_render.cpp2
-rw-r--r--servers/rendering/renderer_storage.h1
-rw-r--r--servers/rendering/renderer_viewport.cpp52
-rw-r--r--servers/rendering/rendering_device.h1
-rw-r--r--servers/rendering/rendering_server_default.cpp16
-rw-r--r--servers/rendering/rendering_server_default.h9
-rw-r--r--servers/rendering/shader_compiler.cpp24
-rw-r--r--servers/rendering/shader_compiler.h4
-rw-r--r--servers/rendering/shader_language.cpp592
-rw-r--r--servers/rendering/shader_language.h28
-rw-r--r--servers/rendering/shader_types.h2
61 files changed, 2841 insertions, 1814 deletions
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index 6cad45ea6d..5c6fcc8386 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -95,9 +95,9 @@ public:
static void make_current() {
_create_func = _create_current;
+ low_end = true;
}
- bool is_low_end() const override { return true; }
uint64_t get_frame_number() const override { return frame; }
double get_frame_delta_time() const override { return delta; }
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h
index ac6085cdec..596960786a 100644
--- a/servers/rendering/dummy/rasterizer_storage_dummy.h
+++ b/servers/rendering/dummy/rasterizer_storage_dummy.h
@@ -128,6 +128,7 @@ public:
String get_video_adapter_name() const override { return String(); }
String get_video_adapter_vendor() const override { return String(); }
RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
+ String get_video_adapter_api_version() const override { return String(); }
static RendererStorage *base_singleton;
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index f4d09ded64..84ab19880c 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -84,7 +84,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
if (r_items) {
r_items[r_index] = child_items[i];
child_items[i]->ysort_xform = p_transform;
- child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
+ child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
child_items[i]->ysort_index = r_index;
}
@@ -236,7 +236,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
Transform2D xform = ci->xform;
if (snapping_2d_transforms_to_pixel) {
- xform.elements[2] = xform.elements[2].floor();
+ xform.columns[2] = xform.columns[2].floor();
}
xform = p_transform * xform;
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index fa4d9c8b31..b331ec2c1d 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -35,6 +35,7 @@
#include "core/string/print_string.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
+bool RendererCompositor::low_end = false;
RendererCompositor *RendererCompositor::create() {
return _create_func();
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 9466148a31..df3df1077a 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -71,6 +71,7 @@ private:
protected:
static RendererCompositor *(*_create_func)();
bool back_end = false;
+ static bool low_end;
public:
static RendererCompositor *create();
@@ -97,7 +98,7 @@ public:
virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0;
- _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; };
+ static bool is_low_end() { return low_end; };
virtual bool is_xr_enabled() const;
RendererCompositor();
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 7f6750fa7e..e82193ea6a 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -289,11 +289,11 @@ public:
e.touches_near = min_d < z_near;
} else {
//contains camera inside light
- Plane base_plane(-xform.basis.get_axis(Vector3::AXIS_Z), xform.origin);
+ 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
- float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_axis(Vector3::AXIS_Z))));
+ float angle = Math::rad2deg(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 {
e.touches_near = false;
@@ -331,9 +331,9 @@ public:
//extract scale and scale the matrix by it, makes things simpler
Vector3 scale = p_half_extents;
for (uint32_t i = 0; i < 3; i++) {
- float s = xform.basis.elements[i].length();
+ float s = xform.basis.rows[i].length();
scale[i] *= s;
- xform.basis.elements[i] /= s;
+ xform.basis.rows[i] /= s;
};
float box_depth = Math::abs(xform.basis.xform_inv(Vector3(0, 0, -1)).dot(scale));
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
new file mode 100644
index 0000000000..cc7441776d
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
@@ -0,0 +1,475 @@
+/*************************************************************************/
+/* bokeh_dof.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "bokeh_dof.h"
+#include "copy_effects.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+BokehDOF::BokehDOF(bool p_prefer_raster_effects) {
+ prefer_raster_effects = p_prefer_raster_effects;
+
+ // Initialize bokeh
+ Vector<String> bokeh_modes;
+ bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
+ bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n");
+ bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
+ if (prefer_raster_effects) {
+ bokeh.raster_shader.initialize(bokeh_modes);
+
+ bokeh.shader_version = bokeh.raster_shader.version_create();
+
+ const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 };
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]);
+ bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ } else {
+ bokeh.compute_shader.initialize(bokeh_modes);
+ bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false);
+ bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false);
+ bokeh.shader_version = bokeh.compute_shader.version_create();
+
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ if (bokeh.compute_shader.is_variant_enabled(i)) {
+ bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
+ }
+ }
+
+ for (int i = 0; i < BOKEH_MAX; i++) {
+ bokeh.raster_pipelines[i].clear();
+ }
+ }
+}
+
+BokehDOF::~BokehDOF() {
+ if (prefer_raster_effects) {
+ bokeh.raster_shader.version_free(bokeh.shader_version);
+ } else {
+ bokeh.compute_shader.version_free(bokeh.shader_version);
+ }
+}
+
+void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our push constant
+ memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
+ bokeh.push_constant.blur_far_active = p_dof_far;
+ bokeh.push_constant.blur_far_begin = p_dof_far_begin;
+ bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
+
+ bokeh.push_constant.blur_near_active = p_dof_near;
+ bokeh.push_constant.blur_near_begin = p_dof_near_begin;
+ bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
+ bokeh.push_constant.use_jitter = p_use_jitter;
+ bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
+
+ bokeh.push_constant.z_near = p_cam_znear;
+ bokeh.push_constant.z_far = p_cam_zfar;
+ bokeh.push_constant.orthogonal = p_cam_orthogonal;
+ bokeh.push_constant.blur_size = p_bokeh_size;
+
+ bokeh.push_constant.second_pass = false;
+ bokeh.push_constant.half_size = false;
+
+ bokeh.push_constant.blur_scale = 0.5;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture }));
+ RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture }));
+ RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture }));
+ RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] }));
+ RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] }));
+
+ RD::Uniform u_base_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.base_texture);
+ RD::Uniform u_secondary_image(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.secondary_texture);
+ RD::Uniform u_half_image0(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[0]);
+ RD::Uniform u_half_image1(RD::UNIFORM_TYPE_IMAGE, 0, p_buffers.half_texture[1]);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ /* FIRST PASS */
+ // The alpha channel of the source color texture is filled with the expected circle size
+ // If used for DOF far, the size is positive, if used for near, its negative.
+
+ RID shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_texture), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ //second pass
+ BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[mode]);
+
+ static const int quality_samples[4] = { 6, 12, 12, 24 };
+
+ bokeh.push_constant.steps = quality_samples[p_quality];
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ bokeh.push_constant.blur_size *= 0.5;
+
+ } else {
+ //medium and high quality use full size
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_secondary_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //third pass
+ bokeh.push_constant.second_pass = true;
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_secondary_texture), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //forth pass, upscale for low quality
+
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture1), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.second_pass = false;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
+ }
+ } else {
+ //circle
+
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BOKEH_CIRCULAR);
+ ERR_FAIL_COND(shader.is_null());
+
+ //second pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
+
+ static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
+
+ bokeh.push_constant.steps = 0;
+ bokeh.push_constant.blur_scale = quality_scale[p_quality];
+
+ //circle always runs in half size, otherwise too expensive
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_base_texture), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //circle is just one pass, then upscale
+
+ // upscale
+
+ shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
+
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.second_pass = false;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our base push constant
+ memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
+
+ bokeh.push_constant.orthogonal = p_cam_orthogonal;
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.width;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.height;
+ bokeh.push_constant.z_far = p_cam_zfar;
+ bokeh.push_constant.z_near = p_cam_znear;
+
+ bokeh.push_constant.second_pass = false;
+ bokeh.push_constant.half_size = false;
+ bokeh.push_constant.blur_size = p_dof_blur_amount;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_base_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.base_texture }));
+ RD::Uniform u_depth_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.depth_texture }));
+ RD::Uniform u_secondary_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.secondary_texture }));
+ RD::Uniform u_half_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[0] }));
+ RD::Uniform u_half_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.half_texture[1] }));
+ RD::Uniform u_weight_texture0(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[0] }));
+ RD::Uniform u_weight_texture1(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[1] }));
+ RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
+ RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
+
+ if (p_dof_far || p_dof_near) {
+ if (p_dof_far) {
+ bokeh.push_constant.blur_far_active = true;
+ bokeh.push_constant.blur_far_begin = p_dof_far_begin;
+ bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
+ }
+
+ if (p_dof_near) {
+ bokeh.push_constant.blur_near_active = true;
+ bokeh.push_constant.blur_near_begin = p_dof_near_begin;
+ bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
+ }
+
+ {
+ // generate our depth data
+ RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE);
+ ERR_FAIL_COND(shader.is_null());
+
+ RID framebuffer = p_buffers.base_weight_fb;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ // double pass approach
+ BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+
+ RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ bokeh.push_constant.blur_size *= 0.5;
+ }
+
+ static const int quality_samples[4] = { 6, 12, 12, 24 };
+ bokeh.push_constant.blur_scale = 0.5;
+ bokeh.push_constant.steps = quality_samples[p_quality];
+
+ RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
+
+ // Pass 1
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ // Pass 2
+ if (!bokeh.push_constant.half_size) {
+ // do not output weight, we're writing back into our base buffer
+ mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
+
+ shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+ }
+ bokeh.push_constant.second_pass = true;
+
+ framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb;
+ RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture;
+ RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ if (bokeh.push_constant.half_size) {
+ // Compose pass
+ mode = BOKEH_COMPOSITE;
+ shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ framebuffer = p_buffers.base_fb;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+
+ } else {
+ // circular is a single pass approach
+ BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR;
+
+ RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ {
+ // circle always runs in half size, otherwise too expensive (though the code below does support making this optional)
+ bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
+ bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
+ bokeh.push_constant.half_size = true;
+ // bokeh.push_constant.blur_size *= 0.5;
+ }
+
+ static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
+ bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.steps = 0.0;
+
+ RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ if (bokeh.push_constant.half_size) {
+ // Compose
+ mode = BOKEH_COMPOSITE;
+ shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ framebuffer = p_buffers.base_fb;
+
+ draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_weight_texture0), 2);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ } else {
+ CopyEffects::get_singleton()->copy_raster(p_buffers.secondary_texture, p_buffers.base_fb);
+ }
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
new file mode 100644
index 0000000000..d7b736119c
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -0,0 +1,120 @@
+/*************************************************************************/
+/* bokeh_dof.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BOKEH_DOF_RD_H
+#define BOKEH_DOF_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class BokehDOF {
+private:
+ bool prefer_raster_effects;
+
+ struct BokehPushConstant {
+ uint32_t size[2];
+ float z_far;
+ float z_near;
+
+ uint32_t orthogonal;
+ float blur_size;
+ float blur_scale;
+ uint32_t steps;
+
+ uint32_t blur_near_active;
+ float blur_near_begin;
+ float blur_near_end;
+ uint32_t blur_far_active;
+
+ float blur_far_begin;
+ float blur_far_end;
+ uint32_t second_pass;
+ uint32_t half_size;
+
+ uint32_t use_jitter;
+ float jitter_seed;
+ uint32_t pad[2];
+ };
+
+ enum BokehMode {
+ BOKEH_GEN_BLUR_SIZE,
+ BOKEH_GEN_BOKEH_BOX,
+ BOKEH_GEN_BOKEH_BOX_NOWEIGHT,
+ BOKEH_GEN_BOKEH_HEXAGONAL,
+ BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT,
+ BOKEH_GEN_BOKEH_CIRCULAR,
+ BOKEH_COMPOSITE,
+ BOKEH_MAX
+ };
+
+ struct Bokeh {
+ BokehPushConstant push_constant;
+ BokehDofShaderRD compute_shader;
+ BokehDofRasterShaderRD raster_shader;
+ RID shader_version;
+ RID compute_pipelines[BOKEH_MAX];
+ PipelineCacheRD raster_pipelines[BOKEH_MAX];
+ } bokeh;
+
+public:
+ struct BokehBuffers {
+ // bokeh buffers
+
+ // textures
+ Size2i base_texture_size;
+ RID base_texture;
+ RID depth_texture;
+ RID secondary_texture;
+ RID half_texture[2];
+
+ // raster only
+ RID base_fb;
+ RID secondary_fb; // with weights
+ RID half_fb[2]; // with weights
+ RID base_weight_fb;
+ RID weight_texture[4];
+ };
+
+ BokehDOF(bool p_prefer_raster_effects);
+ ~BokehDOF();
+
+ void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+};
+
+} // namespace RendererRD
+
+#endif // !BOKEH_DOF_RD_H
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
new file mode 100644
index 0000000000..fabedc80c1
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -0,0 +1,687 @@
+/*************************************************************************/
+/* copy_effects.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "copy_effects.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+CopyEffects *CopyEffects::singleton = nullptr;
+
+CopyEffects *CopyEffects::get_singleton() {
+ return singleton;
+}
+
+CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
+ singleton = this;
+ prefer_raster_effects = p_prefer_raster_effects;
+
+ if (prefer_raster_effects) {
+ // init blur shader (on compute use copy shader)
+
+ Vector<String> blur_modes;
+ blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
+ blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
+
+ blur_raster.shader.initialize(blur_modes);
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+ blur_raster.shader_version = blur_raster.shader.version_create();
+
+ for (int i = 0; i < BLUR_MODE_MAX; i++) {
+ blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+
+ } else {
+ // not used in clustered
+ for (int i = 0; i < BLUR_MODE_MAX; i++) {
+ blur_raster.pipelines[i].clear();
+ }
+
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_MIPMAP\n");
+ copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
+ copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
+ copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n");
+
+ copy.shader.initialize(copy_modes);
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.shader_version = copy.shader.version_create();
+
+ for (int i = 0; i < COPY_MODE_MAX; i++) {
+ if (copy.shader.is_variant_enabled(i)) {
+ copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
+ }
+ }
+ }
+
+ {
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n");
+ copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
+ copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
+ copy_modes.push_back("\n#define MULTIVIEW\n");
+ copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
+
+ copy_to_fb.shader.initialize(copy_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false);
+ copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false);
+ }
+
+ copy_to_fb.shader_version = copy_to_fb.shader.version_create();
+
+ //use additive
+
+ for (int i = 0; i < COPY_TO_FB_MAX; i++) {
+ if (copy_to_fb.shader.is_variant_enabled(i)) {
+ copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ copy_to_fb.pipelines[i].clear();
+ }
+ }
+ }
+}
+
+CopyEffects::~CopyEffects() {
+ if (prefer_raster_effects) {
+ blur_raster.shader.version_free(blur_raster.shader_version);
+ } else {
+ copy.shader.version_free(copy.shader_version);
+ }
+
+ copy_to_fb.shader.version_free(copy_to_fb.shader_version);
+
+ singleton = nullptr;
+}
+
+void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_rect shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ if (p_force_luminance) {
+ copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
+ }
+
+ if (p_all_source) {
+ copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
+ }
+
+ if (p_alpha_to_one) {
+ copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_cubemap_to_panorama shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_panorama_size.width;
+ copy.push_constant.section[3] = p_panorama_size.height;
+ copy.push_constant.target[0] = 0;
+ copy.push_constant.target[1] = 0;
+ copy.push_constant.camera_z_far = p_lod;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_cube(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cube }));
+ RD::Uniform u_dest_panorama(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_panorama);
+
+ CopyMode mode = p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cube), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_panorama), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = COPY_MODE_SIMPLY_COPY_DEPTH;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_depth_to_rect_and_linearize shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+ copy.push_constant.camera_z_far = p_z_far;
+ copy.push_constant.camera_z_near = p_z_near;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = COPY_MODE_LINEARIZE_DEPTH;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_atlas_fb shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
+ copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
+ copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
+ copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
+
+ if (p_flip_y) {
+ copy_to_fb.push_constant.flip_y = true;
+ }
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ CopyToFBMode mode = p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY;
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = p_draw_list;
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+}
+
+void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the copy_to_fb_rect shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
+
+ if (p_flip_y) {
+ copy_to_fb.push_constant.flip_y = true;
+ }
+ if (p_force_luminance) {
+ copy_to_fb.push_constant.force_luminance = true;
+ }
+ if (p_alpha_to_zero) {
+ copy_to_fb.push_constant.alpha_to_zero = true;
+ }
+ if (p_srgb) {
+ copy_to_fb.push_constant.srgb = true;
+ }
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ CopyToFBMode mode;
+ if (p_multiview) {
+ mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW;
+ } else {
+ mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY;
+ }
+
+ RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ if (p_secondary.is_valid()) {
+ // TODO may need to do this differently when reading from depth buffer for multiview
+ RD::Uniform u_secondary(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_secondary }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_secondary), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the copy with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, BLUR_MODE_COPY);
+ ERR_FAIL_COND(shader.is_null());
+
+ // Just copy it back (we use our blur raster shader here)..
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = p_region.position.x;
+ copy.push_constant.section[1] = p_region.position.y;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_texture);
+
+ CopyMode mode = p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ //HORIZONTAL
+ RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_texture), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
+ uint32_t base_flags = 0;
+
+ copy.push_constant.section[2] = p_size.x;
+ copy.push_constant.section[3] = p_size.y;
+
+ copy.push_constant.glow_strength = p_strength;
+ copy.push_constant.glow_bloom = p_bloom;
+ copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
+ copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+ copy.push_constant.glow_exposure = p_exposure;
+ copy.push_constant.glow_white = 0; //actually unused
+ copy.push_constant.glow_luminance_cap = p_luminance_cap;
+
+ copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_back_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_back_texture);
+
+ RID shader = copy.shader.version_get_shader(copy.shader_version, copy_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_back_texture), 3);
+ if (p_auto_exposure.is_valid() && p_first_pass) {
+ RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
+ }
+
+ copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
+ uint32_t base_flags = 0;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ blur_raster.push_constant.glow_strength = p_strength;
+ blur_raster.push_constant.glow_bloom = p_bloom;
+ blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
+ blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+ blur_raster.push_constant.glow_exposure = p_exposure;
+ blur_raster.push_constant.glow_white = 0; //actually unused
+ blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
+
+ blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+
+ blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ //HORIZONTAL
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ if (p_auto_exposure.is_valid() && p_first_pass) {
+ RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_auto_exposure), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
+
+ shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ //VERTICAL
+ draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ blur_raster.push_constant.flags = base_flags;
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the make_mipmap shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_size.width;
+ copy.push_constant.section[3] = p_size.height;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = COPY_MODE_MIPMAP;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode mode = BLUR_MIPMAP;
+
+ blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
+ blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the set_color shader with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+ copy.push_constant.target[0] = p_region.position.x;
+ copy.push_constant.target[1] = p_region.position.y;
+ copy.push_constant.set_color[0] = p_color.r;
+ copy.push_constant.set_color[1] = p_color.g;
+ copy.push_constant.set_color[2] = p_color.b;
+ copy.push_constant.set_color[3] = p_color.a;
+
+ // setup our uniforms
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_texture);
+
+ CopyMode mode = p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR;
+ RID shader = copy.shader.version_get_shader(copy.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
new file mode 100644
index 0000000000..e522408d20
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -0,0 +1,220 @@
+/*************************************************************************/
+/* copy_effects.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef COPY_RD_H
+#define COPY_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class CopyEffects {
+private:
+ bool prefer_raster_effects;
+
+ // Blur raster shader
+
+ enum BlurRasterMode {
+ BLUR_MIPMAP,
+
+ BLUR_MODE_GAUSSIAN_BLUR,
+ BLUR_MODE_GAUSSIAN_GLOW,
+ BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+ BLUR_MODE_COPY,
+
+ BLUR_MODE_MAX
+ };
+
+ enum {
+ BLUR_FLAG_HORIZONTAL = (1 << 0),
+ BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
+ BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
+ };
+
+ struct BlurRasterPushConstant {
+ float pixel_size[2];
+ uint32_t flags;
+ uint32_t pad;
+
+ //glow
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+
+ float luminance_multiplier;
+ float res1;
+ float res2;
+ float res3;
+ };
+
+ struct BlurRaster {
+ BlurRasterPushConstant push_constant;
+ BlurRasterShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[BLUR_MODE_MAX];
+ } blur_raster;
+
+ // Copy shader
+
+ enum CopyMode {
+ COPY_MODE_GAUSSIAN_COPY,
+ COPY_MODE_GAUSSIAN_COPY_8BIT,
+ COPY_MODE_GAUSSIAN_GLOW,
+ COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+ COPY_MODE_SIMPLY_COPY,
+ COPY_MODE_SIMPLY_COPY_8BIT,
+ COPY_MODE_SIMPLY_COPY_DEPTH,
+ COPY_MODE_SET_COLOR,
+ COPY_MODE_SET_COLOR_8BIT,
+ COPY_MODE_MIPMAP,
+ COPY_MODE_LINEARIZE_DEPTH,
+ COPY_MODE_CUBE_TO_PANORAMA,
+ COPY_MODE_CUBE_ARRAY_TO_PANORAMA,
+ COPY_MODE_MAX,
+
+ };
+
+ enum {
+ COPY_FLAG_HORIZONTAL = (1 << 0),
+ COPY_FLAG_USE_COPY_SECTION = (1 << 1),
+ COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
+ COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
+ COPY_FLAG_GLOW_FIRST_PASS = (1 << 4),
+ COPY_FLAG_FLIP_Y = (1 << 5),
+ COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
+ COPY_FLAG_ALL_SOURCE = (1 << 7),
+ COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
+ COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
+ };
+
+ struct CopyPushConstant {
+ int32_t section[4];
+ int32_t target[2];
+ uint32_t flags;
+ uint32_t pad;
+ // Glow.
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+ // DOF.
+ float camera_z_far;
+ float camera_z_near;
+ uint32_t pad2[2];
+ //SET color
+ float set_color[4];
+ };
+
+ struct Copy {
+ CopyPushConstant push_constant;
+ CopyShaderRD shader;
+ RID shader_version;
+ RID pipelines[COPY_MODE_MAX];
+
+ } copy;
+
+ // Copy to FB shader
+
+ enum CopyToFBMode {
+ COPY_TO_FB_COPY,
+ COPY_TO_FB_COPY_PANORAMA_TO_DP,
+ COPY_TO_FB_COPY2,
+
+ COPY_TO_FB_MULTIVIEW,
+ COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
+ COPY_TO_FB_MAX,
+ };
+
+ struct CopyToFbPushConstant {
+ float section[4];
+ float pixel_size[2];
+ uint32_t flip_y;
+ uint32_t use_section;
+
+ uint32_t force_luminance;
+ uint32_t alpha_to_zero;
+ uint32_t srgb;
+ uint32_t pad;
+ };
+
+ struct CopyToFb {
+ CopyToFbPushConstant push_constant;
+ CopyToFbShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[COPY_TO_FB_MAX];
+
+ } copy_to_fb;
+
+ static CopyEffects *singleton;
+
+public:
+ static CopyEffects *get_singleton();
+
+ CopyEffects(bool p_prefer_raster_effects);
+ ~CopyEffects();
+
+ void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
+ void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
+ void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
+ void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
+ void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
+ void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
+ void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
+
+ void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+
+ void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
+ void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
+
+ void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
+};
+
+} // namespace RendererRD
+
+#endif // !COPY_RD_H
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
index e5642116bb..38a4a37b8a 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -75,28 +75,9 @@ ToneMapper::ToneMapper() {
}
}
}
-
- // TODO maybe centralise this in mesh_storage?
- { //create index array for copy shaders
- Vector<uint8_t> pv;
- pv.resize(6 * 4);
- {
- uint8_t *w = pv.ptrw();
- int *p32 = (int *)w;
- p32[0] = 0;
- p32[1] = 1;
- p32[2] = 2;
- p32[3] = 0;
- p32[4] = 2;
- p32[5] = 3;
- }
- index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
- index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
- }
}
ToneMapper::~ToneMapper() {
- RD::get_singleton()->free(index_buffer); //array gets freed as dependency
tonemap.shader.version_free(tonemap.shader_version);
}
@@ -154,11 +135,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
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);
- RD::Uniform u_source_color;
- u_source_color.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u_source_color.binding = 0;
- u_source_color.append_id(default_sampler);
- u_source_color.append_id(p_source_color);
+ RD::Uniform u_source_color(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_color }));
RD::Uniform u_exposure_texture;
u_exposure_texture.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
@@ -193,7 +170,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
@@ -273,7 +250,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1); // should be set to a default texture, it's ignored
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 2, u_glow_texture, u_glow_map), 2); // should be set to a default texture, it's ignored
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, uniform_set_cache->get_cache(shader, 3, u_color_correction_texture), 3);
- RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, index_array);
+ RD::get_singleton()->draw_list_bind_index_array(p_subpass_draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(p_subpass_draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant));
RD::get_singleton()->draw_list_draw(p_subpass_draw_list, true);
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index 357e814845..a90849dbeb 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -96,9 +96,6 @@ private:
PipelineCacheRD pipelines[TONEMAP_MODE_MAX];
} tonemap;
- RID index_buffer;
- RID index_array;
-
public:
ToneMapper();
~ToneMapper();
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index f05027d569..774745abdc 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -86,7 +86,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
u.append_id(p_texture);
uniforms.push_back(u);
// anything with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, 0), 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
@@ -252,295 +252,6 @@ void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RI
RD::get_singleton()->compute_list_end(compute_list);
}
-void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
- memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
-
- copy_to_fb.push_constant.use_section = true;
- copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
- copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
- copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
- copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
-
- if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
- }
-
- RD::DrawListID draw_list = p_draw_list;
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
-}
-
-void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) {
- memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
-
- if (p_flip_y) {
- copy_to_fb.push_constant.flip_y = true;
- }
- if (p_force_luminance) {
- copy_to_fb.push_constant.force_luminance = true;
- }
- if (p_alpha_to_zero) {
- copy_to_fb.push_constant.alpha_to_zero = true;
- }
- if (p_srgb) {
- copy_to_fb.push_constant.srgb = true;
- }
-
- CopyToFBMode mode;
- if (p_multiview) {
- mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW;
- } else {
- mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY;
- }
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- if (p_secondary.is_valid()) {
- // TODO may need to do this differently when reading from depth buffer for multiview
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1);
- }
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-void EffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
- if (p_flip_y) {
- copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
- }
-
- if (p_force_luminance) {
- copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
- }
-
- if (p_all_source) {
- copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
- }
-
- if (p_alpha_to_one) {
- copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
- }
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_rect.size.width;
- copy.push_constant.section[3] = p_rect.size.height;
- copy.push_constant.target[0] = p_rect.position.x;
- copy.push_constant.target[1] = p_rect.position.y;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_panorama_size.width;
- copy.push_constant.section[3] = p_panorama_size.height;
- copy.push_constant.target[0] = 0;
- copy.push_constant.target[1] = 0;
- copy.push_constant.camera_z_far = p_lod;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_panorama_size.width, p_panorama_size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
- if (p_flip_y) {
- copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
- }
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_rect.size.width;
- copy.push_constant.section[3] = p_rect.size.height;
- copy.push_constant.target[0] = p_rect.position.x;
- copy.push_constant.target[1] = p_rect.position.y;
- copy.push_constant.camera_z_far = p_z_far;
- copy.push_constant.camera_z_near = p_z_near;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
- if (p_flip_y) {
- copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
- }
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_rect.size.width;
- copy.push_constant.section[3] = p_rect.size.height;
- copy.push_constant.target[0] = p_rect.position.x;
- copy.push_constant.target[1] = p_rect.position.y;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_rect.size.width, p_rect.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_region.size.width;
- copy.push_constant.section[3] = p_region.size.height;
- copy.push_constant.target[0] = p_region.position.x;
- copy.push_constant.target[1] = p_region.position.y;
- copy.push_constant.set_color[0] = p_color.r;
- copy.push_constant.set_color[1] = p_color.g;
- copy.push_constant.set_color[2] = p_color.b;
- copy.push_constant.set_color[3] = p_color.a;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
-
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = p_region.position.x;
- copy.push_constant.section[1] = p_region.position.y;
- copy.push_constant.section[2] = p_region.size.width;
- copy.push_constant.section[3] = p_region.size.height;
-
- //HORIZONTAL
- RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
-
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
- uint32_t base_flags = 0;
-
- copy.push_constant.section[2] = p_size.x;
- copy.push_constant.section[3] = p_size.y;
-
- copy.push_constant.glow_strength = p_strength;
- copy.push_constant.glow_bloom = p_bloom;
- copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
- copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
- copy.push_constant.glow_exposure = p_exposure;
- copy.push_constant.glow_white = 0; //actually unused
- copy.push_constant.glow_luminance_cap = p_luminance_cap;
-
- copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
- if (p_auto_exposure.is_valid() && p_first_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1);
- }
-
- copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
-
- BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
- uint32_t base_flags = 0;
-
- blur_raster.push_constant.pixel_size[0] = p_pixel_size.x;
- blur_raster.push_constant.pixel_size[1] = p_pixel_size.y;
-
- blur_raster.push_constant.glow_strength = p_strength;
- blur_raster.push_constant.glow_bloom = p_bloom;
- blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
- blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
- blur_raster.push_constant.glow_exposure = p_exposure;
- blur_raster.push_constant.glow_white = 0; //actually unused
- blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
-
- blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
-
- //HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- if (p_auto_exposure.is_valid() && p_first_pass) {
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
- }
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
-
- //VERTICAL
- draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- blur_raster.push_constant.flags = base_flags;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -733,43 +444,6 @@ void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_bas
RD::get_singleton()->draw_list_end();
}
-void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
- copy.push_constant.section[2] = p_size.width;
- copy.push_constant.section[3] = p_size.height;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.width, p_size.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
-
- BlurRasterMode mode = BLUR_MIPMAP;
-
- blur_raster.push_constant.pixel_size[0] = 1.0 / float(p_size.x);
- blur_raster.push_constant.pixel_size[1] = 1.0 / float(p_size.y);
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
CopyToDPPushConstant push_constant;
push_constant.screen_rect[0] = p_rect.position.x;
@@ -865,332 +539,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
}
}
-void EffectsRD::bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer.");
-
- bokeh.push_constant.blur_far_active = p_dof_far;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
-
- bokeh.push_constant.blur_near_active = p_dof_near;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
- bokeh.push_constant.use_jitter = p_use_jitter;
- bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
-
- bokeh.push_constant.z_near = p_cam_znear;
- bokeh.push_constant.z_far = p_cam_zfar;
- bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.blur_size = p_bokeh_size;
-
- bokeh.push_constant.second_pass = false;
- bokeh.push_constant.half_size = false;
-
- bokeh.push_constant.blur_scale = 0.5;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- /* FIRST PASS */
- // The alpha channel of the source color texture is filled with the expected circle size
- // If used for DOF far, the size is positive, if used for near, its negative.
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.depth_texture), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
- //second pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
-
- static const int quality_samples[4] = { 6, 12, 12, 24 };
-
- bokeh.push_constant.steps = quality_samples[p_quality];
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
- bokeh.push_constant.blur_size *= 0.5;
-
- } else {
- //medium and high quality use full size
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.secondary_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //third pass
- bokeh.push_constant.second_pass = true;
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[1]), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.secondary_texture), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- //forth pass, upscale for low quality
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[1]), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
- bokeh.push_constant.half_size = false;
- bokeh.push_constant.second_pass = false;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
- }
- } else {
- //circle
-
- //second pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
-
- static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
-
- bokeh.push_constant.steps = 0;
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
-
- //circle always runs in half size, otherwise too expensive
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //circle is just one pass, then upscale
-
- // upscale
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
-
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
- bokeh.push_constant.half_size = false;
- bokeh.push_constant.second_pass = false;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer.");
-
- memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
-
- bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.width;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.height;
- bokeh.push_constant.z_far = p_cam_zfar;
- bokeh.push_constant.z_near = p_cam_znear;
-
- bokeh.push_constant.second_pass = false;
- bokeh.push_constant.half_size = false;
- bokeh.push_constant.blur_size = p_dof_blur_amount;
-
- if (p_dof_far || p_dof_near) {
- if (p_dof_far) {
- bokeh.push_constant.blur_far_active = true;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
- }
-
- if (p_dof_near) {
- bokeh.push_constant.blur_near_active = true;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
- }
-
- {
- // generate our depth data
- RID framebuffer = p_buffers.base_weight_fb;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.depth_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
-
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
- // double pass approach
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
-
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
- //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
- bokeh.push_constant.blur_size *= 0.5;
- }
-
- static const int quality_samples[4] = { 6, 12, 12, 24 };
- bokeh.push_constant.blur_scale = 0.5;
- bokeh.push_constant.steps = quality_samples[p_quality];
-
- RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
-
- // Pass 1
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- // Pass 2
- if (!bokeh.push_constant.half_size) {
- // do not output weight, we're writing back into our base buffer
- mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
- }
- bokeh.push_constant.second_pass = true;
-
- framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb;
- RID texture = bokeh.push_constant.half_size ? p_buffers.half_texture[0] : p_buffers.secondary_texture;
- RID weight = bokeh.push_constant.half_size ? p_buffers.weight_texture[2] : p_buffers.weight_texture[1];
-
- draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(weight), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- if (bokeh.push_constant.half_size) {
- // Compose pass
- mode = BOKEH_COMPOSITE;
- framebuffer = p_buffers.base_fb;
-
- draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[1]), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[3]), 1);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
-
- } else {
- // circular is a single pass approach
- BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR;
-
- {
- // circle always runs in half size, otherwise too expensive (though the code below does support making this optional)
- bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
- bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
- bokeh.push_constant.half_size = true;
- // bokeh.push_constant.blur_size *= 0.5;
- }
-
- static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
- bokeh.push_constant.steps = 0.0;
-
- RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-
- if (bokeh.push_constant.half_size) {
- // Compose
- mode = BOKEH_COMPOSITE;
- framebuffer = p_buffers.base_fb;
-
- draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[0]), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[2]), 1);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- } else {
- // Just copy it back (we use our blur raster shader here)..
- draw_list = RD::get_singleton()->draw_list_begin(p_buffers.base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_buffers.base_fb)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.secondary_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
- }
- }
-}
-
void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) {
// Downsample and deinterleave the depth buffer for SSAO and SSIL
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -2152,94 +1500,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
prefer_raster_effects = p_prefer_raster_effects;
- if (prefer_raster_effects) {
- // init blur shader (on compute use copy shader)
-
- Vector<String> blur_modes;
- blur_modes.push_back("\n#define MODE_MIPMAP\n"); // BLUR_MIPMAP
- blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
- blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
- blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
- blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
-
- blur_raster.shader.initialize(blur_modes);
- memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
- blur_raster.shader_version = blur_raster.shader.version_create();
-
- for (int i = 0; i < BLUR_MODE_MAX; i++) {
- blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- }
-
- } else {
- // not used in clustered
- for (int i = 0; i < BLUR_MODE_MAX; i++) {
- blur_raster.pipelines[i].clear();
- }
- }
-
- if (!prefer_raster_effects) { // Initialize copy
- Vector<String> copy_modes;
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n");
- copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define MODE_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
- copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
- copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
- copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
- copy_modes.push_back("\n#define MODE_SET_COLOR\n");
- copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
- copy_modes.push_back("\n#define MODE_MIPMAP\n");
- copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
- copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
- copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n");
-
- copy.shader.initialize(copy_modes);
- memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
-
- if (prefer_raster_effects) {
- // disable shaders we can't use
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY, false);
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY_8BIT, false);
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW, false);
- copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, false);
- }
-
- copy.shader_version = copy.shader.version_create();
-
- for (int i = 0; i < COPY_MODE_MAX; i++) {
- if (copy.shader.is_variant_enabled(i)) {
- copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
- }
- }
- }
- {
- Vector<String> copy_modes;
- copy_modes.push_back("\n");
- copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
- copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
- copy_modes.push_back("\n#define MULTIVIEW\n");
- copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
-
- copy_to_fb.shader.initialize(copy_modes);
-
- if (!RendererCompositorRD::singleton->is_xr_enabled()) {
- copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false);
- copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false);
- }
-
- copy_to_fb.shader_version = copy_to_fb.shader.version_create();
-
- //use additive
-
- for (int i = 0; i < COPY_TO_FB_MAX; i++) {
- if (copy_to_fb.shader.is_variant_enabled(i)) {
- copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- } else {
- copy_to_fb.pipelines[i].clear();
- }
- }
- }
-
{
// Initialize roughness
Vector<String> cubemap_roughness_modes;
@@ -2311,42 +1571,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
}
- // Initialize bokeh
- Vector<String> bokeh_modes;
- bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
- bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n");
- bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
- if (prefer_raster_effects) {
- bokeh.raster_shader.initialize(bokeh_modes);
-
- bokeh.shader_version = bokeh.raster_shader.version_create();
-
- const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 };
- for (int i = 0; i < BOKEH_MAX; i++) {
- RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]);
- bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- } else {
- bokeh.compute_shader.initialize(bokeh_modes);
- bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false);
- bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false);
- bokeh.shader_version = bokeh.compute_shader.version_create();
-
- for (int i = 0; i < BOKEH_MAX; i++) {
- if (bokeh.compute_shader.is_variant_enabled(i)) {
- bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
- }
- }
-
- for (int i = 0; i < BOKEH_MAX; i++) {
- bokeh.raster_pipelines[i].clear();
- }
- }
-
if (!prefer_raster_effects) {
{
// Initialize depth buffer for screen space effects
@@ -2837,21 +2061,17 @@ EffectsRD::~EffectsRD() {
FSR_upscale.shader.version_free(FSR_upscale.shader_version);
if (prefer_raster_effects) {
- blur_raster.shader.version_free(blur_raster.shader_version);
- bokeh.raster_shader.version_free(blur_raster.shader_version);
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
roughness.raster_shader.version_free(roughness.shader_version);
cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
filter.raster_shader.version_free(filter.shader_version);
} else {
- bokeh.compute_shader.version_free(bokeh.shader_version);
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
roughness.compute_shader.version_free(roughness.shader_version);
cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
filter.compute_shader.version_free(filter.shader_version);
}
if (!prefer_raster_effects) {
- copy.shader.version_free(copy.shader_version);
resolve.shader.version_free(resolve.shader_version);
specular_merge.shader.version_free(specular_merge.shader_version);
ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
@@ -2875,7 +2095,6 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(ssil.importance_map_load_counter);
RD::get_singleton()->free(ssil.projection_uniform_buffer);
}
- copy_to_fb.shader.version_free(copy_to_fb.shader_version);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
sort.shader.version_free(sort.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 8174e30238..4774864824 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -33,11 +33,6 @@
#include "core/math/camera_matrix.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h"
@@ -95,140 +90,6 @@ private:
RID pipeline;
} FSR_upscale;
- enum BlurRasterMode {
- BLUR_MIPMAP,
-
- BLUR_MODE_GAUSSIAN_BLUR,
- BLUR_MODE_GAUSSIAN_GLOW,
- BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
- BLUR_MODE_COPY,
-
- BLUR_MODE_MAX
- };
-
- enum {
- BLUR_FLAG_HORIZONTAL = (1 << 0),
- BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
- BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
- };
-
- struct BlurRasterPushConstant {
- float pixel_size[2];
- uint32_t flags;
- uint32_t pad;
-
- //glow
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
-
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
- };
-
- struct BlurRaster {
- BlurRasterPushConstant push_constant;
- BlurRasterShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[BLUR_MODE_MAX];
- } blur_raster;
-
- enum CopyMode {
- COPY_MODE_GAUSSIAN_COPY,
- COPY_MODE_GAUSSIAN_COPY_8BIT,
- COPY_MODE_GAUSSIAN_GLOW,
- COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
- COPY_MODE_SIMPLY_COPY,
- COPY_MODE_SIMPLY_COPY_8BIT,
- COPY_MODE_SIMPLY_COPY_DEPTH,
- COPY_MODE_SET_COLOR,
- COPY_MODE_SET_COLOR_8BIT,
- COPY_MODE_MIPMAP,
- COPY_MODE_LINEARIZE_DEPTH,
- COPY_MODE_CUBE_TO_PANORAMA,
- COPY_MODE_CUBE_ARRAY_TO_PANORAMA,
- COPY_MODE_MAX,
-
- };
-
- enum {
- COPY_FLAG_HORIZONTAL = (1 << 0),
- COPY_FLAG_USE_COPY_SECTION = (1 << 1),
- COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
- COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
- COPY_FLAG_GLOW_FIRST_PASS = (1 << 4),
- COPY_FLAG_FLIP_Y = (1 << 5),
- COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
- COPY_FLAG_ALL_SOURCE = (1 << 7),
- COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
- COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
- };
-
- struct CopyPushConstant {
- int32_t section[4];
- int32_t target[2];
- uint32_t flags;
- uint32_t pad;
- // Glow.
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
-
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
- // DOF.
- float camera_z_far;
- float camera_z_near;
- uint32_t pad2[2];
- //SET color
- float set_color[4];
- };
-
- struct Copy {
- CopyPushConstant push_constant;
- CopyShaderRD shader;
- RID shader_version;
- RID pipelines[COPY_MODE_MAX];
-
- } copy;
-
- enum CopyToFBMode {
- COPY_TO_FB_COPY,
- COPY_TO_FB_COPY_PANORAMA_TO_DP,
- COPY_TO_FB_COPY2,
-
- COPY_TO_FB_MULTIVIEW,
- COPY_TO_FB_MULTIVIEW_WITH_DEPTH,
- COPY_TO_FB_MAX,
-
- };
-
- struct CopyToFbPushConstant {
- float section[4];
- float pixel_size[2];
- uint32_t flip_y;
- uint32_t use_section;
-
- uint32_t force_luminance;
- uint32_t alpha_to_zero;
- uint32_t srgb;
- uint32_t pad;
- };
-
- struct CopyToFb {
- CopyToFbPushConstant push_constant;
- CopyToFbShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[COPY_TO_FB_MAX];
-
- } copy_to_fb;
-
struct CubemapRoughnessPushConstant {
uint32_t face_id;
uint32_t sample_count;
@@ -305,51 +166,6 @@ private:
PipelineCacheRD pipeline;
} cube_to_dp;
- struct BokehPushConstant {
- uint32_t size[2];
- float z_far;
- float z_near;
-
- uint32_t orthogonal;
- float blur_size;
- float blur_scale;
- uint32_t steps;
-
- uint32_t blur_near_active;
- float blur_near_begin;
- float blur_near_end;
- uint32_t blur_far_active;
-
- float blur_far_begin;
- float blur_far_end;
- uint32_t second_pass;
- uint32_t half_size;
-
- uint32_t use_jitter;
- float jitter_seed;
- uint32_t pad[2];
- };
-
- enum BokehMode {
- BOKEH_GEN_BLUR_SIZE,
- BOKEH_GEN_BOKEH_BOX,
- BOKEH_GEN_BOKEH_BOX_NOWEIGHT,
- BOKEH_GEN_BOKEH_HEXAGONAL,
- BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT,
- BOKEH_GEN_BOKEH_CIRCULAR,
- BOKEH_COMPOSITE,
- BOKEH_MAX
- };
-
- struct Bokeh {
- BokehPushConstant push_constant;
- BokehDofShaderRD compute_shader;
- BokehDofRasterShaderRD raster_shader;
- RID shader_version;
- RID compute_pipelines[BOKEH_MAX];
- PipelineCacheRD raster_pipelines[BOKEH_MAX];
- } bokeh;
-
struct SSEffectsDownsamplePushConstant {
float pixel_size[2];
float z_far;
@@ -838,46 +654,13 @@ public:
bool get_prefer_raster_effects();
void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
- void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false);
- void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
- void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
- void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
- void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
- void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
- void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
- void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
- void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
- void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- struct BokehBuffers {
- // bokeh buffers
-
- // textures
- Size2i base_texture_size;
- RID base_texture;
- RID depth_texture;
- RID secondary_texture;
- RID half_texture[2];
-
- // raster only
- RID base_fb;
- RID secondary_fb; // with weights
- RID half_fb[2]; // with weights
- RID base_weight_fb;
- RID weight_texture[4];
- };
-
- void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
- void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
-
struct SSAOSettings {
float radius = 1.0;
float intensity = 2.0;
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 ace948d149..4bfaad9fe6 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -977,7 +977,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
+ Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1984,9 +1984,9 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
fb_size.y = p_size[up_axis];
render_data.cam_transform.origin = center + axis * half_extents;
- render_data.cam_transform.basis.set_axis(0, right);
- render_data.cam_transform.basis.set_axis(1, up);
- render_data.cam_transform.basis.set_axis(2, axis);
+ render_data.cam_transform.basis.set_column(0, right);
+ render_data.cam_transform.basis.set_column(1, up);
+ render_data.cam_transform.basis.set_column(2, axis);
//print_line("pass: " + itos(i) + " xform " + render_data.cam_transform);
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 3c115c942b..036ad0f18a 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
@@ -452,8 +452,6 @@ RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_s
SceneShaderForwardClustered::ShaderData::ShaderData() :
shader_list_element(this) {
- valid = false;
- uses_screen_texture = false;
}
SceneShaderForwardClustered::ShaderData::~ShaderData() {
@@ -750,7 +748,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
actions.global_buffer_array_variable = "global_variables.data";
- actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
+ actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
compiler.initialize(actions);
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 6185fa7413..0b2df983ff 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -130,9 +130,9 @@ public:
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
};
- bool valid;
+ bool valid = false;
RID version;
- uint32_t vertex_input_mask;
+ uint32_t vertex_input_mask = 0;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
@@ -142,7 +142,7 @@ public:
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String code;
Map<StringName, Map<int, RID>> default_texture_params;
@@ -150,28 +150,28 @@ public:
DepthDraw depth_draw;
DepthTest depth_test;
- bool uses_point_size;
- bool uses_alpha;
- bool uses_blend_alpha;
- bool uses_alpha_clip;
- bool uses_depth_pre_pass;
- bool uses_discard;
- bool uses_roughness;
- bool uses_normal;
- bool uses_particle_trails;
-
- bool unshaded;
- bool uses_vertex;
- bool uses_position;
- bool uses_sss;
- bool uses_transmittance;
- bool uses_screen_texture;
- bool uses_depth_texture;
- bool uses_normal_texture;
- bool uses_time;
- bool writes_modelview_or_projection;
- bool uses_world_coordinates;
- Cull cull_mode;
+ bool uses_point_size = false;
+ bool uses_alpha = false;
+ bool uses_blend_alpha = false;
+ bool uses_alpha_clip = false;
+ bool uses_depth_pre_pass = false;
+ bool uses_discard = false;
+ bool uses_roughness = false;
+ bool uses_normal = false;
+ bool uses_particle_trails = false;
+
+ bool unshaded = false;
+ bool uses_vertex = false;
+ bool uses_position = false;
+ bool uses_sss = false;
+ bool uses_transmittance = false;
+ bool uses_screen_texture = false;
+ bool uses_depth_texture = false;
+ bool uses_normal_texture = false;
+ bool uses_time = false;
+ bool writes_modelview_or_projection = false;
+ bool uses_world_coordinates = false;
+ Cull cull_mode = CULL_DISABLED;
uint64_t last_pass = 0;
uint32_t index = 0;
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 b9f49cf008..1cbf804ece 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -1341,7 +1341,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
+ Plane near_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
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 60badbdfee..cdddc35579 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
@@ -415,8 +415,6 @@ RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_sour
SceneShaderForwardMobile::ShaderData::ShaderData() :
shader_list_element(this) {
- valid = false;
- uses_screen_texture = false;
}
SceneShaderForwardMobile::ShaderData::~ShaderData() {
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index b89fe908d3..50b5fb26ec 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -97,9 +97,9 @@ public:
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
};
- bool valid;
+ bool valid = false;
RID version;
- uint32_t vertex_input_mask;
+ uint32_t vertex_input_mask = 0;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
String path;
@@ -108,7 +108,7 @@ public:
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String code;
Map<StringName, Map<int, RID>> default_texture_params;
@@ -116,26 +116,26 @@ public:
DepthDraw depth_draw;
DepthTest depth_test;
- bool uses_point_size;
- bool uses_alpha;
- bool uses_blend_alpha;
- bool uses_alpha_clip;
- bool uses_depth_pre_pass;
- bool uses_discard;
- bool uses_roughness;
- bool uses_normal;
- bool uses_particle_trails;
-
- bool unshaded;
- bool uses_vertex;
- bool uses_sss;
- bool uses_transmittance;
- bool uses_screen_texture;
- bool uses_depth_texture;
- bool uses_normal_texture;
- bool uses_time;
- bool writes_modelview_or_projection;
- bool uses_world_coordinates;
+ bool uses_point_size = false;
+ bool uses_alpha = false;
+ bool uses_blend_alpha = false;
+ bool uses_alpha_clip = false;
+ bool uses_depth_pre_pass = false;
+ bool uses_discard = false;
+ bool uses_roughness = false;
+ bool uses_normal = false;
+ bool uses_particle_trails = false;
+
+ bool unshaded = false;
+ bool uses_vertex = false;
+ bool uses_sss = false;
+ bool uses_transmittance = false;
+ bool uses_screen_texture = false;
+ bool uses_depth_texture = false;
+ bool uses_normal_texture = false;
+ bool uses_time = false;
+ bool writes_modelview_or_projection = false;
+ bool uses_world_coordinates = false;
uint64_t last_pass = 0;
uint32_t index = 0;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 1e80381d88..ad83fc76b7 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -45,7 +45,7 @@ class PipelineCacheRD {
RD::PipelineMultisampleState multisample_state;
RD::PipelineDepthStencilState depth_stencil_state;
RD::PipelineColorBlendState blend_state;
- int dynamic_state_flags;
+ int dynamic_state_flags = 0;
Vector<RD::PipelineSpecializationConstant> base_specialization_constants;
struct Version {
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 8c727b2512..386bc18fcd 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -41,57 +41,57 @@
#include "servers/rendering/rendering_server_default.h"
void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
- p_mat4[0] = p_transform.elements[0][0];
- p_mat4[1] = p_transform.elements[0][1];
+ p_mat4[0] = p_transform.columns[0][0];
+ p_mat4[1] = p_transform.columns[0][1];
p_mat4[2] = 0;
p_mat4[3] = 0;
- p_mat4[4] = p_transform.elements[1][0];
- p_mat4[5] = p_transform.elements[1][1];
+ p_mat4[4] = p_transform.columns[1][0];
+ p_mat4[5] = p_transform.columns[1][1];
p_mat4[6] = 0;
p_mat4[7] = 0;
p_mat4[8] = 0;
p_mat4[9] = 0;
p_mat4[10] = 1;
p_mat4[11] = 0;
- p_mat4[12] = p_transform.elements[2][0];
- p_mat4[13] = p_transform.elements[2][1];
+ p_mat4[12] = p_transform.columns[2][0];
+ p_mat4[13] = p_transform.columns[2][1];
p_mat4[14] = 0;
p_mat4[15] = 1;
}
void RendererCanvasRenderRD::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) {
- p_mat2x4[0] = p_transform.elements[0][0];
- p_mat2x4[1] = p_transform.elements[1][0];
+ p_mat2x4[0] = p_transform.columns[0][0];
+ p_mat2x4[1] = p_transform.columns[1][0];
p_mat2x4[2] = 0;
- p_mat2x4[3] = p_transform.elements[2][0];
+ p_mat2x4[3] = p_transform.columns[2][0];
- p_mat2x4[4] = p_transform.elements[0][1];
- p_mat2x4[5] = p_transform.elements[1][1];
+ p_mat2x4[4] = p_transform.columns[0][1];
+ p_mat2x4[5] = p_transform.columns[1][1];
p_mat2x4[6] = 0;
- p_mat2x4[7] = p_transform.elements[2][1];
+ p_mat2x4[7] = p_transform.columns[2][1];
}
void RendererCanvasRenderRD::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) {
- p_mat2x3[0] = p_transform.elements[0][0];
- p_mat2x3[1] = p_transform.elements[0][1];
- p_mat2x3[2] = p_transform.elements[1][0];
- p_mat2x3[3] = p_transform.elements[1][1];
- p_mat2x3[4] = p_transform.elements[2][0];
- p_mat2x3[5] = p_transform.elements[2][1];
+ p_mat2x3[0] = p_transform.columns[0][0];
+ p_mat2x3[1] = p_transform.columns[0][1];
+ p_mat2x3[2] = p_transform.columns[1][0];
+ p_mat2x3[3] = p_transform.columns[1][1];
+ p_mat2x3[4] = p_transform.columns[2][0];
+ p_mat2x3[5] = p_transform.columns[2][1];
}
void RendererCanvasRenderRD::_update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4) {
- p_mat4[0] = p_transform.basis.elements[0][0];
- p_mat4[1] = p_transform.basis.elements[1][0];
- p_mat4[2] = p_transform.basis.elements[2][0];
+ p_mat4[0] = p_transform.basis.rows[0][0];
+ p_mat4[1] = p_transform.basis.rows[1][0];
+ p_mat4[2] = p_transform.basis.rows[2][0];
p_mat4[3] = 0;
- p_mat4[4] = p_transform.basis.elements[0][1];
- p_mat4[5] = p_transform.basis.elements[1][1];
- p_mat4[6] = p_transform.basis.elements[2][1];
+ p_mat4[4] = p_transform.basis.rows[0][1];
+ p_mat4[5] = p_transform.basis.rows[1][1];
+ p_mat4[6] = p_transform.basis.rows[2][1];
p_mat4[7] = 0;
- p_mat4[8] = p_transform.basis.elements[0][2];
- p_mat4[9] = p_transform.basis.elements[1][2];
- p_mat4[10] = p_transform.basis.elements[2][2];
+ p_mat4[8] = p_transform.basis.rows[0][2];
+ p_mat4[9] = p_transform.basis.rows[1][2];
+ p_mat4[10] = p_transform.basis.rows[2][2];
p_mat4[11] = 0;
p_mat4[12] = p_transform.origin.x;
p_mat4[13] = p_transform.origin.y;
@@ -1175,7 +1175,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
ERR_CONTINUE(!clight);
}
- Vector2 canvas_light_dir = l->xform_cache.elements[1].normalized();
+ Vector2 canvas_light_dir = l->xform_cache.columns[1].normalized();
state.light_uniforms[index].position[0] = -canvas_light_dir.x;
state.light_uniforms[index].position[1] = -canvas_light_dir.y;
@@ -1246,7 +1246,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix);
_update_transform_2d_to_mat2x4(l->xform_cache.affine_inverse(), state.light_uniforms[index].shadow_matrix);
- state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss
+ state.light_uniforms[index].height = l->height * (p_canvas_transform.columns[0].length() + p_canvas_transform.columns[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss
for (int i = 0; i < 4; i++) {
state.light_uniforms[index].shadow_color[i] = uint8_t(CLAMP(int32_t(l->shadow_color[i] * 255.0), 0, 255));
state.light_uniforms[index].color[i] = l->color[i];
@@ -1310,9 +1310,9 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
Transform2D normal_transform = p_canvas_transform;
- normal_transform.elements[0].normalize();
- normal_transform.elements[1].normalize();
- normal_transform.elements[2] = Vector2();
+ normal_transform.columns[0].normalize();
+ normal_transform.columns[1].normalize();
+ normal_transform.columns[2] = Vector2();
_update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform);
state_buffer.canvas_modulate[0] = p_modulate.r;
@@ -1645,7 +1645,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
_update_shadow_atlas();
- Vector2 light_dir = p_light_xform.elements[1].normalized();
+ Vector2 light_dir = p_light_xform.columns[1].normalized();
Vector2 center = p_clip_rect.get_center();
@@ -1713,8 +1713,8 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
RD::get_singleton()->draw_list_end();
Transform2D to_shadow;
- to_shadow.elements[0].x = 1.0 / -(half_size * 2.0);
- to_shadow.elements[2].x = 0.5;
+ to_shadow.columns[0].x = 1.0 / -(half_size * 2.0);
+ to_shadow.columns[2].x = 0.5;
cl->shadow.directional_xform = to_shadow * to_light_xform;
}
@@ -1726,14 +1726,14 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
Rect2i rect = texture_storage->render_target_get_sdf_rect(p_render_target);
Transform2D to_sdf;
- to_sdf.elements[0] *= rect.size.width;
- to_sdf.elements[1] *= rect.size.height;
- to_sdf.elements[2] = rect.position;
+ to_sdf.columns[0] *= rect.size.width;
+ to_sdf.columns[1] *= rect.size.height;
+ to_sdf.columns[2] = rect.position;
Transform2D to_clip;
- to_clip.elements[0] *= 2.0;
- to_clip.elements[1] *= 2.0;
- to_clip.elements[2] = -Vector2(1.0, 1.0);
+ to_clip.columns[0] *= 2.0;
+ to_clip.columns[1] *= 2.0;
+ to_clip.columns[2] = -Vector2(1.0, 1.0);
to_clip = to_clip * to_sdf.affine_inverse();
@@ -2232,12 +2232,6 @@ RS::ShaderNativeSourceCode RendererCanvasRenderRD::CanvasShaderData::get_native_
return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
}
-RendererCanvasRenderRD::CanvasShaderData::CanvasShaderData() {
- valid = false;
- uses_screen_texture = false;
- uses_sdf = false;
-}
-
RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
ERR_FAIL_COND(!canvas_singleton);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 6448e1a664..06970acca6 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -161,7 +161,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
BLEND_MODE_DISABLED,
};
- bool valid;
+ bool valid = false;
RID version;
PipelineVariants pipeline_variants;
String path;
@@ -170,7 +170,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String code;
Map<StringName, Map<int, RID>> default_texture_params;
@@ -190,7 +190,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- CanvasShaderData();
+ CanvasShaderData() {}
virtual ~CanvasShaderData();
};
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index fd56de845f..759b8690eb 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -286,7 +286,6 @@ RendererCompositorRD::RendererCompositorRD() {
}
singleton = this;
- time = 0;
texture_storage = memnew(RendererRD::TextureStorage);
material_storage = memnew(RendererRD::MaterialStorage);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 768e9e0947..1fd6550fb8 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -50,11 +50,11 @@ class RendererCompositorRD : public RendererCompositor {
protected:
UniformSetCacheRD *uniform_set_cache = nullptr;
RendererCanvasRenderRD *canvas = nullptr;
- RendererRD::LightStorage *light_storage;
- RendererRD::MaterialStorage *material_storage;
- RendererRD::MeshStorage *mesh_storage;
- RendererRD::ParticlesStorage *particles_storage;
- RendererRD::TextureStorage *texture_storage;
+ RendererRD::LightStorage *light_storage = nullptr;
+ RendererRD::MaterialStorage *material_storage = nullptr;
+ RendererRD::MeshStorage *mesh_storage = nullptr;
+ RendererRD::ParticlesStorage *particles_storage = nullptr;
+ RendererRD::TextureStorage *texture_storage = nullptr;
RendererStorageRD *storage = nullptr;
RendererSceneRenderRD *scene = nullptr;
@@ -92,8 +92,8 @@ protected:
Map<RID, RID> render_target_descriptors;
- double time;
- double delta;
+ double time = 0.0;
+ double delta = 0.0;
static uint64_t frame;
@@ -131,6 +131,7 @@ public:
static void make_current() {
_create_func = _create_current;
+ low_end = false;
}
static RendererCompositorRD *singleton;
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index 0a16bf4bd1..7aede6bb48 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -1115,6 +1115,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() {
void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -1228,17 +1229,17 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
push_constant.cam_extent[1] = vp_half.y;
push_constant.cam_extent[2] = -p_projection.get_z_near();
- push_constant.cam_transform[0] = p_transform.basis.elements[0][0];
- push_constant.cam_transform[1] = p_transform.basis.elements[1][0];
- push_constant.cam_transform[2] = p_transform.basis.elements[2][0];
+ push_constant.cam_transform[0] = p_transform.basis.rows[0][0];
+ push_constant.cam_transform[1] = p_transform.basis.rows[1][0];
+ push_constant.cam_transform[2] = p_transform.basis.rows[2][0];
push_constant.cam_transform[3] = 0;
- push_constant.cam_transform[4] = p_transform.basis.elements[0][1];
- push_constant.cam_transform[5] = p_transform.basis.elements[1][1];
- push_constant.cam_transform[6] = p_transform.basis.elements[2][1];
+ push_constant.cam_transform[4] = p_transform.basis.rows[0][1];
+ push_constant.cam_transform[5] = p_transform.basis.rows[1][1];
+ push_constant.cam_transform[6] = p_transform.basis.rows[2][1];
push_constant.cam_transform[7] = 0;
- push_constant.cam_transform[8] = p_transform.basis.elements[0][2];
- push_constant.cam_transform[9] = p_transform.basis.elements[1][2];
- push_constant.cam_transform[10] = p_transform.basis.elements[2][2];
+ push_constant.cam_transform[8] = p_transform.basis.rows[0][2];
+ push_constant.cam_transform[9] = p_transform.basis.rows[1][2];
+ push_constant.cam_transform[10] = p_transform.basis.rows[2][2];
push_constant.cam_transform[11] = 0;
push_constant.cam_transform[12] = p_transform.origin.x;
push_constant.cam_transform[13] = p_transform.origin.y;
@@ -1251,7 +1252,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
RD::get_singleton()->compute_list_end();
Size2 rtsize = texture_storage->render_target_get_size(p_render_target);
- storage->get_effects()->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
+ copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
}
void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
@@ -1469,7 +1470,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
continue;
}
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
dir.y *= y_mult;
dir.normalize();
lights[idx].direction[0] = dir.x;
@@ -1508,7 +1509,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
continue;
}
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
//faster to not do this here
//dir.y *= y_mult;
//dir.normalize();
@@ -1946,7 +1947,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
lights[idx].type = RSG::light_storage->light_get_type(li->light);
- Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
+ Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
dir.y *= y_mult; //only makes sense for directional
dir.normalize();
@@ -2416,7 +2417,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
Vector3 pos = to_probe_xform.xform(xform.origin);
- Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized();
+ Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_column(2)).normalized();
l.position[0] = pos.x;
l.position[1] = pos.y;
@@ -2593,17 +2594,17 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
Transform3D xform;
xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir);
- Vector3 x_dir = xform.basis.get_axis(0).abs();
+ Vector3 x_dir = xform.basis.get_column(0).abs();
int x_axis = int(Vector3(0, 1, 2).dot(x_dir));
- Vector3 y_dir = xform.basis.get_axis(1).abs();
+ Vector3 y_dir = xform.basis.get_column(1).abs();
int y_axis = int(Vector3(0, 1, 2).dot(y_dir));
- Vector3 z_dir = -xform.basis.get_axis(2);
+ Vector3 z_dir = -xform.basis.get_column(2);
int z_axis = int(Vector3(0, 1, 2).dot(z_dir.abs()));
Rect2i rect(aabb.position[x_axis], aabb.position[y_axis], aabb.size[x_axis], aabb.size[y_axis]);
- bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(0)) < 0);
- bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(1)) < 0);
- bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(2)) > 0);
+ bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(0)) < 0);
+ bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0);
+ bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0);
CameraMatrix cm;
cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
@@ -3070,17 +3071,17 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
- gipd.xform[0] = to_cell.basis.elements[0][0];
- gipd.xform[1] = to_cell.basis.elements[1][0];
- gipd.xform[2] = to_cell.basis.elements[2][0];
+ gipd.xform[0] = to_cell.basis.rows[0][0];
+ gipd.xform[1] = to_cell.basis.rows[1][0];
+ gipd.xform[2] = to_cell.basis.rows[2][0];
gipd.xform[3] = 0;
- gipd.xform[4] = to_cell.basis.elements[0][1];
- gipd.xform[5] = to_cell.basis.elements[1][1];
- gipd.xform[6] = to_cell.basis.elements[2][1];
+ gipd.xform[4] = to_cell.basis.rows[0][1];
+ gipd.xform[5] = to_cell.basis.rows[1][1];
+ gipd.xform[6] = to_cell.basis.rows[2][1];
gipd.xform[7] = 0;
- gipd.xform[8] = to_cell.basis.elements[0][2];
- gipd.xform[9] = to_cell.basis.elements[1][2];
- gipd.xform[10] = to_cell.basis.elements[2][2];
+ gipd.xform[8] = to_cell.basis.rows[0][2];
+ gipd.xform[9] = to_cell.basis.rows[1][2];
+ gipd.xform[10] = to_cell.basis.rows[2][2];
gipd.xform[11] = 0;
gipd.xform[12] = to_cell.origin.x;
gipd.xform[13] = to_cell.origin.y;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 26365aafc4..9f780013bd 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1556,8 +1556,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH);
- // TODO make sure texture_create_shared_from_slice works for multiview
-
RD::TextureFormat tf;
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->internal_width;
@@ -1583,55 +1581,63 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.mipmaps--;
rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- int base_width = rb->internal_width;
- int base_height = rb->internal_height;
+ for (uint32_t l = 0; l < rb->view_count; l++) {
+ RenderBuffers::Blur::Layer ll[2];
+ int base_width = rb->internal_width;
+ int base_height = rb->internal_height;
- for (uint32_t i = 0; i < mipmaps_required; i++) {
- RenderBuffers::Blur::Mipmap mm;
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i);
+ for (uint32_t i = 0; i < mipmaps_required; i++) {
+ RenderBuffers::Blur::Mipmap mm;
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, l, i);
- mm.width = base_width;
- mm.height = base_height;
+ mm.width = base_width;
+ mm.height = base_height;
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(mm.texture);
-
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
- }
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
- if (!_render_buffers_can_be_storage()) {
- // and half texture, this is an intermediate result so just allocate a texture, is this good enough?
- tf.width = MAX(1, base_width >> 1);
- tf.height = base_height;
- tf.mipmaps = 1; // 1 or 0?
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ }
- mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (!_render_buffers_can_be_storage()) {
+ // and half texture, this is an intermediate result so just allocate a texture, is this good enough?
+ tf.width = MAX(1, base_width >> 1);
+ tf.height = base_height;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.mipmaps = 1;
+
+ mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> half_fb;
+ half_fb.push_back(mm.half_texture);
+ mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
+ }
- Vector<RID> half_fb;
- half_fb.push_back(mm.half_texture);
- mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
- }
+ ll[0].mipmaps.push_back(mm);
- rb->blur[0].mipmaps.push_back(mm);
+ if (i > 0) {
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, l, i - 1);
- if (i > 0) {
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(mm.texture);
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ // We can re-use the half texture here as it is an intermediate result
+ }
- // We can re-use the half texture here as it is an intermediate result
+ ll[1].mipmaps.push_back(mm);
}
- rb->blur[1].mipmaps.push_back(mm);
+ base_width = MAX(1, base_width >> 1);
+ base_height = MAX(1, base_height >> 1);
}
- base_width = MAX(1, base_width >> 1);
- base_height = MAX(1, base_height >> 1);
+ rb->blur[0].layers.push_back(ll[0]);
+ rb->blur[1].layers.push_back(ll[1]);
}
if (!_render_buffers_can_be_storage()) {
@@ -1640,21 +1646,19 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
tf.width = rb->internal_width;
tf.height = rb->internal_height;
- tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
- tf.array_layers = rb->view_count;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1; // Our DOF effect handles one eye per turn
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
tf.mipmaps = 1;
for (uint32_t i = 0; i < 4; i++) {
// associated blur texture
RID texture;
- if (i == 0) {
- texture = rb->texture;
- } else if (i == 1) {
- texture = rb->blur[0].mipmaps[0].texture;
+ if (i == 1) {
+ texture = rb->blur[0].layers[0].mipmaps[0].texture;
} else if (i == 2) {
- texture = rb->blur[1].mipmaps[0].texture;
+ texture = rb->blur[1].layers[0].mipmaps[0].texture;
} else if (i == 3) {
- texture = rb->blur[0].mipmaps[1].texture;
+ texture = rb->blur[0].layers[0].mipmaps[1].texture;
}
// create weight texture
@@ -1662,7 +1666,9 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
// create frame buffer
Vector<RID> fb;
- fb.push_back(texture);
+ if (i != 0) {
+ fb.push_back(texture);
+ }
fb.push_back(rb->weight_buffers[i].weight);
rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
@@ -1672,13 +1678,6 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.height = MAX(1u, tf.height >> 1);
}
}
-
- {
- // and finally an FB for just our base weights
- Vector<RID> fb;
- fb.push_back(rb->weight_buffers[0].weight);
- rb->base_weight_fb = RD::get_singleton()->framebuffer_create(fb);
- }
}
}
@@ -1765,6 +1764,21 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
}
void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
+ if (rb->views.size() > 1) { // if 1 these are copies ofs rb->internal_texture, rb->depth_texture and rb->texture_fb
+ for (int i = 0; i < rb->views.size(); i++) {
+ if (rb->views[i].view_fb.is_valid()) {
+ RD::get_singleton()->free(rb->views[i].view_fb);
+ }
+ if (rb->views[i].view_texture.is_valid()) {
+ RD::get_singleton()->free(rb->views[i].view_texture);
+ }
+ if (rb->views[i].view_depth.is_valid()) {
+ RD::get_singleton()->free(rb->views[i].view_depth);
+ }
+ }
+ }
+ rb->views.clear();
+
if (rb->texture_fb.is_valid()) {
RD::get_singleton()->free(rb->texture_fb);
rb->texture_fb = RID();
@@ -1813,24 +1827,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
}
for (int i = 0; i < 2; i++) {
- for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
- // do we free the texture slice here? or is it enough to free the main texture?
+ for (int l = 0; l < rb->blur[i].layers.size(); l++) {
+ for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) {
+ // do we free the texture slice here? or is it enough to free the main texture?
- // do free the mobile extra stuff
- if (rb->blur[i].mipmaps[m].fb.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb);
- }
- // texture and framebuffer in both blur mipmaps are shared, so only free from the first one
- if (i == 0) {
- if (rb->blur[i].mipmaps[m].half_fb.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb);
+ // do free the mobile extra stuff
+ if (rb->blur[i].layers[l].mipmaps[m].fb.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].fb);
}
- if (rb->blur[i].mipmaps[m].half_texture.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture);
+ // texture and framebuffer in both blur mipmaps are shared, so only free from the first one
+ if (i == 0) {
+ if (rb->blur[i].layers[l].mipmaps[m].half_fb.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_fb);
+ }
+ if (rb->blur[i].layers[l].mipmaps[m].half_texture.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_texture);
+ }
}
}
}
- rb->blur[i].mipmaps.clear();
+ rb->blur[i].layers.clear();
if (rb->blur[i].texture.is_valid()) {
RD::get_singleton()->free(rb->blur[i].texture);
@@ -1998,8 +2014,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
_allocate_blur_textures(rb);
}
- storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture);
+ storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture);
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
@@ -2295,14 +2311,14 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) {
ERR_FAIL_COND(!rb);
if (rb->ss_effects.last_frame.is_valid()) {
- storage->get_effects()->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
+ copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
int width = rb->width;
int height = rb->height;
for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) {
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
- storage->get_effects()->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
+ copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
}
}
}
@@ -2317,19 +2333,19 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
_allocate_blur_textures(rb);
}
- // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
-
bool can_use_storage = _render_buffers_can_be_storage();
- if (can_use_storage) {
- storage->get_effects()->copy_to_rect(rb->texture, rb->blur[0].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height));
- for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) {
- storage->get_effects()->make_mipmap(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].texture, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height));
- }
- } else {
- storage->get_effects()->copy_to_fb_rect(rb->texture, rb->blur[0].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height));
- for (int i = 1; i < rb->blur[0].mipmaps.size(); i++) {
- storage->get_effects()->make_mipmap_raster(rb->blur[0].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i].fb, Size2i(rb->blur[0].mipmaps[i].width, rb->blur[0].mipmaps[i].height));
+ for (uint32_t v = 0; v < rb->view_count; v++) {
+ if (can_use_storage) {
+ copy_effects->copy_to_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height));
+ for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) {
+ copy_effects->make_mipmap(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].texture, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height));
+ }
+ } else {
+ copy_effects->copy_to_fb_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height));
+ for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) {
+ copy_effects->make_mipmap_raster(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].fb, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height));
+ }
}
}
@@ -2351,9 +2367,9 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
bool can_use_storage = _render_buffers_can_be_storage();
if (can_use_storage) {
- storage->get_effects()->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height));
+ copy_effects->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height));
} else {
- storage->get_effects()->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height));
+ copy_effects->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height));
}
RD::get_singleton()->draw_command_end_label();
@@ -2371,30 +2387,33 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
bool can_use_storage = _render_buffers_can_be_storage();
- // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
-
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
RD::get_singleton()->draw_command_begin_label("DOF");
if (rb->blur[0].texture.is_null()) {
_allocate_blur_textures(rb);
}
- EffectsRD::BokehBuffers buffers;
+ RendererRD::BokehDOF::BokehBuffers buffers;
// Textures we use
buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
- buffers.base_texture = rb->internal_texture;
- buffers.depth_texture = rb->depth_texture;
- buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
- buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
- buffers.half_texture[1] = rb->blur[0].mipmaps[1].texture;
+ buffers.secondary_texture = rb->blur[0].layers[0].mipmaps[0].texture;
+ buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture;
+ buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture;
float bokeh_size = camfx->dof_blur_amount * 64.0;
if (can_use_storage) {
- storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal);
+ for (uint32_t i = 0; i < rb->view_count; i++) {
+ buffers.base_texture = rb->views[i].view_texture;
+ buffers.depth_texture = rb->views[i].view_depth;
+
+ // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
+ float z_near = p_render_data->view_projection[i].get_z_near();
+ float z_far = p_render_data->view_projection[i].get_z_far();
+ bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal);
+ };
} else {
// Set framebuffers.
- buffers.base_fb = rb->texture_fb;
buffers.secondary_fb = rb->weight_buffers[1].fb;
buffers.half_fb[0] = rb->weight_buffers[2].fb;
buffers.half_fb[1] = rb->weight_buffers[3].fb;
@@ -2404,9 +2423,18 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.weight_texture[3] = rb->weight_buffers[3].weight;
// Set weight buffers.
- buffers.base_weight_fb = rb->base_weight_fb;
+ buffers.base_weight_fb = rb->weight_buffers[0].fb;
- storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_orthogonal);
+ for (uint32_t i = 0; i < rb->view_count; i++) {
+ buffers.base_texture = rb->views[i].view_texture;
+ buffers.depth_texture = rb->views[i].view_depth;
+ buffers.base_fb = rb->views[i].view_fb;
+
+ // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
+ float z_near = p_render_data->view_projection[i].get_z_near();
+ float z_far = p_render_data->view_projection[i].get_z_far();
+ bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal);
+ }
}
RD::get_singleton()->draw_command_end_label();
}
@@ -2449,33 +2477,36 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
if (env->glow_levels[i] > 0.0) {
- if (i >= rb->blur[1].mipmaps.size()) {
- max_glow_level = rb->blur[1].mipmaps.size() - 1;
+ if (i >= rb->blur[1].layers[0].mipmaps.size()) {
+ max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1;
} else {
max_glow_level = i;
}
}
}
- for (int i = 0; i < (max_glow_level + 1); i++) {
- int vp_w = rb->blur[1].mipmaps[i].width;
- int vp_h = rb->blur[1].mipmaps[i].height;
+ float luminance_multiplier = _render_buffers_get_luminance_multiplier();
+ for (uint32_t l = 0; l < rb->view_count; l++) {
+ for (int i = 0; i < (max_glow_level + 1); i++) {
+ int vp_w = rb->blur[1].layers[l].mipmaps[i].width;
+ int vp_h = rb->blur[1].layers[l].mipmaps[i].height;
- if (i == 0) {
- RID luminance_texture;
- if (env->auto_exposure && rb->luminance.current.is_valid()) {
- luminance_texture = rb->luminance.current;
- }
- if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
- } else {
- storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
- }
- } else {
- if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ if (i == 0) {
+ RID luminance_texture;
+ if (env->auto_exposure && rb->luminance.current.is_valid()) {
+ luminance_texture = rb->luminance.current;
+ }
+ if (can_use_storage) {
+ copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ } else {
+ copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ }
} else {
- storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality);
+ if (can_use_storage) {
+ copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ } else {
+ copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ }
}
}
}
@@ -2503,8 +2534,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
tonemap.glow_levels[i] = env->glow_levels[i];
}
- tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width;
- tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height;
+ tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width;
+ tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
tonemap.glow_texture = rb->blur[1].texture;
if (env->glow_map.is_valid()) {
@@ -2652,7 +2683,6 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- EffectsRD *effects = storage->get_effects();
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -2666,7 +2696,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
}
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
@@ -2675,7 +2705,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
RID shadow_atlas_texture = directional_shadow_get_texture();
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
@@ -2685,7 +2715,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
if (decal_atlas.is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
+ copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
}
}
@@ -2693,36 +2723,36 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
if (rb->luminance.current.is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+ copy_effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ copy_effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ copy_effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
RID ambient_texture = rb->ambient_buffer;
RID reflection_texture = rb->reflection_buffer;
- effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
+ copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
if (p_occlusion_buffer.is_valid()) {
Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
+ copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
}
}
}
@@ -3035,12 +3065,38 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
- if (!_render_buffers_can_be_storage()) {
- // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
- Vector<RID> fb;
- fb.push_back(rb->internal_texture);
+ {
+ if (!_render_buffers_can_be_storage()) {
+ // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
+ Vector<RID> fb;
+ fb.push_back(rb->internal_texture);
+
+ rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
+ }
+
+ rb->views.clear(); // JIC
+ if (rb->view_count == 1) {
+ // copy as a convenience
+ RenderBuffers::View view;
+ view.view_texture = rb->internal_texture;
+ view.view_depth = rb->depth_texture;
+ view.view_fb = rb->texture_fb;
+ rb->views.push_back(view);
+ } else {
+ for (uint32_t i = 0; i < rb->view_count; i++) {
+ RenderBuffers::View view;
+ view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->internal_texture, i, 0);
+ view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0);
+
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(view.view_texture);
+ view.view_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, 1);
+ }
- rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
+ rb->views.push_back(view);
+ }
+ }
}
RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
@@ -3280,7 +3336,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_directional_light_count = 0;
r_positional_light_count = 0;
- Plane camera_plane(-p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
+ Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
cluster.omni_light_count = 0;
cluster.spot_light_count = 0;
@@ -3735,12 +3791,13 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
float fade = 1.0;
if (texture_storage->decal_is_distance_fade_enabled(decal)) {
- real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
- float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
- float fade_length = texture_storage->decal_get_distance_fade_length(decal);
+ const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ const float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+ const float fade_length = texture_storage->decal_get_distance_fade_length(decal);
if (distance > fade_begin) {
- fade = 1.0 - (distance - fade_begin) / fade_length;
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
+ fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
}
}
@@ -3753,7 +3810,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
RendererStorageRD::store_transform(to_decal_xform, dd.xform);
- Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
+ Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
dd.normal[0] = normal.x;
@@ -3976,10 +4033,6 @@ RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_sour
return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
}
-RendererSceneRenderRD::FogShaderData::FogShaderData() {
- valid = false;
-}
-
RendererSceneRenderRD::FogShaderData::~FogShaderData() {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
@@ -4828,7 +4881,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
render_state.shadows.clear();
render_state.directional_shadows.clear();
- Plane camera_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
+ Plane camera_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < render_state.render_shadow_count; i++) {
@@ -5024,7 +5077,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// this should be the same for all cameras..
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
+ render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_column(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
render_data.screen_mesh_lod_threshold = 0.0;
@@ -5343,7 +5396,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
cam_pos.y += extents.y;
Transform3D cam_xform;
- cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_axis(Vector3::AXIS_Y), -p_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
+ cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_column(Vector3::AXIS_Y), -p_transform.basis.get_column(Vector3::AXIS_Z).normalized());
RID fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);
@@ -5839,12 +5892,21 @@ void fog() {
cull_argument.set_page_pool(&cull_argument_pool);
+ bool can_use_storage = _render_buffers_can_be_storage();
+ bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
+ copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
tone_mapper = memnew(RendererRD::ToneMapper);
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ if (bokeh_dof) {
+ memdelete(bokeh_dof);
+ }
+ if (copy_effects) {
+ memdelete(copy_effects);
+ }
if (tone_mapper) {
memdelete(tone_mapper);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 2b79d8997f..f60b7c7232 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -35,6 +35,8 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h"
@@ -47,10 +49,10 @@
#include "servers/rendering/rendering_device.h"
struct RenderDataRD {
- RID render_buffers = RID();
+ RID render_buffers;
- Transform3D cam_transform = Transform3D();
- CameraMatrix cam_projection = CameraMatrix();
+ Transform3D cam_transform;
+ CameraMatrix cam_projection;
bool cam_orthogonal = false;
// For stereo rendering
@@ -67,18 +69,18 @@ struct RenderDataRD {
const PagedArray<RID> *decals = nullptr;
const PagedArray<RID> *lightmaps = nullptr;
const PagedArray<RID> *fog_volumes = nullptr;
- RID environment = RID();
- RID camera_effects = RID();
- RID shadow_atlas = RID();
- RID reflection_atlas = RID();
- RID reflection_probe = RID();
+ RID environment;
+ RID camera_effects;
+ RID shadow_atlas;
+ RID reflection_atlas;
+ RID reflection_probe;
int reflection_probe_pass = 0;
float lod_distance_multiplier = 0.0;
- Plane lod_camera_plane = Plane();
+ Plane lod_camera_plane;
float screen_mesh_lod_threshold = 0.0;
- RID cluster_buffer = RID();
+ RID cluster_buffer;
uint32_t cluster_size = 0;
uint32_t cluster_max_elements = 0;
@@ -94,9 +96,11 @@ class RendererSceneRenderRD : public RendererSceneRender {
protected:
RendererStorageRD *storage = nullptr;
+ RendererRD::BokehDOF *bokeh_dof = nullptr;
+ RendererRD::CopyEffects *copy_effects = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
- double time;
- double time_step = 0;
+ double time = 0.0;
+ double time_step = 0.0;
struct RenderBufferData {
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
@@ -236,7 +240,7 @@ private:
struct DecalInstance {
RID decal;
Transform3D transform;
- uint32_t cull_mask;
+ uint32_t cull_mask = 0;
ForwardID forward_id = -1;
};
@@ -256,7 +260,7 @@ private:
struct ShadowShrinkStage {
RID texture;
RID filter_texture;
- uint32_t size;
+ uint32_t size = 0;
};
struct ShadowAtlas {
@@ -268,27 +272,20 @@ private:
};
struct Quadrant {
- uint32_t subdivision;
+ uint32_t subdivision = 0;
struct Shadow {
RID owner;
- uint64_t version;
- uint64_t fog_version; // used for fog
- uint64_t alloc_tick;
-
- Shadow() {
- version = 0;
- fog_version = 0;
- alloc_tick = 0;
- }
+ uint64_t version = 0;
+ uint64_t fog_version = 0; // used for fog
+ uint64_t alloc_tick = 0;
+
+ Shadow() {}
};
Vector<Shadow> shadows;
- Quadrant() {
- subdivision = 0; //not in use
- }
-
+ Quadrant() {}
} quadrants[4];
int size_order[4] = { 0, 1, 2, 3 };
@@ -337,7 +334,6 @@ private:
int size = 0;
bool use_16_bits = true;
int current_light = 0;
-
} directional_shadow;
void _update_directional_shadow_atlas();
@@ -490,6 +486,14 @@ private:
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
+ // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
+ struct View {
+ RID view_texture; // texture slice for this view/layer
+ RID view_depth; // depth slice for this view/layer
+ RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
+ };
+ Vector<View> views;
+
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
RendererSceneGIRD::RenderBuffersGI gi;
@@ -511,19 +515,22 @@ private:
RID half_fb;
};
- Vector<Mipmap> mipmaps;
+ struct Layer {
+ Vector<Mipmap> mipmaps;
+ };
+
+ Vector<Layer> layers;
};
Blur blur[2]; //the second one starts from the first mipmap
struct WeightBuffers {
RID weight;
- RID fb; // FB with both texture and weight
+ RID fb; // FB with both texture and weight writing into one level lower
};
// 2 full size, 2 half size
WeightBuffers weight_buffers[4]; // Only used in raster
- RID base_weight_fb; // base buffer for weight
RID depth_back_texture;
RID depth_back_fb; // only used on mobile
@@ -910,7 +917,7 @@ private:
void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
struct FogShaderData : public RendererRD::ShaderData {
- bool valid;
+ bool valid = false;
RID version;
RID pipeline;
@@ -918,13 +925,13 @@ private:
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String path;
String code;
Map<StringName, Map<int, RID>> default_texture_params;
- bool uses_time;
+ bool uses_time = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
@@ -935,7 +942,8 @@ private:
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- FogShaderData();
+
+ FogShaderData() {}
virtual ~FogShaderData();
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index db7a5250b6..4e62dee6af 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
#include "renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
@@ -224,10 +225,6 @@ RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_
return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
}
-RendererSceneSkyRD::SkyShaderData::SkyShaderData() {
- valid = false;
-}
-
RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
@@ -256,17 +253,17 @@ RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
// Render sky
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
- p_array[0] = p_basis.elements[0][0];
- p_array[1] = p_basis.elements[1][0];
- p_array[2] = p_basis.elements[2][0];
+ p_array[0] = p_basis.rows[0][0];
+ p_array[1] = p_basis.rows[1][0];
+ p_array[2] = p_basis.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_basis.elements[0][1];
- p_array[5] = p_basis.elements[1][1];
- p_array[6] = p_basis.elements[2][1];
+ p_array[4] = p_basis.rows[0][1];
+ p_array[5] = p_basis.rows[1][1];
+ p_array[6] = p_basis.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_basis.elements[0][2];
- p_array[9] = p_basis.elements[1][2];
- p_array[10] = p_basis.elements[2][2];
+ p_array[8] = p_basis.rows[0][2];
+ p_array[9] = p_basis.rows[1][2];
+ p_array[10] = p_basis.rows[2][2];
p_array[11] = 0;
}
@@ -734,8 +731,10 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
return true;
}
-Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size) {
+Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
if (radiance.is_valid()) {
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
tf.width = p_size.width;
@@ -743,7 +742,7 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
- p_storage->get_effects()->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1);
+ copy_effects->copy_cubemap_to_panorama(radiance, rad_tex, p_size, p_roughness_layers, reflection.layers.size() > 1);
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);
RD::get_singleton()->free(rad_tex);
@@ -1909,7 +1908,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool
update_dirty_skys();
- return sky->bake_panorama(storage, p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
+ return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
}
RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 010e2178a9..ec225019c8 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -106,7 +106,7 @@ private:
};
struct SkyShaderData : public RendererRD::ShaderData {
- bool valid;
+ bool valid = false;
RID version;
PipelineCacheRD pipelines[SKY_VERSION_MAX];
@@ -114,17 +114,17 @@ private:
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String path;
String code;
Map<StringName, Map<int, RID>> default_texture_params;
- bool uses_time;
- bool uses_position;
- bool uses_half_res;
- bool uses_quarter_res;
- bool uses_light;
+ bool uses_time = false;
+ bool uses_position = false;
+ bool uses_half_res = false;
+ bool uses_quarter_res = false;
+ bool uses_light = false;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
@@ -135,7 +135,8 @@ private:
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- SkyShaderData();
+
+ SkyShaderData() {}
virtual ~SkyShaderData();
};
@@ -272,7 +273,7 @@ public:
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
- Ref<Image> bake_panorama(RendererStorageRD *p_storage, float p_energy, int p_roughness_layers, const Size2i &p_size);
+ Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size);
};
uint32_t sky_ggx_samples_quality;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index fa9f87abbe..cf642c38c9 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -727,6 +727,10 @@ RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const {
return RenderingDevice::get_singleton()->get_device_type();
}
+String RendererStorageRD::get_video_adapter_api_version() const {
+ return RenderingDevice::get_singleton()->get_device_api_version();
+}
+
RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
RendererStorageRD::RendererStorageRD() {
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 37c76f9c62..07fae45a26 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -45,17 +45,17 @@
class RendererStorageRD : public RendererStorage {
public:
static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[1][0];
- p_array[2] = p_mtx.basis.elements[2][0];
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[1][0];
+ p_array[2] = p_mtx.basis.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.basis.elements[0][1];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[2][1];
+ p_array[4] = p_mtx.basis.rows[0][1];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.basis.elements[0][2];
- p_array[9] = p_mtx.basis.elements[1][2];
- p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[8] = p_mtx.basis.rows[0][2];
+ p_array[9] = p_mtx.basis.rows[1][2];
+ p_array[10] = p_mtx.basis.rows[2][2];
p_array[11] = 0;
p_array[12] = p_mtx.origin.x;
p_array[13] = p_mtx.origin.y;
@@ -64,47 +64,47 @@ public:
}
static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.elements[0][0];
- p_array[1] = p_mtx.elements[1][0];
- p_array[2] = p_mtx.elements[2][0];
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.elements[0][1];
- p_array[5] = p_mtx.elements[1][1];
- p_array[6] = p_mtx.elements[2][1];
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.elements[0][2];
- p_array[9] = p_mtx.elements[1][2];
- p_array[10] = p_mtx.elements[2][2];
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.elements[0][0];
- p_array[1] = p_mtx.elements[1][0];
- p_array[2] = p_mtx.elements[2][0];
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.elements[0][1];
- p_array[5] = p_mtx.elements[1][1];
- p_array[6] = p_mtx.elements[2][1];
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.elements[0][2];
- p_array[9] = p_mtx.elements[1][2];
- p_array[10] = p_mtx.elements[2][2];
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
p_array[11] = 0;
}
static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[0][1];
- p_array[2] = p_mtx.basis.elements[0][2];
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[0][1];
+ p_array[2] = p_mtx.basis.rows[0][2];
p_array[3] = p_mtx.origin.x;
- p_array[4] = p_mtx.basis.elements[1][0];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[1][2];
+ p_array[4] = p_mtx.basis.rows[1][0];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[1][2];
p_array[7] = p_mtx.origin.y;
- p_array[8] = p_mtx.basis.elements[2][0];
- p_array[9] = p_mtx.basis.elements[2][1];
- p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[8] = p_mtx.basis.rows[2][0];
+ p_array[9] = p_mtx.basis.rows[2][1];
+ p_array[10] = p_mtx.basis.rows[2][2];
p_array[11] = p_mtx.origin.z;
}
@@ -284,6 +284,7 @@ public:
String get_video_adapter_name() const;
String get_video_adapter_vendor() const;
RenderingDevice::DeviceType get_video_adapter_type() const;
+ String get_video_adapter_api_version() const;
virtual void capture_timestamps_begin();
virtual void capture_timestamp(const String &p_name);
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
deleted file mode 100644
index e7a2e18323..0000000000
--- a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
+++ /dev/null
@@ -1,21 +0,0 @@
-#define FLAG_HORIZONTAL (1 << 0)
-#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
-#define FLAG_GLOW_FIRST_PASS (1 << 2)
-
-layout(push_constant, std430) uniform Blur {
- vec2 pixel_size;
- uint flags;
- uint pad;
-
- // Glow.
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
-
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
-}
-blur;
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index f8b4e3f610..96f5c3e9f2 100644
--- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -53,7 +53,9 @@ void main() {
#ifdef MODE_GAUSSIAN_BLUR
- //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
+ // Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
+
+ // note, for blur blur.luminance_multiplier is irrelavant, we would be multiplying and then dividing by this amount.
if (bool(blur.flags & FLAG_HORIZONTAL)) {
vec2 pix_size = blur.pixel_size;
@@ -94,6 +96,7 @@ void main() {
if (bool(blur.flags & FLAG_HORIZONTAL)) {
vec2 pix_size = blur.pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
+
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
GLOW_ADD(vec2(1.0, 0.0), 0.165569);
GLOW_ADD(vec2(2.0, 0.0), 0.140367);
@@ -101,7 +104,10 @@ void main() {
GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
+
+ // only do this in the horizontal pass, if we also do this in the vertical pass we're doubling up.
color *= blur.glow_strength;
+
frag_color = color;
} else {
vec2 pix_size = blur.pixel_size;
@@ -110,13 +116,17 @@ void main() {
GLOW_ADD(vec2(0.0, 2.0), 0.122581);
GLOW_ADD(vec2(0.0, -1.0), 0.233062);
GLOW_ADD(vec2(0.0, -2.0), 0.122581);
- color *= blur.glow_strength;
+
frag_color = color;
}
#undef GLOW_ADD
if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
+ // In the first pass bring back to correct color range else we're applying the wrong threshold
+ // in subsequent passes we can use it as is as we'd just be undoing it right after.
+ frag_color *= blur.luminance_multiplier;
+
#ifdef GLOW_USE_AUTO_EXPOSURE
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
@@ -126,10 +136,10 @@ void main() {
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
- frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
+ frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)) / blur.luminance_multiplier;
}
-#endif
+#endif // MODE_GAUSSIAN_GLOW
#ifdef MODE_COPY
vec4 color = textureLod(source_color, uv_interp, 0.0);
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
new file mode 100644
index 0000000000..730504571a
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
@@ -0,0 +1,26 @@
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
+#define FLAG_GLOW_FIRST_PASS (1 << 2)
+
+layout(push_constant, std430) uniform Blur {
+ vec2 pixel_size; // 08 - 08
+ uint flags; // 04 - 12
+ uint pad; // 04 - 16
+
+ // Glow.
+ float glow_strength; // 04 - 20
+ float glow_bloom; // 04 - 24
+ float glow_hdr_threshold; // 04 - 28
+ float glow_hdr_scale; // 04 - 32
+
+ float glow_exposure; // 04 - 36
+ float glow_white; // 04 - 40
+ float glow_luminance_cap; // 04 - 44
+ float glow_auto_exposure_grey; // 04 - 48
+
+ float luminance_multiplier; // 04 - 52
+ float res1; // 04 - 56
+ float res2; // 04 - 60
+ float res3; // 04 - 64
+}
+blur;
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0438671dd2..0438671dd2 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
index b90a527554..b90a527554 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a3b3938ee9..a3b3938ee9 100644
--- a/servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
diff --git a/servers/rendering/renderer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index 4563ac7af9..3a4ef86ef0 100644
--- a/servers/rendering/renderer_rd/shaders/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -189,7 +189,7 @@ void main() {
#endif
color *= params.glow_exposure;
- float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114));
+ float luminance = max(color.r, max(color.g, color.b));
float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
color = min(color * feedback, vec4(params.glow_luminance_cap));
diff --git a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 9787c9879d..9787c9879d 100644
--- a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
index 19a9350137..5a238452c0 100644
--- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
@@ -44,7 +44,11 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#ifdef MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2DArray source_glow;
+#else
layout(set = 2, binding = 0) uniform sampler2D source_glow;
+#endif
layout(set = 2, binding = 1) uniform sampler2D glow_map;
#ifdef USE_1D_LUT
@@ -118,6 +122,36 @@ float h1(float a) {
return 1.0f + w3(a) / (w2(a) + w3(a));
}
+#ifdef MULTIVIEW
+vec4 texture2D_bicubic(sampler2DArray tex, vec2 uv, int p_lod) {
+ float lod = float(p_lod);
+ vec2 tex_size = vec2(params.glow_texture_size >> p_lod);
+ vec2 pixel_size = vec2(1.0f) / tex_size;
+
+ uv = uv * tex_size + vec2(0.5f);
+
+ vec2 iuv = floor(uv);
+ vec2 fuv = fract(uv);
+
+ float g0x = g0(fuv.x);
+ float g1x = g1(fuv.x);
+ float h0x = h0(fuv.x);
+ float h1x = h1(fuv.x);
+ float h0y = h0(fuv.y);
+ float h1y = h1(fuv.y);
+
+ vec3 p0 = vec3((vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex);
+ vec3 p1 = vec3((vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size, ViewIndex);
+ vec3 p2 = vec3((vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex);
+ vec3 p3 = vec3((vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size, ViewIndex);
+
+ return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
+ (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
+}
+
+#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
+#else // MULTIVIEW
+
vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
float lod = float(p_lod);
vec2 tex_size = vec2(params.glow_texture_size >> p_lod);
@@ -145,12 +179,17 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
+#endif // !MULTIVIEW
-#else
+#else // USE_GLOW_FILTER_BICUBIC
+#ifdef MULTIVIEW
+#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, vec3(m_uv, ViewIndex), float(m_lod))
+#else // MULTIVIEW
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
+#endif // !MULTIVIEW
-#endif
+#endif // !USE_GLOW_FILTER_BICUBIC
vec3 tonemap_filmic(vec3 color, float white) {
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
@@ -231,7 +270,11 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
}
}
+#ifdef MULTIVIEW
+vec3 gather_glow(sampler2DArray tex, vec2 uv) { // sample all selected glow levels, view is added to uv later
+#else
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
+#endif // defined(MULTIVIEW)
vec3 glow = vec3(0.0f);
if (params.glow_levels[0] > 0.0001) {
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index c3747ffabc..550fc7d788 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -554,13 +554,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
Transform2D v = value;
//in std140 members of mat2 are treated as vec4s
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[0][1];
+ gui[0] = v.columns[0][0];
+ gui[1] = v.columns[0][1];
gui[2] = 0; // ignored
gui[3] = 0; // ignored
- gui[4] = v.elements[1][0];
- gui[5] = v.elements[1][1];
+ gui[4] = v.columns[1][0];
+ gui[5] = v.columns[1][1];
gui[6] = 0; // ignored
gui[7] = 0; // ignored
}
@@ -604,19 +604,19 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} else {
Basis v = value;
- gui[0] = v.elements[0][0];
- gui[1] = v.elements[1][0];
- gui[2] = v.elements[2][0];
+ gui[0] = v.rows[0][0];
+ gui[1] = v.rows[1][0];
+ gui[2] = v.rows[2][0];
gui[3] = 0; // ignored
- gui[4] = v.elements[0][1];
- gui[5] = v.elements[1][1];
- gui[6] = v.elements[2][1];
+ gui[4] = v.rows[0][1];
+ gui[5] = v.rows[1][1];
+ gui[6] = v.rows[2][1];
gui[7] = 0; // ignored
- gui[8] = v.elements[0][2];
- gui[9] = v.elements[1][2];
- gui[10] = v.elements[2][2];
+ gui[8] = v.rows[0][2];
+ gui[9] = v.rows[1][2];
+ gui[10] = v.rows[2][2];
gui[11] = 0; // ignored
}
} break;
@@ -672,19 +672,19 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} else {
Transform3D v = value;
- gui[0] = v.basis.elements[0][0];
- gui[1] = v.basis.elements[1][0];
- gui[2] = v.basis.elements[2][0];
+ gui[0] = v.basis.rows[0][0];
+ gui[1] = v.basis.rows[1][0];
+ gui[2] = v.basis.rows[2][0];
gui[3] = 0;
- gui[4] = v.basis.elements[0][1];
- gui[5] = v.basis.elements[1][1];
- gui[6] = v.basis.elements[2][1];
+ gui[4] = v.basis.rows[0][1];
+ gui[5] = v.basis.rows[1][1];
+ gui[6] = v.basis.rows[2][1];
gui[7] = 0;
- gui[8] = v.basis.elements[0][2];
- gui[9] = v.basis.elements[1][2];
- gui[10] = v.basis.elements[2][2];
+ gui[8] = v.basis.rows[0][2];
+ gui[9] = v.basis.rows[1][2];
+ gui[10] = v.basis.rows[2][2];
gui[11] = 0;
gui[12] = v.origin.x;
@@ -1420,6 +1420,25 @@ MaterialStorage::MaterialStorage() {
//custom sampler
sampler_rd_configure_custom(0.0f);
+ // buffers
+ { //create index array for copy shaders
+ Vector<uint8_t> pv;
+ pv.resize(6 * 4);
+ {
+ uint8_t *w = pv.ptrw();
+ int *p32 = (int *)w;
+ p32[0] = 0;
+ p32[1] = 1;
+ p32[2] = 2;
+ p32[3] = 0;
+ p32[4] = 2;
+ p32[5] = 3;
+ }
+ quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ quad_index_array = RD::get_singleton()->index_array_create(quad_index_buffer, 0, 6);
+ }
+
+ // Shaders
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
shader_data_request_func[i] = nullptr;
}
@@ -1441,6 +1460,10 @@ MaterialStorage::~MaterialStorage() {
memdelete_arr(global_variables.buffer_dirty_regions);
RD::get_singleton()->free(global_variables.buffer);
+ // buffers
+
+ RD::get_singleton()->free(quad_index_buffer); //array gets freed as dependency
+
//def samplers
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
@@ -1767,19 +1790,19 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
case RS::GLOBAL_VAR_TYPE_MAT3: {
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
Basis v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[1][0];
- bv[0].z = v.elements[2][0];
+ bv[0].x = v.rows[0][0];
+ bv[0].y = v.rows[1][0];
+ bv[0].z = v.rows[2][0];
bv[0].w = 0;
- bv[1].x = v.elements[0][1];
- bv[1].y = v.elements[1][1];
- bv[1].z = v.elements[2][1];
+ bv[1].x = v.rows[0][1];
+ bv[1].y = v.rows[1][1];
+ bv[1].z = v.rows[2][1];
bv[1].w = 0;
- bv[2].x = v.elements[0][2];
- bv[2].y = v.elements[1][2];
- bv[2].z = v.elements[2][2];
+ bv[2].x = v.rows[0][2];
+ bv[2].y = v.rows[1][2];
+ bv[2].z = v.rows[2][2];
bv[2].w = 0;
} break;
@@ -1815,18 +1838,18 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
Transform2D v = p_value;
- bv[0].x = v.elements[0][0];
- bv[0].y = v.elements[0][1];
+ bv[0].x = v.columns[0][0];
+ bv[0].y = v.columns[0][1];
bv[0].z = 0;
bv[0].w = 0;
- bv[1].x = v.elements[1][0];
- bv[1].y = v.elements[1][1];
+ bv[1].x = v.columns[1][0];
+ bv[1].y = v.columns[1][1];
bv[1].z = 0;
bv[1].w = 0;
- bv[2].x = v.elements[2][0];
- bv[2].y = v.elements[2][1];
+ bv[2].x = v.columns[2][0];
+ bv[2].y = v.columns[2][1];
bv[2].z = 1;
bv[2].w = 0;
@@ -1834,19 +1857,19 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
Transform3D v = p_value;
- bv[0].x = v.basis.elements[0][0];
- bv[0].y = v.basis.elements[1][0];
- bv[0].z = v.basis.elements[2][0];
+ bv[0].x = v.basis.rows[0][0];
+ bv[0].y = v.basis.rows[1][0];
+ bv[0].z = v.basis.rows[2][0];
bv[0].w = 0;
- bv[1].x = v.basis.elements[0][1];
- bv[1].y = v.basis.elements[1][1];
- bv[1].z = v.basis.elements[2][1];
+ bv[1].x = v.basis.rows[0][1];
+ bv[1].y = v.basis.rows[1][1];
+ bv[1].z = v.basis.rows[2][1];
bv[1].w = 0;
- bv[2].x = v.basis.elements[0][2];
- bv[2].y = v.basis.elements[1][2];
- bv[2].z = v.basis.elements[2][2];
+ bv[2].x = v.basis.rows[0][2];
+ bv[2].y = v.basis.rows[1][2];
+ bv[2].z = v.basis.rows[2][2];
bv[2].w = 0;
bv[3].x = v.origin.x;
@@ -1936,10 +1959,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
- const StringName *K = nullptr;
Vector<StringName> names;
- while ((K = global_variables.variables.next(K))) {
- names.push_back(*K);
+ for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
@@ -2091,7 +2113,7 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
}
String path = value;
- RES resource = ResourceLoader::load(path);
+ Ref<Resource> resource = ResourceLoader::load(path);
ERR_CONTINUE(resource.is_null());
value = resource;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index c8cc418c3a..0e899e37c8 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -200,6 +200,11 @@ private:
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+ /* Buffers */
+
+ RID quad_index_buffer;
+ RID quad_index_array;
+
/* GLOBAL VARIABLE API */
GlobalVariables global_variables;
@@ -240,6 +245,10 @@ public:
// void sampler_rd_set_default(float p_mipmap_bias);
+ /* Buffers */
+
+ RID get_quad_index_array() { return quad_index_array; }
+
/* GLOBAL VARIABLE API */
void _update_global_variables();
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 0f74c591c6..9b7b0d2c25 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -609,12 +609,12 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
Transform3D mtx;
- mtx.basis.elements[0].x = dataptr[0];
- mtx.basis.elements[1].x = dataptr[1];
+ mtx.basis.rows[0].x = dataptr[0];
+ mtx.basis.rows[1].x = dataptr[1];
mtx.origin.x = dataptr[3];
- mtx.basis.elements[0].y = dataptr[4];
- mtx.basis.elements[1].y = dataptr[5];
+ mtx.basis.rows[0].y = dataptr[4];
+ mtx.basis.rows[1].y = dataptr[5];
mtx.origin.y = dataptr[7];
AABB baabb = mtx.xform(skbones[j]);
@@ -636,17 +636,17 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
Transform3D mtx;
- mtx.basis.elements[0][0] = dataptr[0];
- mtx.basis.elements[0][1] = dataptr[1];
- mtx.basis.elements[0][2] = dataptr[2];
+ mtx.basis.rows[0][0] = dataptr[0];
+ mtx.basis.rows[0][1] = dataptr[1];
+ mtx.basis.rows[0][2] = dataptr[2];
mtx.origin.x = dataptr[3];
- mtx.basis.elements[1][0] = dataptr[4];
- mtx.basis.elements[1][1] = dataptr[5];
- mtx.basis.elements[1][2] = dataptr[6];
+ mtx.basis.rows[1][0] = dataptr[4];
+ mtx.basis.rows[1][1] = dataptr[5];
+ mtx.basis.rows[1][2] = dataptr[6];
mtx.origin.y = dataptr[7];
- mtx.basis.elements[2][0] = dataptr[8];
- mtx.basis.elements[2][1] = dataptr[9];
- mtx.basis.elements[2][2] = dataptr[10];
+ mtx.basis.rows[2][0] = dataptr[8];
+ mtx.basis.rows[2][1] = dataptr[9];
+ mtx.basis.rows[2][2] = dataptr[10];
mtx.origin.z = dataptr[11];
AABB baabb = mtx.xform(skbones[j]);
@@ -1331,26 +1331,26 @@ void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p
Transform3D t;
if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
- t.basis.elements[0][0] = data[0];
- t.basis.elements[0][1] = data[1];
- t.basis.elements[0][2] = data[2];
+ t.basis.rows[0][0] = data[0];
+ t.basis.rows[0][1] = data[1];
+ t.basis.rows[0][2] = data[2];
t.origin.x = data[3];
- t.basis.elements[1][0] = data[4];
- t.basis.elements[1][1] = data[5];
- t.basis.elements[1][2] = data[6];
+ t.basis.rows[1][0] = data[4];
+ t.basis.rows[1][1] = data[5];
+ t.basis.rows[1][2] = data[6];
t.origin.y = data[7];
- t.basis.elements[2][0] = data[8];
- t.basis.elements[2][1] = data[9];
- t.basis.elements[2][2] = data[10];
+ t.basis.rows[2][0] = data[8];
+ t.basis.rows[2][1] = data[9];
+ t.basis.rows[2][2] = data[10];
t.origin.z = data[11];
} else {
- t.basis.elements[0].x = data[0];
- t.basis.elements[1].x = data[1];
+ t.basis.rows[0].x = data[0];
+ t.basis.rows[1].x = data[1];
t.origin.x = data[3];
- t.basis.elements[0].y = data[4];
- t.basis.elements[1].y = data[5];
+ t.basis.rows[0].y = data[4];
+ t.basis.rows[1].y = data[5];
t.origin.y = data[7];
}
@@ -1377,17 +1377,17 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index,
float *dataptr = w + p_index * multimesh->stride_cache;
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
+ dataptr[0] = p_transform.basis.rows[0][0];
+ dataptr[1] = p_transform.basis.rows[0][1];
+ dataptr[2] = p_transform.basis.rows[0][2];
dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
+ dataptr[4] = p_transform.basis.rows[1][0];
+ dataptr[5] = p_transform.basis.rows[1][1];
+ dataptr[6] = p_transform.basis.rows[1][2];
dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
+ dataptr[8] = p_transform.basis.rows[2][0];
+ dataptr[9] = p_transform.basis.rows[2][1];
+ dataptr[10] = p_transform.basis.rows[2][2];
dataptr[11] = p_transform.origin.z;
}
@@ -1407,14 +1407,14 @@ void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_ind
float *dataptr = w + p_index * multimesh->stride_cache;
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
+ dataptr[0] = p_transform.columns[0][0];
+ dataptr[1] = p_transform.columns[1][0];
dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
+ dataptr[3] = p_transform.columns[2][0];
+ dataptr[4] = p_transform.columns[0][1];
+ dataptr[5] = p_transform.columns[1][1];
dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
+ dataptr[7] = p_transform.columns[2][1];
}
_multimesh_mark_dirty(multimesh, p_index, true);
@@ -1485,17 +1485,17 @@ Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p
const float *dataptr = r + p_index * multimesh->stride_cache;
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
+ t.basis.rows[0][0] = dataptr[0];
+ t.basis.rows[0][1] = dataptr[1];
+ t.basis.rows[0][2] = dataptr[2];
t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
+ t.basis.rows[1][0] = dataptr[4];
+ t.basis.rows[1][1] = dataptr[5];
+ t.basis.rows[1][2] = dataptr[6];
t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
+ t.basis.rows[2][0] = dataptr[8];
+ t.basis.rows[2][1] = dataptr[9];
+ t.basis.rows[2][2] = dataptr[10];
t.origin.z = dataptr[11];
}
@@ -1516,12 +1516,12 @@ Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, in
const float *dataptr = r + p_index * multimesh->stride_cache;
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
+ t.columns[0][0] = dataptr[0];
+ t.columns[1][0] = dataptr[1];
+ t.columns[2][0] = dataptr[3];
+ t.columns[0][1] = dataptr[4];
+ t.columns[1][1] = dataptr[5];
+ t.columns[2][1] = dataptr[7];
}
return t;
@@ -1800,17 +1800,17 @@ void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const
float *dataptr = skeleton->data.ptrw() + p_bone * 12;
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
+ dataptr[0] = p_transform.basis.rows[0][0];
+ dataptr[1] = p_transform.basis.rows[0][1];
+ dataptr[2] = p_transform.basis.rows[0][2];
dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
+ dataptr[4] = p_transform.basis.rows[1][0];
+ dataptr[5] = p_transform.basis.rows[1][1];
+ dataptr[6] = p_transform.basis.rows[1][2];
dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
+ dataptr[8] = p_transform.basis.rows[2][0];
+ dataptr[9] = p_transform.basis.rows[2][1];
+ dataptr[10] = p_transform.basis.rows[2][2];
dataptr[11] = p_transform.origin.z;
_skeleton_make_dirty(skeleton);
@@ -1827,17 +1827,17 @@ Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone)
Transform3D t;
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
+ t.basis.rows[0][0] = dataptr[0];
+ t.basis.rows[0][1] = dataptr[1];
+ t.basis.rows[0][2] = dataptr[2];
t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
+ t.basis.rows[1][0] = dataptr[4];
+ t.basis.rows[1][1] = dataptr[5];
+ t.basis.rows[1][2] = dataptr[6];
t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
+ t.basis.rows[2][0] = dataptr[8];
+ t.basis.rows[2][1] = dataptr[9];
+ t.basis.rows[2][2] = dataptr[10];
t.origin.z = dataptr[11];
return t;
@@ -1852,14 +1852,14 @@ void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, con
float *dataptr = skeleton->data.ptrw() + p_bone * 8;
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
+ dataptr[0] = p_transform.columns[0][0];
+ dataptr[1] = p_transform.columns[1][0];
dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
+ dataptr[3] = p_transform.columns[2][0];
+ dataptr[4] = p_transform.columns[0][1];
+ dataptr[5] = p_transform.columns[1][1];
dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
+ dataptr[7] = p_transform.columns[2][1];
_skeleton_make_dirty(skeleton);
}
@@ -1874,12 +1874,12 @@ Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bo
const float *dataptr = skeleton->data.ptr() + p_bone * 8;
Transform2D t;
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
+ t.columns[0][0] = dataptr[0];
+ t.columns[1][0] = dataptr[1];
+ t.columns[2][0] = dataptr[3];
+ t.columns[0][1] = dataptr[4];
+ t.columns[1][1] = dataptr[5];
+ t.columns[2][1] = dataptr[7];
return t;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index e8da8ad563..7d3f603afd 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -614,7 +614,13 @@ public:
_FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh == nullptr) {
+ return RID();
+ }
if (!multimesh->uniform_set_3d.is_valid()) {
+ if (!multimesh->buffer.is_valid()) {
+ return RID();
+ }
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
@@ -629,7 +635,13 @@ public:
_FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh == nullptr) {
+ return RID();
+ }
if (!multimesh->uniform_set_2d.is_valid()) {
+ if (!multimesh->buffer.is_valid()) {
+ return RID();
+ }
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 402536de88..094120f908 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -800,25 +800,25 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
Transform2D revert = xform.affine_inverse();
frame_params.collider_count = 1;
- frame_params.colliders[0].transform[0] = xform.elements[0][0];
- frame_params.colliders[0].transform[1] = xform.elements[0][1];
+ frame_params.colliders[0].transform[0] = xform.columns[0][0];
+ frame_params.colliders[0].transform[1] = xform.columns[0][1];
frame_params.colliders[0].transform[2] = 0;
- frame_params.colliders[0].transform[3] = xform.elements[2][0];
+ frame_params.colliders[0].transform[3] = xform.columns[2][0];
- frame_params.colliders[0].transform[4] = xform.elements[1][0];
- frame_params.colliders[0].transform[5] = xform.elements[1][1];
+ frame_params.colliders[0].transform[4] = xform.columns[1][0];
+ frame_params.colliders[0].transform[5] = xform.columns[1][1];
frame_params.colliders[0].transform[6] = 0;
- frame_params.colliders[0].transform[7] = xform.elements[2][1];
+ frame_params.colliders[0].transform[7] = xform.columns[2][1];
- frame_params.colliders[0].transform[8] = revert.elements[0][0];
- frame_params.colliders[0].transform[9] = revert.elements[0][1];
+ frame_params.colliders[0].transform[8] = revert.columns[0][0];
+ frame_params.colliders[0].transform[9] = revert.columns[0][1];
frame_params.colliders[0].transform[10] = 0;
- frame_params.colliders[0].transform[11] = revert.elements[2][0];
+ frame_params.colliders[0].transform[11] = revert.columns[2][0];
- frame_params.colliders[0].transform[12] = revert.elements[1][0];
- frame_params.colliders[0].transform[13] = revert.elements[1][1];
+ frame_params.colliders[0].transform[12] = revert.columns[1][0];
+ frame_params.colliders[0].transform[13] = revert.columns[1][1];
frame_params.colliders[0].transform[14] = 0;
- frame_params.colliders[0].transform[15] = revert.elements[2][1];
+ frame_params.colliders[0].transform[15] = revert.columns[2][1];
frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
@@ -1664,10 +1664,6 @@ RS::ShaderNativeSourceCode ParticlesStorage::ParticlesShaderData::get_native_sou
return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version);
}
-ParticlesStorage::ParticlesShaderData::ParticlesShaderData() {
- valid = false;
-}
-
ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
//pipeline variants will clear themselves if shader is gone
if (version.is_valid()) {
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 7764af08f2..c6480794c1 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -341,16 +341,15 @@ private:
/* Particle Shader */
struct ParticlesShaderData : public ShaderData {
- bool valid;
+ bool valid = false;
RID version;
bool uses_collision = false;
- //PipelineCacheRD pipelines[SKY_VERSION_MAX];
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
+ uint32_t ubo_size = 0;
String path;
String code;
@@ -373,7 +372,7 @@ private:
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- ParticlesShaderData();
+ ParticlesShaderData() {}
virtual ~ParticlesShaderData();
};
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 3b52a187f6..7d4808f936 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "texture_storage.h"
-
-#include "../renderer_storage_rd.h"
+#include "../effects/copy_effects.h"
+#include "material_storage.h"
using namespace RendererRD;
@@ -1808,8 +1808,8 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
}
void TextureStorage::update_decal_atlas() {
- EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
- ERR_FAIL_NULL(effects);
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
if (!decal_atlas.dirty) {
return; //nothing to do
@@ -1831,13 +1831,13 @@ void TextureStorage::update_decal_atlas() {
Vector<DecalAtlas::SortItem> itemsv;
itemsv.resize(decal_atlas.textures.size());
int base_size = 8;
- const RID *K = nullptr;
int idx = 0;
- while ((K = decal_atlas.textures.next(K))) {
+
+ for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) {
DecalAtlas::SortItem &si = itemsv.write[idx];
- Texture *src_tex = get_texture(*K);
+ Texture *src_tex = get_texture(E.key);
si.size.width = (src_tex->width / border) + 1;
si.size.height = (src_tex->height / border) + 1;
@@ -1847,7 +1847,7 @@ void TextureStorage::update_decal_atlas() {
base_size = nearest_power_of_2_templated(si.size.width);
}
- si.texture = *K;
+ si.texture = E.key;
idx++;
}
@@ -1983,18 +1983,17 @@ void TextureStorage::update_decal_atlas() {
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
- const RID *K = nullptr;
- while ((K = decal_atlas.textures.next(K))) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
- Texture *src_tex = get_texture(*K);
- effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
+ for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key);
+ Texture *src_tex = get_texture(E.key);
+ copy_effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
}
RD::get_singleton()->draw_list_end();
prev_texture = mm.texture;
} else {
- effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
+ copy_effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
prev_texture = mm.texture;
}
} else {
@@ -2623,8 +2622,8 @@ void TextureStorage::render_target_sdf_process(RID p_render_target) {
}
void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
- EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
- ERR_FAIL_NULL(effects);
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -2642,9 +2641,11 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
}
}
+ // TODO figure out stereo support here
+
//single texture copy for backbuffer
//RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
if (!p_gen_mipmaps) {
return;
@@ -2660,7 +2661,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
region.size.y = MAX(1, region.size.y >> 1);
RID mipmap = rt->backbuffer_mipmaps[i];
- effects->gaussian_blur(prev_texture, mipmap, region, true);
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
prev_texture = mipmap;
}
RD::get_singleton()->draw_command_end_label();
@@ -2670,8 +2671,8 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
- EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
- ERR_FAIL_NULL(effects);
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
@@ -2688,15 +2689,15 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
}
//single texture copy for backbuffer
- effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
}
void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
- EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
- ERR_FAIL_NULL(effects);
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+ ERR_FAIL_NULL(copy_effects);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
@@ -2722,7 +2723,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
region.size.y = MAX(1, region.size.y >> 1);
RID mipmap = rt->backbuffer_mipmaps[i];
- effects->gaussian_blur(prev_texture, mipmap, region, true);
+ copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
prev_texture = mipmap;
}
RD::get_singleton()->draw_command_end_label();
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 528f381139..6e1fa59a7a 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -860,7 +860,7 @@ void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D
#ifdef DEBUG_ENABLED
for (int i = 0; i < 4; i++) {
- const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin;
+ const Vector3 &v = i < 3 ? p_transform.basis.rows[i] : p_transform.origin;
ERR_FAIL_COND(Math::is_inf(v.x));
ERR_FAIL_COND(Math::is_nan(v.x));
ERR_FAIL_COND(Math::is_inf(v.y));
@@ -2065,9 +2065,9 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
Transform3D transform = light_transform; //discard scale and stabilize light
- Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized();
- Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized();
- Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
+ Vector3 x_vec = transform.basis.get_column(Vector3::AXIS_X).normalized();
+ Vector3 y_vec = transform.basis.get_column(Vector3::AXIS_Y).normalized();
+ Vector3 z_vec = transform.basis.get_column(Vector3::AXIS_Z).normalized();
//z_vec points against the camera, like in default opengl
real_t x_min = 0.f, x_max = 0.f;
@@ -2721,7 +2721,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
cull_data.cull->lock.lock();
RSG::particles_storage->particles_request_process(idata.base_rid);
cull_data.cull->lock.unlock();
- RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
+ RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_column(2).normalized(), cull_data.cam_transform.basis.get_column(1).normalized());
//particles visible? request redraw
RenderingServerDefault::redraw_request();
}
@@ -3082,7 +3082,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Transform3D cam_xf = p_camera_data->main_transform;
float zn = p_camera_data->main_projection.get_z_near();
- Plane p(-cam_xf.basis.get_axis(2), cam_xf.origin + cam_xf.basis.get_axis(2) * -zn); //camera near plane
+ Plane p(-cam_xf.basis.get_column(2), cam_xf.origin + cam_xf.basis.get_column(2) * -zn); //camera near plane
// near plane half width and height
Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
@@ -3094,7 +3094,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
//get two points parallel to near plane
Vector3 points[2] = {
ins->transform.origin,
- ins->transform.origin + cam_xf.basis.get_axis(0) * radius
+ ins->transform.origin + cam_xf.basis.get_column(0) * radius
};
if (!p_camera_data->is_orthogonal) {
@@ -3118,11 +3118,11 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
float w = radius * Math::sin(Math::deg2rad(angle));
float d = radius * Math::cos(Math::deg2rad(angle));
- Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d;
+ Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;
Vector3 points[2] = {
base,
- base + cam_xf.basis.get_axis(0) * w
+ base + cam_xf.basis.get_column(0) * w
};
if (!p_camera_data->is_orthogonal) {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 5f71250ced..b5e8cf702f 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -921,7 +921,7 @@ public:
RID_Owner<Instance, true> instance_owner;
- uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecessary on clustered
+ uint32_t geometry_instance_pair_mask = 0; // used in traditional forward, unnecessary on clustered
virtual RID instance_allocate();
virtual void instance_initialize(RID p_rid);
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index fadece317a..a4d281fac4 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -65,7 +65,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
Vector3 y = n0.cross(n1).normalized();
Vector3 x = y.cross(z).normalized();
y = z.cross(x).normalized();
- main_transform.basis.set(x, y, z);
+ main_transform.basis.set_columns(x, y, z);
// 3. create a horizon plane with one of the eyes and the up vector as normal.
Plane horizon(y, p_transforms[0].origin);
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index ab7dbb87a3..7cf4fd0aff 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -199,6 +199,7 @@ public:
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
+ virtual String get_video_adapter_api_version() const = 0;
static RendererStorage *base_singleton;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 8507e20648..3ea67ae115 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -43,7 +43,7 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
if (p_viewport->canvas_map.has(p_canvas->parent)) {
Transform2D c_xform = p_viewport->canvas_map[p_canvas->parent].transform;
if (p_viewport->snap_2d_transforms_to_pixel) {
- c_xform.elements[2] = c_xform.elements[2].floor();
+ c_xform.columns[2] = c_xform.columns[2].floor();
}
xf = xf * c_xform;
scale = p_canvas->parent_scale;
@@ -52,7 +52,7 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
Transform2D c_xform = p_canvas_data->transform;
if (p_viewport->snap_2d_transforms_to_pixel) {
- c_xform.elements[2] = c_xform.elements[2].floor();
+ c_xform.columns[2] = c_xform.columns[2].floor();
}
xf = xf * c_xform;
@@ -195,8 +195,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
}
}
- Color bgcolor = RSG::storage->get_default_clear_color();
-
if (!p_viewport->disable_2d && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
@@ -207,15 +205,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera) && !p_viewport->disable_3d;
- if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
- if (p_viewport->transparent_bg) {
- bgcolor = Color(0, 0, 0, 0);
- }
- if (p_viewport->clear_mode == RS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
- p_viewport->clear_mode = RS::VIEWPORT_CLEAR_NEVER;
- }
- }
-
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
//wants to draw 3D but there is no render buffer, create
p_viewport->render_buffers = RSG::scene->render_buffers_create();
@@ -223,15 +212,20 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_configure_3d_render_buffers(p_viewport);
}
- RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
+ Color bgcolor = p_viewport->transparent_bg ? Color(0, 0, 0, 0) : RSG::storage->get_default_clear_color();
+
+ if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
+ RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
+ if (p_viewport->clear_mode == RS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
+ p_viewport->clear_mode = RS::VIEWPORT_CLEAR_NEVER;
+ }
+ }
if (!scenario_draw_canvas_bg && can_draw_3d) {
_draw_3d(p_viewport);
}
if (!p_viewport->disable_2d) {
- int i = 0;
-
Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
@@ -242,13 +236,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RendererCanvasRender::Light *directional_lights_with_shadow = nullptr;
if (p_viewport->sdf_active) {
- //process SDF
+ // Process SDF.
Rect2 sdf_rect = RSG::texture_storage->render_target_get_sdf_rect(p_viewport->render_target);
RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
- //make list of occluders
+ // Make list of occluders.
for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
@@ -269,14 +263,13 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
- p_viewport->sdf_active = false; // if used, gets set active again
+ p_viewport->sdf_active = false; // If used, gets set active again.
} else {
RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
}
Rect2 shadow_rect;
- int light_count = 0;
int shadow_count = 0;
int directional_light_count = 0;
@@ -286,7 +279,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
- //find lights in canvas
+ // Find lights in canvas.
for (Set<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
RendererCanvasRender::Light *cl = F->get();
@@ -302,12 +295,10 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) {
cl->filter_next_ptr = lights;
lights = cl;
- // cl->texture_cache = nullptr;
Transform2D scale;
scale.scale(cl->rect_cache.size);
- scale.elements[2] = cl->rect_cache.position;
+ scale.columns[2] = cl->rect_cache.position;
cl->light_shader_xform = cl->xform * scale;
- //cl->light_shader_pos = cl->xform_cache[2];
if (cl->use_shadow) {
cl->shadows_next_ptr = lights_with_shadow;
if (lights_with_shadow == nullptr) {
@@ -318,11 +309,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
lights_with_shadow = cl;
cl->radius_cache = cl->rect_cache.size.length();
}
-
- light_count++;
}
-
- //guess this is not needed, but keeping because it may be
}
}
@@ -332,7 +319,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
cl->filter_next_ptr = directional_lights;
directional_lights = cl;
cl->xform_cache = xf * cl->xform;
- cl->xform_cache.elements[2] = Vector2(); //translation is pointless
+ cl->xform_cache.columns[2] = Vector2(); //translation is pointless
if (cl->use_shadow) {
cl->shadows_next_ptr = directional_lights_with_shadow;
directional_lights_with_shadow = cl;
@@ -390,7 +377,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
//update shadows if any
RendererCanvasRender::Light *light = directional_lights_with_shadow;
while (light) {
- Vector2 light_dir = -light->xform_cache.elements[1].normalized(); // Y is light direction
+ Vector2 light_dir = -light->xform_cache.columns[1].normalized(); // Y is light direction
float cull_distance = light->directional_distance;
Vector2 light_dir_sign;
@@ -437,8 +424,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
RENDER_TIMESTAMP("> Render DirectionalLight2D Shadows");
- //make list of occluders
- int occ_cullded = 0;
+ // Make list of occluders.
for (KeyValue<RID, Viewport::CanvasData> &E : p_viewport->canvas_map) {
RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E.value.canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E.value, clip_rect.size);
@@ -456,7 +442,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (F->get()->aabb_cache.intersects_filled_polygon(xf_points, point_count)) {
F->get()->next = occluders;
occluders = F->get();
- occ_cullded++;
}
}
}
@@ -508,7 +493,6 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (RSG::canvas->was_sdf_used()) {
p_viewport->sdf_active = true;
}
- i++;
if (scenario_draw_canvas_bg && E.key.get_layer() >= scenario_canvas_max_layer) {
if (!can_draw_3d) {
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 1902b5f74a..0973e29974 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1254,6 +1254,7 @@ public:
virtual String get_device_vendor_name() const = 0;
virtual String get_device_name() const = 0;
virtual RenderingDevice::DeviceType get_device_type() const = 0;
+ virtual String get_device_api_version() const = 0;
virtual String get_device_pipeline_cache_uuid() const = 0;
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0) = 0;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index e42034dbb9..c4538e0776 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -179,10 +179,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
print_line("GPU PROFILE (total " + rtos(total_time) + "ms): ");
float print_threshold = 0.01;
- for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) {
- double time = E.value() / double(print_frame_profile_frame_count);
+ for (const KeyValue<String, float> &E : print_gpu_profile_task_time) {
+ double time = E.value / double(print_frame_profile_frame_count);
if (time > print_threshold) {
- print_line("\t-" + E.key() + ": " + rtos(time) + "ms");
+ print_line("\t-" + E.key + ": " + rtos(time) + "ms");
}
}
print_gpu_profile_task_time.clear();
@@ -265,6 +265,10 @@ RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() con
return RSG::storage->get_video_adapter_type();
}
+String RenderingServerDefault::get_video_adapter_api_version() const {
+ return RSG::storage->get_video_adapter_api_version();
+}
+
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
RSG::storage->capturing_timestamps = p_enable;
}
@@ -317,11 +321,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
}
bool RenderingServerDefault::is_low_end() const {
- // FIXME: Commented out when rebasing vulkan branch on master,
- // causes a crash, it seems rasterizer is not initialized yet the
- // first time it's called.
- //return RSG::rasterizer->is_low_end();
- return false;
+ return RendererCompositor::is_low_end();
}
void RenderingServerDefault::_thread_exit() {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 8dfb5985f8..9d4059b9df 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -33,7 +33,7 @@
#include "core/math/octree.h"
#include "core/templates/command_queue_mt.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
#include "renderer_viewport.h"
@@ -69,7 +69,7 @@ class RenderingServerDefault : public RenderingServer {
//for printing
bool print_gpu_profile = false;
- OrderedHashMap<String, float> print_gpu_profile_task_time;
+ HashMap<String, float> print_gpu_profile_task_time;
uint64_t print_frame_profile_ticks_from = 0;
uint32_t print_frame_profile_frame_count = 0;
@@ -113,7 +113,9 @@ public:
_changes_changed();
#else
- _FORCE_INLINE_ static void redraw_request() { changes++; }
+ _FORCE_INLINE_ static void redraw_request() {
+ changes++;
+ }
#endif
#define WRITE_ACTION redraw_request();
@@ -939,6 +941,7 @@ public:
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
+ virtual String get_video_adapter_api_version() const override;
virtual void set_frame_profiling_enabled(bool p_enable) override;
virtual Vector<FrameProfileArea> get_frame_profile() override;
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 812d636a0b..5669cb2054 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -48,8 +48,8 @@ static String _mktab(int p_level) {
static String _typestr(SL::DataType p_type) {
String type = ShaderLanguage::get_datatype_name(p_type);
- if (ShaderLanguage::is_sampler_type(p_type)) {
- type = type.replace("sampler", "texture"); //we use textures instead of samplers
+ if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
+ type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
}
return type;
}
@@ -538,7 +538,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
continue; // Instances are indexed directly, don't need index uniforms.
}
if (SL::is_sampler_type(uniform.type)) {
- ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform ";
+ // Texture layouts are different for OpenGL GLSL and Vulkan GLSL
+ if (!RS::get_singleton()->is_low_end()) {
+ ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
+ }
+ ucode += "uniform ";
}
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -681,9 +685,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
vcode += ";\n";
-
- r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode;
- r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode;
+ // GLSL ES 3.0 does not allow layout qualifiers for varyings
+ if (!RS::get_singleton()->is_low_end()) {
+ r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") ";
+ r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") ";
+ }
+ r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode;
+ r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;
index += inc;
}
@@ -1125,8 +1133,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += ", ";
}
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (is_texture_func && i == 1) {
- //need to map from texture to sampler in order to sample
+ if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
+ //need to map from texture to sampler in order to sample when using Vulkan GLSL
StringName texture_uniform;
bool correct_texture_uniform = false;
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index 8f0ee664ac..347ecf2988 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -106,8 +106,8 @@ private:
void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_scope = true);
- const ShaderLanguage::ShaderNode *shader;
- const ShaderLanguage::FunctionNode *function;
+ const ShaderLanguage::ShaderNode *shader = nullptr;
+ const ShaderLanguage::FunctionNode *function = nullptr;
StringName current_func_name;
StringName time_name;
Set<StringName> texture_functions;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 1fd7062d6e..6f70a55948 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -237,92 +237,141 @@ ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type, const String
return tk;
}
+enum ContextFlag : uint32_t {
+ CF_UNSPECIFIED = 0U,
+ CF_BLOCK = 1U, // "void test() { <x> }"
+ CF_FUNC_DECL_PARAM_SPEC = 2U, // "void test(<x> int param) {}"
+ CF_FUNC_DECL_PARAM_TYPE = 4U, // "void test(<x> param) {}"
+ CF_IF_DECL = 8U, // "if(<x>) {}"
+ CF_BOOLEAN = 16U, // "bool t = <x>;"
+ CF_GLOBAL_SPACE = 32U, // "struct", "const", "void" etc.
+ CF_DATATYPE = 64U, // "<x> value;"
+ CF_UNIFORM_TYPE = 128U, // "uniform <x> myUniform;"
+ CF_VARYING_TYPE = 256U, // "varying <x> myVarying;"
+ CF_PRECISION_MODIFIER = 512U, // "<x> vec4 a = vec4(0.0, 1.0, 2.0, 3.0);"
+ CF_INTERPOLATION_QUALIFIER = 1024U, // "varying <x> vec3 myColor;"
+ CF_UNIFORM_KEYWORD = 2048U, // "uniform"
+ CF_CONST_KEYWORD = 4096U, // "const"
+ CF_UNIFORM_QUALIFIER = 8192U, // "<x> uniform float t;"
+};
+
+const uint32_t KCF_DATATYPE = CF_BLOCK | CF_GLOBAL_SPACE | CF_DATATYPE | CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE;
+const uint32_t KCF_SAMPLER_DATATYPE = CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE;
+
const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
- { TK_TRUE, "true" },
- { TK_FALSE, "false" },
- { TK_TYPE_VOID, "void" },
- { TK_TYPE_BOOL, "bool" },
- { TK_TYPE_BVEC2, "bvec2" },
- { TK_TYPE_BVEC3, "bvec3" },
- { TK_TYPE_BVEC4, "bvec4" },
- { TK_TYPE_INT, "int" },
- { TK_TYPE_IVEC2, "ivec2" },
- { TK_TYPE_IVEC3, "ivec3" },
- { TK_TYPE_IVEC4, "ivec4" },
- { TK_TYPE_UINT, "uint" },
- { TK_TYPE_UVEC2, "uvec2" },
- { TK_TYPE_UVEC3, "uvec3" },
- { TK_TYPE_UVEC4, "uvec4" },
- { TK_TYPE_FLOAT, "float" },
- { TK_TYPE_VEC2, "vec2" },
- { TK_TYPE_VEC3, "vec3" },
- { TK_TYPE_VEC4, "vec4" },
- { TK_TYPE_MAT2, "mat2" },
- { TK_TYPE_MAT3, "mat3" },
- { TK_TYPE_MAT4, "mat4" },
- { TK_TYPE_SAMPLER2D, "sampler2D" },
- { TK_TYPE_ISAMPLER2D, "isampler2D" },
- { TK_TYPE_USAMPLER2D, "usampler2D" },
- { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" },
- { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" },
- { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" },
- { TK_TYPE_SAMPLER3D, "sampler3D" },
- { TK_TYPE_ISAMPLER3D, "isampler3D" },
- { TK_TYPE_USAMPLER3D, "usampler3D" },
- { TK_TYPE_SAMPLERCUBE, "samplerCube" },
- { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray" },
- { TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_SMOOTH, "smooth" },
- { TK_CONST, "const" },
- { TK_STRUCT, "struct" },
- { TK_PRECISION_LOW, "lowp" },
- { TK_PRECISION_MID, "mediump" },
- { TK_PRECISION_HIGH, "highp" },
- { TK_CF_IF, "if" },
- { TK_CF_ELSE, "else" },
- { TK_CF_FOR, "for" },
- { TK_CF_WHILE, "while" },
- { TK_CF_DO, "do" },
- { TK_CF_SWITCH, "switch" },
- { TK_CF_CASE, "case" },
- { TK_CF_DEFAULT, "default" },
- { TK_CF_BREAK, "break" },
- { TK_CF_CONTINUE, "continue" },
- { TK_CF_RETURN, "return" },
- { TK_CF_DISCARD, "discard" },
- { TK_UNIFORM, "uniform" },
- { TK_INSTANCE, "instance" },
- { TK_GLOBAL, "global" },
- { TK_VARYING, "varying" },
- { TK_ARG_IN, "in" },
- { TK_ARG_OUT, "out" },
- { TK_ARG_INOUT, "inout" },
- { TK_RENDER_MODE, "render_mode" },
- { TK_HINT_WHITE_TEXTURE, "hint_white" },
- { TK_HINT_BLACK_TEXTURE, "hint_black" },
- { TK_HINT_NORMAL_TEXTURE, "hint_normal" },
- { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal" },
- { TK_HINT_ROUGHNESS_R, "hint_roughness_r" },
- { TK_HINT_ROUGHNESS_G, "hint_roughness_g" },
- { TK_HINT_ROUGHNESS_B, "hint_roughness_b" },
- { TK_HINT_ROUGHNESS_A, "hint_roughness_a" },
- { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" },
- { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy" },
- { TK_HINT_ALBEDO_TEXTURE, "hint_albedo" },
- { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
- { TK_HINT_COLOR, "hint_color" },
- { TK_HINT_RANGE, "hint_range" },
- { TK_HINT_INSTANCE_INDEX, "instance_index" },
- { TK_FILTER_NEAREST, "filter_nearest" },
- { TK_FILTER_LINEAR, "filter_linear" },
- { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
- { TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" },
- { TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC, "filter_nearest_mipmap_anisotropic" },
- { TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC, "filter_linear_mipmap_anisotropic" },
- { TK_REPEAT_ENABLE, "repeat_enable" },
- { TK_REPEAT_DISABLE, "repeat_disable" },
- { TK_SHADER_TYPE, "shader_type" },
- { TK_ERROR, nullptr }
+ { TK_TRUE, "true", CF_BLOCK | CF_IF_DECL | CF_BOOLEAN, {}, {} },
+ { TK_FALSE, "false", CF_BLOCK | CF_IF_DECL | CF_BOOLEAN, {}, {} },
+
+ // data types
+
+ { TK_TYPE_VOID, "void", CF_GLOBAL_SPACE, {}, {} },
+ { TK_TYPE_BOOL, "bool", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_BVEC2, "bvec2", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_BVEC3, "bvec3", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_BVEC4, "bvec4", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_INT, "int", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_IVEC2, "ivec2", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_IVEC3, "ivec3", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_IVEC4, "ivec4", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UINT, "uint", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UVEC2, "uvec2", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UVEC3, "uvec3", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_UVEC4, "uvec4", KCF_DATATYPE, {}, {} },
+ { TK_TYPE_FLOAT, "float", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_VEC2, "vec2", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_VEC3, "vec3", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_VEC4, "vec4", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_MAT2, "mat2", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_MAT3, "mat3", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_MAT4, "mat4", KCF_DATATYPE | CF_VARYING_TYPE, {}, {} },
+ { TK_TYPE_SAMPLER2D, "sampler2D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_ISAMPLER2D, "isampler2D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_USAMPLER2D, "usampler2D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLER3D, "sampler3D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_ISAMPLER3D, "isampler3D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_USAMPLER3D, "usampler3D", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLERCUBE, "samplerCube", KCF_SAMPLER_DATATYPE, {}, {} },
+ { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray", KCF_SAMPLER_DATATYPE, {}, {} },
+
+ // interpolation qualifiers
+
+ { TK_INTERPOLATION_FLAT, "flat", CF_INTERPOLATION_QUALIFIER, {}, {} },
+ { TK_INTERPOLATION_SMOOTH, "smooth", CF_INTERPOLATION_QUALIFIER, {}, {} },
+
+ // precision modifiers
+
+ { TK_PRECISION_LOW, "lowp", CF_BLOCK | CF_PRECISION_MODIFIER, {}, {} },
+ { TK_PRECISION_MID, "mediump", CF_BLOCK | CF_PRECISION_MODIFIER, {}, {} },
+ { TK_PRECISION_HIGH, "highp", CF_BLOCK | CF_PRECISION_MODIFIER, {}, {} },
+
+ // global space keywords
+
+ { TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} },
+ { TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} },
+ { TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} },
+ { TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
+ { TK_SHADER_TYPE, "shader_type", CF_GLOBAL_SPACE, {}, {} },
+ { TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} },
+
+ // uniform qualifiers
+
+ { TK_INSTANCE, "instance", CF_GLOBAL_SPACE | CF_UNIFORM_QUALIFIER, {}, {} },
+ { TK_GLOBAL, "global", CF_GLOBAL_SPACE | CF_UNIFORM_QUALIFIER, {}, {} },
+
+ // block keywords
+
+ { TK_CF_IF, "if", CF_BLOCK, {}, {} },
+ { TK_CF_ELSE, "else", CF_BLOCK, {}, {} },
+ { TK_CF_FOR, "for", CF_BLOCK, {}, {} },
+ { TK_CF_WHILE, "while", CF_BLOCK, {}, {} },
+ { TK_CF_DO, "do", CF_BLOCK, {}, {} },
+ { TK_CF_SWITCH, "switch", CF_BLOCK, {}, {} },
+ { TK_CF_CASE, "case", CF_BLOCK, {}, {} },
+ { TK_CF_DEFAULT, "default", CF_BLOCK, {}, {} },
+ { TK_CF_BREAK, "break", CF_BLOCK, {}, {} },
+ { TK_CF_CONTINUE, "continue", CF_BLOCK, {}, {} },
+ { TK_CF_RETURN, "return", CF_BLOCK, {}, {} },
+ { TK_CF_DISCARD, "discard", CF_BLOCK, { "particles", "sky", "fog" }, { "fragment" } },
+
+ // function specifier keywords
+
+ { TK_ARG_IN, "in", CF_FUNC_DECL_PARAM_SPEC, {}, {} },
+ { TK_ARG_OUT, "out", CF_FUNC_DECL_PARAM_SPEC, {}, {} },
+ { TK_ARG_INOUT, "inout", CF_FUNC_DECL_PARAM_SPEC, {}, {} },
+
+ // hints
+
+ { TK_HINT_RANGE, "hint_range", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_COLOR, "hint_color", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_INSTANCE_INDEX, "instance_index", CF_UNSPECIFIED, {}, {} },
+
+ // sampler hints
+
+ { TK_HINT_ALBEDO_TEXTURE, "hint_albedo", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_WHITE_TEXTURE, "hint_white", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_BLACK_TEXTURE, "hint_black", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_B, "hint_roughness_b", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC, "filter_nearest_mipmap_anisotropic", CF_UNSPECIFIED, {}, {} },
+ { TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC, "filter_linear_mipmap_anisotropic", CF_UNSPECIFIED, {}, {} },
+ { TK_REPEAT_ENABLE, "repeat_enable", CF_UNSPECIFIED, {}, {} },
+ { TK_REPEAT_DISABLE, "repeat_disable", CF_UNSPECIFIED, {}, {} },
+
+ { TK_ERROR, nullptr, CF_UNSPECIFIED, {}, {} }
};
ShaderLanguage::Token ShaderLanguage::_get_token() {
@@ -752,6 +801,19 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
#undef GETCHAR
}
+bool ShaderLanguage::_lookup_next(Token &r_tk) {
+ TkPos pre_pos = _get_tkpos();
+ int line = pre_pos.tk_line;
+ _get_token();
+ Token tk = _get_token();
+ _set_tkpos(pre_pos);
+ if (tk.line == line) {
+ r_tk = tk;
+ return true;
+ }
+ return false;
+}
+
String ShaderLanguage::token_debug(const String &p_code) {
clear();
@@ -852,6 +914,13 @@ bool ShaderLanguage::is_token_precision(TokenType p_type) {
p_type == TK_PRECISION_HIGH);
}
+bool ShaderLanguage::is_token_arg_qual(TokenType p_type) {
+ return (
+ p_type == TK_ARG_IN ||
+ p_type == TK_ARG_OUT ||
+ p_type == TK_ARG_INOUT);
+}
+
ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) {
if (p_type == TK_PRECISION_LOW) {
return PRECISION_LOWP;
@@ -967,6 +1036,7 @@ void ShaderLanguage::clear() {
completion_base_array = false;
#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
used_constants.clear();
used_varyings.clear();
used_uniforms.clear();
@@ -6395,8 +6465,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_
Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one, bool p_can_break, bool p_can_continue) {
while (true) {
TkPos pos = _get_tkpos();
-
Token tk = _get_token();
+#ifdef DEBUG_ENABLED
+ Token next;
+#endif // DEBUG_ENABLED
if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) {
if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) {
@@ -6429,6 +6501,16 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
#endif // DEBUG_ENABLED
}
+#ifdef DEBUG_ENABLED
+ uint32_t precision_flag = CF_PRECISION_MODIFIER;
+
+ keyword_completion_context = CF_DATATYPE;
+ if (!is_token_precision(tk.type)) {
+ if (!is_struct) {
+ keyword_completion_context |= precision_flag;
+ }
+ }
+#endif // DEBUG_ENABLED
bool is_const = false;
@@ -6450,6 +6532,26 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!is_struct) {
is_struct = shader->structs.has(tk.text); // check again.
}
+
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & precision_flag) {
+ keyword_completion_context ^= precision_flag;
+ }
+#endif // DEBUG_ENABLED
+ }
+
+#ifdef DEBUG_ENABLED
+ if (is_const && _lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ }
+ if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= CF_DATATYPE;
+ }
+ }
+#endif // DEBUG_ENABLED
+
+ if (precision != PRECISION_DEFAULT) {
if (!is_token_nonvoid_datatype(tk.type)) {
_set_error(RTR("Expected variable type after precision modifier."));
return ERR_PARSE_ERROR;
@@ -6473,6 +6575,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
+
int array_size = 0;
bool fixed_array_size = false;
bool first = true;
@@ -6576,7 +6682,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
}
-
+#ifdef DEBUG_ENABLED
+ if (var.type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BOOLEAN;
+ }
+#endif // DEBUG_ENABLED
if (var.array_size > 0 || unknown_size) {
bool full_def = false;
@@ -6823,7 +6933,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
} while (tk.type == TK_COMMA); //another variable
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
p_block->statements.push_back(static_cast<Node *>(vdnode));
} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
//a sub block, just because..
@@ -6843,10 +6955,16 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_IF;
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_IF_DECL;
+#endif // DEBUG_ENABLED
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n) {
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
if (n->get_datatype() != TYPE_BOOL) {
_set_error(RTR("Expected a boolean expression."));
@@ -7184,10 +7302,17 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
init_block->parent_block = p_block;
init_block->single_statement = true;
cf->blocks.push_back(init_block);
+
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_DATATYPE;
+#endif // DEBUG_ENABLED
Error err = _parse_block(init_block, p_function_info, true, false, false);
if (err != OK) {
return err;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
BlockNode *condition_block = alloc_node<BlockNode>();
condition_block->block_type = BlockNode::BLOCK_TYPE_FOR_CONDITION;
@@ -7216,6 +7341,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
cf->blocks.push_back(block);
p_block->statements.push_back(cf);
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
err = _parse_block(block, p_function_info, true, true, true);
if (err != OK) {
return err;
@@ -7260,6 +7388,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else {
_set_tkpos(pos); //rollback, wants expression
+#ifdef DEBUG_ENABLED
+ if (b->parent_function->return_type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BOOLEAN;
+ }
+#endif // DEBUG_ENABLED
+
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
if (!expr) {
return ERR_PARSE_ERROR;
@@ -7276,6 +7410,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ if (b->parent_function->return_type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BLOCK;
+ }
+#endif // DEBUG_ENABLED
+
flow->expressions.push_back(expr);
}
@@ -7502,15 +7642,17 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
TkPos prev_pos;
+ Token next;
if (tk.type != TK_SHADER_TYPE) {
_set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
- StringName shader_type_identifier;
_get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
-
if (shader_type_identifier == StringName()) {
_set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
@@ -7528,6 +7670,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
tk = _get_token();
int texture_uniforms = 0;
@@ -7621,7 +7766,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
case TK_STRUCT: {
ShaderNode::Struct st;
DataType type;
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
@@ -7644,7 +7791,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int member_count = 0;
Set<String> member_names;
+
while (true) { // variables list
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_DATATYPE | CF_PRECISION_MODIFIER;
+#endif // DEBUG_ENABLED
+
tk = _get_token();
if (tk.type == TK_CURLY_BRACKET_CLOSE) {
break;
@@ -7661,6 +7813,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+#endif // DEBUG_ENABLED
}
if (shader->structs.has(tk.text)) {
@@ -7687,6 +7842,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type)));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
bool first = true;
bool fixed_array_size = false;
@@ -7758,12 +7916,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_set_error(RTR("Empty structs are not allowed."));
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
_set_expected_error(";");
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
+
shader->structs[st.name] = st;
shader->vstructs.push_back(st); // struct's order is important!
#ifdef DEBUG_ENABLED
@@ -7773,6 +7938,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
#endif // DEBUG_ENABLED
} break;
case TK_GLOBAL: {
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
+ }
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type != TK_UNIFORM) {
_set_expected_after_error("uniform", "global");
@@ -7782,6 +7955,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
};
[[fallthrough]];
case TK_INSTANCE: {
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNIFORM_KEYWORD;
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context ^= CF_UNIFORM_KEYWORD;
+ }
+ }
+#endif // DEBUG_ENABLED
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
tk = _get_token();
if (tk.type != TK_UNIFORM) {
@@ -7795,14 +7976,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
case TK_UNIFORM:
case TK_VARYING: {
bool uniform = tk.type == TK_UNIFORM;
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
if (!uniform) {
if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") {
_set_error(vformat(RTR("Varyings cannot be used in '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
}
-
DataPrecision precision = PRECISION_DEFAULT;
DataInterpolation interpolation = INTERPOLATION_SMOOTH;
DataType type;
@@ -7810,18 +7992,81 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int array_size = 0;
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ bool temp_error = false;
+ uint32_t datatype_flag;
+
+ if (!uniform) {
+ datatype_flag = CF_VARYING_TYPE;
+ keyword_completion_context = CF_INTERPOLATION_QUALIFIER | CF_PRECISION_MODIFIER | datatype_flag;
+
+ if (_lookup_next(next)) {
+ if (is_token_interpolation(next.type)) {
+ keyword_completion_context ^= (CF_INTERPOLATION_QUALIFIER | datatype_flag);
+ } else if (is_token_precision(next.type)) {
+ keyword_completion_context ^= (CF_PRECISION_MODIFIER | datatype_flag);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= datatype_flag;
+ }
+ }
+ } else {
+ datatype_flag = CF_UNIFORM_TYPE;
+ keyword_completion_context = CF_PRECISION_MODIFIER | datatype_flag;
+
+ if (_lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context ^= (CF_PRECISION_MODIFIER | datatype_flag);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= datatype_flag;
+ }
+ }
+ }
+#endif // DEBUG_ENABLED
+
if (is_token_interpolation(tk.type)) {
if (uniform) {
_set_error(RTR("Interpolation qualifiers are not supported for uniforms."));
+#ifdef DEBUG_ENABLED
+ temp_error = true;
+#else
return ERR_PARSE_ERROR;
+#endif // DEBUG_ENABLED
}
interpolation = get_token_interpolation(tk.type);
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_INTERPOLATION_QUALIFIER) {
+ keyword_completion_context ^= CF_INTERPOLATION_QUALIFIER;
+ }
+ if (_lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context ^= datatype_flag;
+ }
+ }
+ if (temp_error) {
+ return ERR_PARSE_ERROR;
+ }
+#endif // DEBUG_ENABLED
}
if (is_token_precision(tk.type)) {
precision = get_token_precision(tk.type);
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_INTERPOLATION_QUALIFIER) {
+ keyword_completion_context ^= CF_INTERPOLATION_QUALIFIER;
+ }
+ if (keyword_completion_context & CF_PRECISION_MODIFIER) {
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+ }
+ if (_lookup_next(next)) {
+ if (is_token_datatype(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ }
+ }
+#endif // DEBUG_ENABLED
}
if (shader->structs.has(tk.text)) {
@@ -7855,6 +8100,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
@@ -8226,6 +8474,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
completion_type = COMPLETION_NONE;
} else { // varying
ShaderNode::Varying varying;
@@ -8291,6 +8542,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
is_struct = true;
struct_name = tk.text;
} else {
+#ifdef DEBUG_ENABLED
+ if (_lookup_next(next)) {
+ if (next.type == TK_UNIFORM) {
+ keyword_completion_context = CF_UNIFORM_QUALIFIER;
+ }
+ }
+#endif // DEBUG_ENABLED
if (!is_token_datatype(tk.type)) {
_set_error(RTR("Expected constant, function, uniform or varying."));
return ERR_PARSE_ERROR;
@@ -8319,6 +8577,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
+
bool unknown_size = false;
bool fixed_array_size = false;
@@ -8555,11 +8817,22 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
} else {
+#ifdef DEBUG_ENABLED
+ if (constant.type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_BOOLEAN;
+ }
+#endif // DEBUG_ENABLED
+
//variable created with assignment! must parse an expression
Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
+#ifdef DEBUG_ENABLED
+ if (constant.type == DataType::TYPE_BOOL) {
+ keyword_completion_context = CF_GLOBAL_SPACE;
+ }
+#endif // DEBUG_ENABLED
if (expr->type == Node::TYPE_OPERATOR && static_cast<OperatorNode *>(expr)->op == OP_CALL) {
OperatorNode *op = static_cast<OperatorNode *>(expr);
for (int i = 1; i < op->arguments.size(); i++) {
@@ -8691,31 +8964,88 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_PARENTHESIS_CLOSE) {
break;
}
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_CONST_KEYWORD | CF_FUNC_DECL_PARAM_SPEC | CF_PRECISION_MODIFIER | CF_FUNC_DECL_PARAM_TYPE; // eg. const in mediump float
+
+ if (_lookup_next(next)) {
+ if (next.type == TK_CONST) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ } else if (is_token_arg_qual(next.type)) {
+ keyword_completion_context = CF_CONST_KEYWORD;
+ } else if (is_token_precision(next.type)) {
+ keyword_completion_context = (CF_CONST_KEYWORD | CF_FUNC_DECL_PARAM_SPEC | CF_FUNC_DECL_PARAM_TYPE);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context = (CF_CONST_KEYWORD | CF_FUNC_DECL_PARAM_SPEC | CF_PRECISION_MODIFIER);
+ }
+ }
+#endif // DEBUG_ENABLED
bool param_is_const = false;
if (tk.type == TK_CONST) {
param_is_const = true;
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_CONST_KEYWORD) {
+ keyword_completion_context ^= CF_CONST_KEYWORD;
+ }
+
+ if (_lookup_next(next)) {
+ if (is_token_arg_qual(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ } else if (is_token_precision(next.type)) {
+ keyword_completion_context = (CF_FUNC_DECL_PARAM_SPEC | CF_FUNC_DECL_PARAM_TYPE);
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context = (CF_FUNC_DECL_PARAM_SPEC | CF_PRECISION_MODIFIER);
+ }
+ }
+#endif // DEBUG_ENABLED
}
ArgumentQualifier param_qualifier = ARGUMENT_QUALIFIER_IN;
- if (tk.type == TK_ARG_IN) {
- param_qualifier = ARGUMENT_QUALIFIER_IN;
- tk = _get_token();
- } else if (tk.type == TK_ARG_OUT) {
- if (param_is_const) {
- _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const"));
- return ERR_PARSE_ERROR;
+ if (is_token_arg_qual(tk.type)) {
+ bool error = false;
+ switch (tk.type) {
+ case TK_ARG_IN: {
+ param_qualifier = ARGUMENT_QUALIFIER_IN;
+ } break;
+ case TK_ARG_OUT: {
+ if (param_is_const) {
+ _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const"));
+ error = true;
+ }
+ param_qualifier = ARGUMENT_QUALIFIER_OUT;
+ } break;
+ case TK_ARG_INOUT: {
+ if (param_is_const) {
+ _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const"));
+ error = true;
+ }
+ param_qualifier = ARGUMENT_QUALIFIER_INOUT;
+ } break;
+ default:
+ error = true;
+ break;
}
- param_qualifier = ARGUMENT_QUALIFIER_OUT;
tk = _get_token();
- } else if (tk.type == TK_ARG_INOUT) {
- if (param_is_const) {
- _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const"));
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_CONST_KEYWORD) {
+ keyword_completion_context ^= CF_CONST_KEYWORD;
+ }
+ if (keyword_completion_context & CF_FUNC_DECL_PARAM_SPEC) {
+ keyword_completion_context ^= CF_FUNC_DECL_PARAM_SPEC;
+ }
+
+ if (_lookup_next(next)) {
+ if (is_token_precision(next.type)) {
+ keyword_completion_context = CF_FUNC_DECL_PARAM_TYPE;
+ } else if (is_token_datatype(next.type)) {
+ keyword_completion_context = CF_PRECISION_MODIFIER;
+ }
+ }
+#endif // DEBUG_ENABLED
+ if (error) {
return ERR_PARSE_ERROR;
}
- param_qualifier = ARGUMENT_QUALIFIER_INOUT;
- tk = _get_token();
}
DataType param_type;
@@ -8727,6 +9057,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (is_token_precision(tk.type)) {
param_precision = get_token_precision(tk.type);
tk = _get_token();
+#ifdef DEBUG_ENABLED
+ if (keyword_completion_context & CF_CONST_KEYWORD) {
+ keyword_completion_context ^= CF_CONST_KEYWORD;
+ }
+ if (keyword_completion_context & CF_FUNC_DECL_PARAM_SPEC) {
+ keyword_completion_context ^= CF_FUNC_DECL_PARAM_SPEC;
+ }
+ if (keyword_completion_context & CF_PRECISION_MODIFIER) {
+ keyword_completion_context ^= CF_PRECISION_MODIFIER;
+ }
+
+ if (_lookup_next(next)) {
+ if (is_token_datatype(next.type)) {
+ keyword_completion_context = CF_UNSPECIFIED;
+ }
+ }
+#endif // DEBUG_ENABLED
}
is_struct = false;
@@ -8769,7 +9116,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (param_precision != PRECISION_DEFAULT && _validate_precision(param_type, param_precision) != OK) {
return ERR_PARSE_ERROR;
}
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -8853,11 +9202,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
current_function = name;
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_BLOCK;
+#endif // DEBUG_ENABLED
Error err = _parse_block(func_node->body, builtins);
if (err) {
return err;
}
-
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_GLOBAL_SPACE;
+#endif // DEBUG_ENABLED
if (func_node->return_type != DataType::TYPE_VOID) {
BlockNode *block = func_node->body;
if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
@@ -9092,6 +9446,28 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
shader = alloc_node<ShaderNode>();
_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
+#ifdef DEBUG_ENABLED
+ // Adds context keywords.
+ if (keyword_completion_context != CF_UNSPECIFIED) {
+ int sz = sizeof(keyword_list) / sizeof(KeyWord);
+ for (int i = 0; i < sz; i++) {
+ if (keyword_list[i].flags == CF_UNSPECIFIED) {
+ break; // Ignore hint keywords (parsed below).
+ }
+ if (keyword_list[i].flags & keyword_completion_context) {
+ if (keyword_list[i].excluded_shader_types.has(shader_type_identifier)) {
+ continue;
+ }
+ if (!keyword_list[i].functions.is_empty() && !keyword_list[i].functions.has(current_function)) {
+ continue;
+ }
+ ScriptLanguage::CodeCompletionOption option(keyword_list[i].text, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ }
+#endif // DEBUG_ENABLED
+
switch (completion_type) {
case COMPLETION_NONE: {
//do nothing
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index de6d912a4f..80230ed54c 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -756,6 +756,7 @@ public:
static bool is_token_interpolation(TokenType p_type);
static DataInterpolation get_token_interpolation(TokenType p_type);
static bool is_token_precision(TokenType p_type);
+ static bool is_token_arg_qual(TokenType p_type);
static DataPrecision get_token_precision(TokenType p_type);
static String get_precision_name(DataPrecision p_type);
static String get_datatype_name(DataType p_type);
@@ -870,15 +871,18 @@ private:
struct KeyWord {
TokenType token;
const char *text;
+ uint32_t flags;
+ const Vector<String> excluded_shader_types;
+ const Vector<String> functions;
};
static const KeyWord keyword_list[];
- GlobalVariableGetTypeFunc global_var_get_type_func;
+ GlobalVariableGetTypeFunc global_var_get_type_func = nullptr;
- bool error_set;
+ bool error_set = false;
String error_str;
- int error_line;
+ int error_line = 0;
#ifdef DEBUG_ENABLED
struct Usage {
@@ -902,7 +906,7 @@ private:
List<ShaderWarning> warnings;
bool check_warnings = false;
- uint32_t warning_flags;
+ uint32_t warning_flags = 0;
void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
warnings.push_back(ShaderWarning(p_code, tk_line, p_subject, p_extra_args));
@@ -917,9 +921,10 @@ private:
#endif // DEBUG_ENABLED
String code;
- int char_idx;
- int tk_line;
+ int char_idx = 0;
+ int tk_line = 0;
+ StringName shader_type_identifier;
StringName current_function;
bool last_const = false;
StringName last_name;
@@ -972,6 +977,7 @@ private:
Token _make_token(TokenType p_type, const StringName &p_text = StringName());
Token _get_token();
+ bool _lookup_next(Token &r_tk);
ShaderNode *shader = nullptr;
@@ -1020,14 +1026,18 @@ private:
};
CompletionType completion_type;
- int completion_line;
+ int completion_line = 0;
BlockNode *completion_block = nullptr;
DataType completion_base;
- bool completion_base_array;
+ bool completion_base_array = false;
SubClassTag completion_class;
StringName completion_function;
StringName completion_struct;
- int completion_argument;
+ int completion_argument = 0;
+
+#ifdef DEBUG_ENABLED
+ uint32_t keyword_completion_context;
+#endif // DEBUG_ENABLED
const Map<StringName, FunctionInfo> *stages = nullptr;
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 385083b670..6ba05a3b43 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -31,7 +31,7 @@
#ifndef SHADERTYPES_H
#define SHADERTYPES_H
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/map.h"
#include "servers/rendering_server.h"
#include "shader_language.h"