summaryrefslogtreecommitdiffstats
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_stream.cpp13
-rw-r--r--servers/audio_server.cpp6
-rw-r--r--servers/debugger/servers_debugger.cpp6
-rw-r--r--servers/display_server.cpp6
-rw-r--r--servers/display_server.h18
-rw-r--r--servers/display_server_headless.h44
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp2
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp11
-rw-r--r--servers/physics_server_2d_wrap_mt.cpp44
-rw-r--r--servers/physics_server_2d_wrap_mt.h9
-rw-r--r--servers/physics_server_3d_wrap_mt.cpp44
-rw-r--r--servers/physics_server_3d_wrap_mt.h10
-rw-r--r--servers/register_server_types.cpp1
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h2
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp288
-rw-r--r--servers/rendering/renderer_canvas_cull.h6
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp6
-rw-r--r--servers/rendering/renderer_rd/effects/debug_effects.cpp4
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp22
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h7
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp44
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h5
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp59
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h5
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl46
-rw-r--r--servers/rendering/renderer_rd/shaders/samplers_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_data_rd.h3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp32
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h3
-rw-r--r--servers/rendering/renderer_scene_cull.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp15
-rw-r--r--servers/rendering/renderer_viewport.h2
-rw-r--r--servers/rendering/rendering_context_driver.h5
-rw-r--r--servers/rendering/rendering_device.cpp184
-rw-r--r--servers/rendering/rendering_device.h9
-rw-r--r--servers/rendering/rendering_device_commons.h2
-rw-r--r--servers/rendering/rendering_device_driver.h2
-rw-r--r--servers/rendering/rendering_device_graph.cpp83
-rw-r--r--servers/rendering/rendering_device_graph.h22
-rw-r--r--servers/rendering/rendering_light_culler.cpp16
-rw-r--r--servers/rendering/rendering_light_culler.h4
-rw-r--r--servers/rendering/rendering_server_default.cpp126
-rw-r--r--servers/rendering/rendering_server_default.h34
-rw-r--r--servers/rendering/shader_compiler.cpp14
-rw-r--r--servers/rendering/shader_language.cpp74
-rw-r--r--servers/rendering/shader_language.h4
-rw-r--r--servers/rendering/shader_types.cpp4
-rw-r--r--servers/rendering/storage/texture_storage.h2
-rw-r--r--servers/rendering/storage/variant_converters.h3
-rw-r--r--servers/rendering_server.compat.inc15
-rw-r--r--servers/rendering_server.cpp15
-rw-r--r--servers/rendering_server.h19
-rw-r--r--servers/text/text_server_extension.cpp9
-rw-r--r--servers/text/text_server_extension.h2
-rw-r--r--servers/text_server.cpp5
-rw-r--r--servers/text_server.h1
-rw-r--r--servers/xr/xr_interface.cpp83
-rw-r--r--servers/xr/xr_interface.h13
-rw-r--r--servers/xr/xr_vrs.cpp151
-rw-r--r--servers/xr/xr_vrs.h67
65 files changed, 1242 insertions, 511 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index b5333d91c6..dc54e01ec8 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -442,7 +442,7 @@ void AudioStreamRandomizer::add_stream(int p_index, Ref<AudioStream> p_stream, f
ERR_FAIL_COND(p_index > audio_stream_pool.size());
PoolEntry entry{ p_stream, p_weight };
audio_stream_pool.insert(p_index, entry);
- emit_signal(SNAME("changed"));
+ emit_signal(CoreStringName(changed));
notify_property_list_changed();
}
@@ -459,21 +459,21 @@ void AudioStreamRandomizer::move_stream(int p_index_from, int p_index_to) {
p_index_from++;
}
audio_stream_pool.remove_at(p_index_from);
- emit_signal(SNAME("changed"));
+ emit_signal(CoreStringName(changed));
notify_property_list_changed();
}
void AudioStreamRandomizer::remove_stream(int p_index) {
ERR_FAIL_INDEX(p_index, audio_stream_pool.size());
audio_stream_pool.remove_at(p_index);
- emit_signal(SNAME("changed"));
+ emit_signal(CoreStringName(changed));
notify_property_list_changed();
}
void AudioStreamRandomizer::set_stream(int p_index, Ref<AudioStream> p_stream) {
ERR_FAIL_INDEX(p_index, audio_stream_pool.size());
audio_stream_pool.write[p_index].stream = p_stream;
- emit_signal(SNAME("changed"));
+ emit_signal(CoreStringName(changed));
}
Ref<AudioStream> AudioStreamRandomizer::get_stream(int p_index) const {
@@ -484,7 +484,7 @@ Ref<AudioStream> AudioStreamRandomizer::get_stream(int p_index) const {
void AudioStreamRandomizer::set_stream_probability_weight(int p_index, float p_weight) {
ERR_FAIL_INDEX(p_index, audio_stream_pool.size());
audio_stream_pool.write[p_index].weight = p_weight;
- emit_signal(SNAME("changed"));
+ emit_signal(CoreStringName(changed));
}
float AudioStreamRandomizer::get_stream_probability_weight(int p_index) const {
@@ -618,7 +618,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
if (entry.stream.is_null()) {
continue;
}
- if (local_pool.find(entry.stream) != -1) {
+ if (local_pool.has(entry.stream)) {
WARN_PRINT("Duplicate stream in sequential playback pool");
continue;
}
@@ -711,6 +711,7 @@ void AudioStreamRandomizer::_bind_methods() {
PoolEntry defaults;
base_property_helper.set_prefix("stream_");
+ base_property_helper.set_array_length_getter(&AudioStreamRandomizer::get_streams_count);
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), defaults.stream, &AudioStreamRandomizer::set_stream, &AudioStreamRandomizer::get_stream);
base_property_helper.register_property(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), defaults.weight, &AudioStreamRandomizer::set_stream_probability_weight, &AudioStreamRandomizer::get_stream_probability_weight);
}
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 820e0bbeb6..d37836ed96 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -762,7 +762,7 @@ void AudioServer::set_bus_count(int p_count) {
buses[i]->bypass = false;
buses[i]->volume_db = 0;
if (i > 0) {
- buses[i]->send = SceneStringNames::get_singleton()->Master;
+ buses[i]->send = SceneStringName(Master);
}
bus_map[attempt] = buses[i];
@@ -1600,7 +1600,7 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
for (int i = 0; i < p_bus_layout->buses.size(); i++) {
Bus *bus = memnew(Bus);
if (i == 0) {
- bus->name = SceneStringNames::get_singleton()->Master;
+ bus->name = SceneStringName(Master);
} else {
bus->name = p_bus_layout->buses[i].name;
bus->send = p_bus_layout->buses[i].send;
@@ -1923,5 +1923,5 @@ void AudioBusLayout::_get_property_list(List<PropertyInfo> *p_list) const {
AudioBusLayout::AudioBusLayout() {
buses.resize(1);
- buses.write[0].name = SceneStringNames::get_singleton()->Master;
+ buses.write[0].name = SceneStringName(Master);
}
diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp
index 06be73acc5..eded0ecfe5 100644
--- a/servers/debugger/servers_debugger.cpp
+++ b/servers/debugger/servers_debugger.cpp
@@ -97,12 +97,10 @@ Array ServersDebugger::ServersProfilerFrame::serialize() {
arr.push_back(script_time);
arr.push_back(servers.size());
- for (int i = 0; i < servers.size(); i++) {
- ServerInfo &s = servers[i];
+ for (const ServerInfo &s : servers) {
arr.push_back(s.name);
arr.push_back(s.functions.size() * 2);
- for (int j = 0; j < s.functions.size(); j++) {
- ServerFunctionInfo &f = s.functions[j];
+ for (const ServerFunctionInfo &f : s.functions) {
arr.push_back(f.name);
arr.push_back(f.time);
}
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index fcbedbc1f8..2150a3038e 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -996,6 +996,8 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("tablet_get_current_driver"), &DisplayServer::tablet_get_current_driver);
ClassDB::bind_method(D_METHOD("tablet_set_current_driver", "name"), &DisplayServer::tablet_set_current_driver);
+ ClassDB::bind_method(D_METHOD("is_window_transparency_available"), &DisplayServer::is_window_transparency_available);
+
#ifndef DISABLE_DEPRECATED
BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU);
#endif
@@ -1183,9 +1185,9 @@ Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index)
return server_create_functions[p_index].get_rendering_drivers_function();
}
-DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
+DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error);
+ return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, r_error);
}
void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) {
diff --git a/servers/display_server.h b/servers/display_server.h
index 30f6ee5ccf..5224d59c04 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -82,7 +82,13 @@ public:
OPENGL_CONTEXT,
};
- typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, int p_screen, Error &r_error);
+ enum Context {
+ CONTEXT_EDITOR,
+ CONTEXT_PROJECTMAN,
+ CONTEXT_ENGINE,
+ };
+
+ typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, int p_screen, Context, Error &r_error);
typedef Vector<String> (*GetRenderingDriversFunction)();
private:
@@ -572,19 +578,15 @@ public:
virtual Rect2 status_indicator_get_rect(IndicatorID p_id) const;
virtual void delete_status_indicator(IndicatorID p_id);
- enum Context {
- CONTEXT_EDITOR,
- CONTEXT_PROJECTMAN,
- CONTEXT_ENGINE,
- };
-
virtual void set_context(Context p_context);
+ virtual bool is_window_transparency_available() const { return false; }
+
static void register_create_function(const char *p_name, CreateFunction p_function, GetRenderingDriversFunction p_get_drivers);
static int get_create_function_count();
static const char *get_create_function_name(int p_index);
static Vector<String> get_create_function_rendering_drivers(int p_index);
- static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
+ static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error);
DisplayServer();
~DisplayServer();
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 7a44645b1e..51755ddfbd 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -45,7 +45,7 @@ private:
return drivers;
}
- static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
+ static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
r_error = OK;
RasterizerDummy::make_current();
return memnew(DisplayServerHeadless());
@@ -57,6 +57,9 @@ public:
bool has_feature(Feature p_feature) const override { return false; }
String get_name() const override { return "headless"; }
+ // Stub implementations to prevent warnings from being printed for methods
+ // that don't affect the project's behavior in headless mode.
+
int get_screen_count() const override { return 0; }
int get_primary_screen() const override { return 0; };
Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); }
@@ -66,6 +69,8 @@ public:
float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 1; }
float screen_get_max_scale() const override { return 1; }
float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return SCREEN_REFRESH_RATE_FALLBACK; }
+ void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override {}
+ void screen_set_keep_on(bool p_enable) override {}
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
@@ -130,10 +135,47 @@ public:
void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override {}
void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override {}
+ int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override { return 0; }
+
void process_events() override {}
+ void set_native_icon(const String &p_filename) override {}
void set_icon(const Ref<Image> &p_icon) override {}
+ void help_set_search_callbacks(const Callable &p_search_callback = Callable(), const Callable &p_action_callback = Callable()) override {}
+
+ bool tts_is_speaking() const override { return false; }
+ bool tts_is_paused() const override { return false; }
+ TypedArray<Dictionary> tts_get_voices() const override { return TypedArray<Dictionary>(); }
+ void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.0f, float p_rate = 1.0f, int p_utterance_id = 0, bool p_interrupt = false) override {}
+ void tts_pause() override {}
+ void tts_resume() override {}
+ void tts_stop() override {}
+
+ void mouse_set_mode(MouseMode p_mode) override {}
+ void clipboard_set(const String &p_text) override {}
+ void clipboard_set_primary(const String &p_text) override {}
+
+ void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override {}
+ void virtual_keyboard_hide() override {}
+
+ void cursor_set_shape(CursorShape p_shape) override {}
+ void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override {}
+
+ Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+ Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+ Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+ Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
+
+ void release_rendering_thread() override {}
+ void swap_buffers() override {}
+
+ IndicatorID create_status_indicator(const Ref<Texture2D> &p_icon, const String &p_tooltip, const Callable &p_callback) override { return INVALID_INDICATOR_ID; }
+ void status_indicator_set_icon(IndicatorID p_id, const Ref<Texture2D> &p_icon) override {}
+ void status_indicator_set_tooltip(IndicatorID p_id, const String &p_tooltip) override {}
+ void status_indicator_set_callback(IndicatorID p_id, const Callable &p_callback) override {}
+ void delete_status_indicator(IndicatorID p_id) override {}
+
DisplayServerHeadless() {
native_menu = memnew(NativeMenu);
}
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 6eb983d5e0..70b6bcf19e 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -1133,7 +1133,7 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
max_support = s;
}
}
- if (extreme_vertices.find(best_vertex) == -1)
+ if (!extreme_vertices.has(best_vertex))
extreme_vertices.push_back(best_vertex);
}
}
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index e621977326..7284076a47 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -140,7 +140,12 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) {
Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0);
ERR_FAIL_COND(arrays.is_empty());
- bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]);
+ const Vector<int> &indices = arrays[RenderingServer::ARRAY_INDEX];
+ const Vector<Vector3> &vertices = arrays[RenderingServer::ARRAY_VERTEX];
+ ERR_FAIL_COND_MSG(indices.is_empty(), "Soft body's mesh needs to have indices");
+ ERR_FAIL_COND_MSG(vertices.is_empty(), "Soft body's mesh needs to have vertices");
+
+ bool success = create_from_trimesh(indices, vertices);
if (!success) {
destroy();
}
@@ -626,11 +631,11 @@ void GodotSoftBody3D::generate_bending_constraints(int p_distance) {
for (Link &link : links) {
const int ia = (int)(link.n[0] - &nodes[0]);
const int ib = (int)(link.n[1] - &nodes[0]);
- if (node_links[ia].find(ib) == -1) {
+ if (!node_links[ia].has(ib)) {
node_links[ia].push_back(ib);
}
- if (node_links[ib].find(ia) == -1) {
+ if (!node_links[ib].has(ia)) {
node_links[ib].push_back(ia);
}
}
diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp
index 4548bb91cb..8e9f7aa8fc 100644
--- a/servers/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_server_2d_wrap_mt.cpp
@@ -32,45 +32,37 @@
#include "core/os/os.h"
-void PhysicsServer2DWrapMT::thread_exit() {
- exit = true;
+void PhysicsServer2DWrapMT::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
+ server_thread = Thread::get_caller_id();
+ server_task_id = p_pump_task_id;
}
-void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
- physics_server_2d->step(p_delta);
- step_sem.post();
+void PhysicsServer2DWrapMT::_thread_exit() {
+ exit = true;
}
-void PhysicsServer2DWrapMT::thread_loop() {
- server_thread = Thread::get_caller_id();
-
- physics_server_2d->init();
-
- command_queue.set_pump_task_id(server_task_id);
+void PhysicsServer2DWrapMT::_thread_loop() {
while (!exit) {
WorkerThreadPool::get_singleton()->yield();
command_queue.flush_all();
}
-
- command_queue.flush_all();
-
- physics_server_2d->finish();
}
/* EVENT QUEUING */
void PhysicsServer2DWrapMT::step(real_t p_step) {
if (create_thread) {
- command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step);
+ command_queue.push(physics_server_2d, &PhysicsServer2D::step, p_step);
} else {
- command_queue.flush_all(); // Flush all pending from other threads.
physics_server_2d->step(p_step);
}
}
void PhysicsServer2DWrapMT::sync() {
if (create_thread) {
- step_sem.wait();
+ command_queue.sync();
+ } else {
+ command_queue.flush_all(); // Flush all pending from other threads.
}
physics_server_2d->sync();
}
@@ -85,21 +77,26 @@ void PhysicsServer2DWrapMT::end_sync() {
void PhysicsServer2DWrapMT::init() {
if (create_thread) {
- exit = false;
- server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::thread_loop), true);
- step_sem.post();
+ WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::_thread_loop), true);
+ command_queue.set_pump_task_id(tid);
+ command_queue.push(this, &PhysicsServer2DWrapMT::_assign_mt_ids, tid);
+ command_queue.push_and_sync(physics_server_2d, &PhysicsServer2D::init);
+ DEV_ASSERT(server_task_id == tid);
} else {
+ server_thread = Thread::MAIN_ID;
physics_server_2d->init();
}
}
void PhysicsServer2DWrapMT::finish() {
if (create_thread) {
- command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
+ command_queue.push(physics_server_2d, &PhysicsServer2D::finish);
+ command_queue.push(this, &PhysicsServer2DWrapMT::_thread_exit);
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
}
+ server_thread = Thread::MAIN_ID;
} else {
physics_server_2d->finish();
}
@@ -108,9 +105,6 @@ void PhysicsServer2DWrapMT::finish() {
PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) {
physics_server_2d = p_contained;
create_thread = p_create_thread;
- if (!create_thread) {
- server_thread = Thread::MAIN_ID;
- }
}
PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index 5e2b3b4086..f0c36a906f 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -53,17 +53,14 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
mutable CommandQueueMT command_queue;
- void thread_loop();
-
Thread::ID server_thread = Thread::UNASSIGNED_ID;
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
bool exit = false;
- Semaphore step_sem;
bool create_thread = false;
- void thread_step(real_t p_delta);
-
- void thread_exit();
+ void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id);
+ void _thread_exit();
+ void _thread_loop();
public:
#define ServerName PhysicsServer2D
diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp
index f8f60281a7..95b71217c4 100644
--- a/servers/physics_server_3d_wrap_mt.cpp
+++ b/servers/physics_server_3d_wrap_mt.cpp
@@ -32,45 +32,37 @@
#include "core/os/os.h"
-void PhysicsServer3DWrapMT::thread_exit() {
- exit = true;
+void PhysicsServer3DWrapMT::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
+ server_thread = Thread::get_caller_id();
+ server_task_id = p_pump_task_id;
}
-void PhysicsServer3DWrapMT::thread_step(real_t p_delta) {
- physics_server_3d->step(p_delta);
- step_sem.post();
+void PhysicsServer3DWrapMT::_thread_exit() {
+ exit = true;
}
-void PhysicsServer3DWrapMT::thread_loop() {
- server_thread = Thread::get_caller_id();
-
- physics_server_3d->init();
-
- command_queue.set_pump_task_id(server_task_id);
+void PhysicsServer3DWrapMT::_thread_loop() {
while (!exit) {
WorkerThreadPool::get_singleton()->yield();
command_queue.flush_all();
}
-
- command_queue.flush_all(); // flush all
-
- physics_server_3d->finish();
}
/* EVENT QUEUING */
void PhysicsServer3DWrapMT::step(real_t p_step) {
if (create_thread) {
- command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
+ command_queue.push(physics_server_3d, &PhysicsServer3D::step, p_step);
} else {
- command_queue.flush_all(); // Flush all pending from other threads.
physics_server_3d->step(p_step);
}
}
void PhysicsServer3DWrapMT::sync() {
if (create_thread) {
- step_sem.wait();
+ command_queue.sync();
+ } else {
+ command_queue.flush_all(); // Flush all pending from other threads.
}
physics_server_3d->sync();
}
@@ -85,21 +77,26 @@ void PhysicsServer3DWrapMT::end_sync() {
void PhysicsServer3DWrapMT::init() {
if (create_thread) {
- exit = false;
- server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::thread_loop), true);
- step_sem.post();
+ WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::_thread_loop), true);
+ command_queue.set_pump_task_id(tid);
+ command_queue.push(this, &PhysicsServer3DWrapMT::_assign_mt_ids, tid);
+ command_queue.push_and_sync(physics_server_3d, &PhysicsServer3D::init);
+ DEV_ASSERT(server_task_id == tid);
} else {
+ server_thread = Thread::MAIN_ID;
physics_server_3d->init();
}
}
void PhysicsServer3DWrapMT::finish() {
if (create_thread) {
- command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
+ command_queue.push(physics_server_3d, &PhysicsServer3D::finish);
+ command_queue.push(this, &PhysicsServer3DWrapMT::_thread_exit);
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
}
+ server_thread = Thread::MAIN_ID;
} else {
physics_server_3d->finish();
}
@@ -108,9 +105,6 @@ void PhysicsServer3DWrapMT::finish() {
PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) {
physics_server_3d = p_contained;
create_thread = p_create_thread;
- if (!create_thread) {
- server_thread = Thread::MAIN_ID;
- }
}
PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index 22f3ee0e45..0909c46b55 100644
--- a/servers/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -52,17 +52,15 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D {
mutable CommandQueueMT command_queue;
- void thread_loop();
-
Thread::ID server_thread = Thread::UNASSIGNED_ID;
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
bool exit = false;
- Semaphore step_sem;
bool create_thread = false;
- void thread_step(real_t p_delta);
-
- void thread_exit();
+ void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id);
+ void _thread_exit();
+ void _thread_step(real_t p_delta);
+ void _thread_loop();
public:
#define ServerName PhysicsServer3D
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 1a75614a4c..7a15d202a3 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -325,6 +325,7 @@ void register_server_types() {
PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
GDREGISTER_ABSTRACT_CLASS(XRInterface);
+ GDREGISTER_CLASS(XRVRS);
GDREGISTER_CLASS(XRBodyTracker);
GDREGISTER_CLASS(XRControllerTracker);
GDREGISTER_CLASS(XRFaceTracker);
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 1331ca72c2..43572b65e0 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -193,6 +193,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override {}
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_UPDATE_DISABLED; }
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index e48c72cec7..42de831e7a 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -38,6 +38,12 @@
#include "rendering_server_globals.h"
#include "servers/rendering/storage/texture_storage.h"
+// Use the same antialiasing feather size as StyleBoxFlat's default
+// (but doubled, as it's specified for both sides here).
+// This value is empirically determined to provide good antialiasing quality
+// while not making lines appear too soft.
+const static float FEATHER_SIZE = 1.25f;
+
void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
@@ -638,11 +644,8 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
if (p_antialiased) {
- // Use the same antialiasing feather size as StyleBoxFlat's default
- // (but doubled, as it's specified for both sides here).
- // This value is empirically determined to provide good antialiasing quality
- // while not making lines appear too soft.
- float border_size = 1.25f;
+ float border_size = FEATHER_SIZE;
+
if (0.0f <= p_width && p_width < 1.0f) {
border_size *= p_width;
}
@@ -651,7 +654,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
Vector2 border = dir * border_size;
Vector2 border2 = dir2 * border_size;
- Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0);
+ Color transparent = Color(p_color, 0.0);
{
Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
@@ -903,11 +906,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
- // Use the same antialiasing feather size as StyleBoxFlat's default
- // (but doubled, as it's specified for both sides here).
- // This value is empirically determined to provide good antialiasing quality
- // while not making lines appear too soft.
- float border_size = 1.25f;
+ float border_size = FEATHER_SIZE;
if (p_width < 1.0f) {
border_size *= p_width;
}
@@ -1094,12 +1093,15 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
pline->polygon.create(indices, points, colors);
}
-void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
ERR_FAIL_COND(p_points.is_empty() || p_points.size() % 2 != 0);
ERR_FAIL_COND(p_colors.size() != 1 && p_colors.size() * 2 != p_points.size());
// TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out.
if (p_width < 0) {
+ if (p_antialiased) {
+ WARN_PRINT("Antialiasing is not supported for thin multilines drawn using line strips (`p_width < 0`).");
+ }
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1127,7 +1129,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
Vector2 from = p_points[i * 2 + 0];
Vector2 to = p_points[i * 2 + 1];
- canvas_item_add_line(p_item, from, to, color, p_width);
+ canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);
}
} else { //} else if (p_colors.size() << 1 == p_points.size()) {
for (int i = 0; i < p_colors.size(); i++) {
@@ -1135,13 +1137,13 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
Vector2 from = p_points[i * 2 + 0];
Vector2 to = p_points[i * 2 + 1];
- canvas_item_add_line(p_item, from, to, color, p_width);
+ canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);
}
}
}
}
-void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) {
+void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -1149,45 +1151,251 @@ void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, c
ERR_FAIL_NULL(rect);
rect->modulate = p_color;
rect->rect = p_rect;
+
+ // Add feathers.
+ if (p_antialiased) {
+ float border_size = FEATHER_SIZE;
+
+ const real_t size = MIN(p_rect.size.width, p_rect.size.height);
+ if (0.0f <= size && size < 1.0f) {
+ border_size *= size;
+ }
+
+ const Vector2 vec_down = Vector2(0.0f, p_rect.size.height);
+ const Vector2 vec_right = Vector2(p_rect.size.width, 0.0f);
+
+ const Vector2 begin_left = p_rect.position;
+ const Vector2 begin_right = p_rect.position + vec_down;
+ const Vector2 end_left = p_rect.position + vec_right;
+ const Vector2 end_right = p_rect.position + p_rect.size;
+
+ const Vector2 dir = Vector2(0.0f, -1.0f);
+ const Vector2 dir2 = Vector2(-1.0f, 0.0f);
+ const Vector2 border = dir * border_size;
+ const Vector2 border2 = dir2 * border_size;
+
+ Color transparent = Color(p_color, 0.0);
+
+ {
+ Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(left_border);
+
+ left_border->points[0] = begin_left;
+ left_border->points[1] = begin_left + border;
+ left_border->points[2] = end_left + border;
+ left_border->points[3] = end_left;
+
+ left_border->colors[0] = p_color;
+ left_border->colors[1] = transparent;
+ left_border->colors[2] = transparent;
+ left_border->colors[3] = p_color;
+
+ left_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(right_border);
+
+ right_border->points[0] = begin_right;
+ right_border->points[1] = begin_right - border;
+ right_border->points[2] = end_right - border;
+ right_border->points[3] = end_right;
+
+ right_border->colors[0] = p_color;
+ right_border->colors[1] = transparent;
+ right_border->colors[2] = transparent;
+ right_border->colors[3] = p_color;
+
+ right_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_border);
+
+ top_border->points[0] = begin_left;
+ top_border->points[1] = begin_left + border2;
+ top_border->points[2] = begin_right + border2;
+ top_border->points[3] = begin_right;
+
+ top_border->colors[0] = p_color;
+ top_border->colors[1] = transparent;
+ top_border->colors[2] = transparent;
+ top_border->colors[3] = p_color;
+
+ top_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_border);
+
+ bottom_border->points[0] = end_left;
+ bottom_border->points[1] = end_left - border2;
+ bottom_border->points[2] = end_right - border2;
+ bottom_border->points[3] = end_right;
+
+ bottom_border->colors[0] = p_color;
+ bottom_border->colors[1] = transparent;
+ bottom_border->colors[2] = transparent;
+ bottom_border->colors[3] = p_color;
+
+ bottom_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_left_corner);
+
+ top_left_corner->points[0] = begin_left;
+ top_left_corner->points[1] = begin_left + border2;
+ top_left_corner->points[2] = begin_left + border + border2;
+ top_left_corner->points[3] = begin_left + border;
+
+ top_left_corner->colors[0] = p_color;
+ top_left_corner->colors[1] = transparent;
+ top_left_corner->colors[2] = transparent;
+ top_left_corner->colors[3] = transparent;
+
+ top_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(top_right_corner);
+
+ top_right_corner->points[0] = begin_right;
+ top_right_corner->points[1] = begin_right + border2;
+ top_right_corner->points[2] = begin_right - border + border2;
+ top_right_corner->points[3] = begin_right - border;
+
+ top_right_corner->colors[0] = p_color;
+ top_right_corner->colors[1] = transparent;
+ top_right_corner->colors[2] = transparent;
+ top_right_corner->colors[3] = transparent;
+
+ top_right_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_left_corner);
+
+ bottom_left_corner->points[0] = end_left;
+ bottom_left_corner->points[1] = end_left - border2;
+ bottom_left_corner->points[2] = end_left + border - border2;
+ bottom_left_corner->points[3] = end_left + border;
+
+ bottom_left_corner->colors[0] = p_color;
+ bottom_left_corner->colors[1] = transparent;
+ bottom_left_corner->colors[2] = transparent;
+ bottom_left_corner->colors[3] = transparent;
+
+ bottom_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_NULL(bottom_right_corner);
+
+ bottom_right_corner->points[0] = end_right;
+ bottom_right_corner->points[1] = end_right - border2;
+ bottom_right_corner->points[2] = end_right - border - border2;
+ bottom_right_corner->points[3] = end_right - border;
+
+ bottom_right_corner->colors[0] = p_color;
+ bottom_right_corner->colors[1] = transparent;
+ bottom_right_corner->colors[2] = transparent;
+ bottom_right_corner->colors[3] = transparent;
+
+ bottom_right_corner->point_count = 4;
+ }
+ }
}
-void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
+void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
- Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_NULL(circle);
+ static const int circle_segments = 64;
- circle->primitive = RS::PRIMITIVE_TRIANGLES;
+ {
+ Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_NULL(circle);
- Vector<int> indices;
- Vector<Vector2> points;
+ circle->primitive = RS::PRIMITIVE_TRIANGLES;
- static const int circle_points = 64;
+ Vector<int> indices;
+ Vector<Vector2> points;
- points.resize(circle_points);
- Vector2 *points_ptr = points.ptrw();
- const real_t circle_point_step = Math_TAU / circle_points;
+ points.resize(circle_segments + 2);
+ Vector2 *points_ptr = points.ptrw();
- for (int i = 0; i < circle_points; i++) {
- float angle = i * circle_point_step;
- points_ptr[i].x = Math::cos(angle) * p_radius;
- points_ptr[i].y = Math::sin(angle) * p_radius;
- points_ptr[i] += p_pos;
- }
+ // Store circle center in the last point.
+ points_ptr[circle_segments + 1] = p_pos;
- indices.resize((circle_points - 2) * 3);
- int *indices_ptr = indices.ptrw();
+ const real_t circle_point_step = Math_TAU / circle_segments;
+
+ for (int i = 0; i < circle_segments + 1; i++) {
+ float angle = i * circle_point_step;
+ points_ptr[i].x = Math::cos(angle) * p_radius;
+ points_ptr[i].y = Math::sin(angle) * p_radius;
+ points_ptr[i] += p_pos;
+ }
- for (int i = 0; i < circle_points - 2; i++) {
- indices_ptr[i * 3 + 0] = 0;
- indices_ptr[i * 3 + 1] = i + 1;
- indices_ptr[i * 3 + 2] = i + 2;
+ indices.resize(circle_segments * 3);
+ int *indices_ptr = indices.ptrw();
+
+ for (int i = 0; i < circle_segments; i++) {
+ indices_ptr[i * 3 + 0] = circle_segments + 1;
+ indices_ptr[i * 3 + 1] = i;
+ indices_ptr[i * 3 + 2] = i + 1;
+ }
+
+ Vector<Color> color;
+ color.push_back(p_color);
+ circle->polygon.create(indices, points, color);
}
- Vector<Color> color;
- color.push_back(p_color);
- circle->polygon.create(indices, points, color);
+ if (p_antialiased) {
+ float border_size = FEATHER_SIZE;
+
+ const float diameter = p_radius * 2.0f;
+ if (0.0f <= diameter && diameter < 1.0f) {
+ border_size *= p_radius;
+ }
+
+ Item::CommandPolygon *feather = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_NULL(feather);
+ feather->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+
+ Color transparent = Color(p_color, 0.0);
+
+ Vector<int> indices;
+ Vector<Color> colors;
+ Vector<Vector2> points;
+
+ points.resize(2 * circle_segments + 2);
+ colors.resize(2 * circle_segments + 2);
+
+ const real_t circle_point_step = Math_TAU / circle_segments;
+
+ Vector2 *points_ptr = points.ptrw();
+ Color *colors_ptr = colors.ptrw();
+
+ for (int i = 0; i < circle_segments + 1; i++) {
+ const float angle = i * circle_point_step;
+ const float c = Math::cos(angle);
+ const float s = Math::sin(angle);
+
+ points_ptr[i * 2].x = c * p_radius;
+ points_ptr[i * 2].y = s * p_radius;
+ points_ptr[i * 2] += p_pos;
+
+ points_ptr[i * 2 + 1].x = c * (p_radius + border_size);
+ points_ptr[i * 2 + 1].y = s * (p_radius + border_size);
+ points_ptr[i * 2 + 1] += p_pos;
+
+ colors_ptr[i * 2] = p_color;
+ colors_ptr[i * 2 + 1] = transparent;
+ }
+
+ feather->polygon.create(indices, points, colors);
+ }
}
void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 961506ca28..9f8cbea2e9 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -233,9 +233,9 @@ public:
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false);
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
- void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
- void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
- void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
+ void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
+ void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased);
+ void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index a363b03dd8..c7a7532d76 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -661,10 +661,9 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, 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());
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_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -927,10 +926,9 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, 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(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_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp
index 017ad41fdc..04afaf63d7 100644
--- a/servers/rendering/renderer_rd/effects/debug_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp
@@ -354,7 +354,9 @@ void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_f
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass()));
- Projection reprojection = p_previous_projection.flipped_y() * p_previous_transform.affine_inverse() * p_current_transform * p_current_projection.flipped_y().inverse();
+ Projection correction;
+ correction.set_depth_correction(true, true, false);
+ Projection reprojection = (correction * p_previous_projection) * p_previous_transform.affine_inverse() * p_current_transform * (correction * p_current_projection).inverse();
RendererRD::MaterialStorage::store_camera(reprojection, motion_vectors.push_constant.reprojection_matrix);
motion_vectors.push_constant.resolution[0] = p_resolution.width;
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 30c318fb9a..94453bf95f 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -80,7 +80,16 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
- VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+ VRSPushConstant push_constant = {};
+
+ int mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+
+ // Set maximum texel factor based on maximum fragment size, some GPUs do not support 8x8 (fragment shading rate approach).
+ if (MIN(RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_WIDTH), RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_HEIGHT)) > 4) {
+ push_constant.max_texel_factor = 3.0;
+ } else {
+ push_constant.max_texel_factor = 2.0;
+ }
RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -88,7 +97,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>());
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.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_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(VRSPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -111,12 +120,11 @@ Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+ RS::ViewportVRSUpdateMode vrs_update_mode = texture_storage->render_target_get_vrs_update_mode(p_render_target);
- if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ if (vrs_mode != RS::VIEWPORT_VRS_DISABLED && vrs_update_mode != RS::VIEWPORT_VRS_UPDATE_DISABLED) {
RD::get_singleton()->draw_command_begin_label("VRS Setup");
- // TODO figure out if image has changed since it was last copied so we can save some resources..
-
if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
if (vrs_texture.is_valid()) {
@@ -145,6 +153,10 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
#endif // _3D_DISABLED
}
+ if (vrs_update_mode == RS::VIEWPORT_VRS_UPDATE_ONCE) {
+ texture_storage->render_target_set_vrs_update_mode(p_render_target, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+ }
+
RD::get_singleton()->draw_command_end_label();
}
}
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
index b18cf55791..94878e4661 100644
--- a/servers/rendering/renderer_rd/effects/vrs.h
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -47,11 +47,12 @@ private:
VRS_MAX,
};
- /* we have no push constant here (yet)
struct VRSPushConstant {
-
+ float max_texel_factor; // 4x8, 8x4 and 8x8 are only available on some GPUs.
+ float res1;
+ float res2;
+ float res3;
};
- */
struct VRSShader {
// VRSPushConstant push_constant;
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 2df0331688..aae32f0b3e 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -972,14 +972,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
float distance = 0.0;
// Check if camera is NOT inside the mesh AABB.
- if (!inst->transformed_aabb.has_point(p_render_data->scene_data->cam_transform.origin)) {
+ if (!inst->transformed_aabb.has_point(p_render_data->scene_data->main_cam_transform.origin)) {
// Get the LOD support points on the mesh AABB.
- Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
- Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
+ Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z));
+ Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z));
// Get the distances to those points on the AABB from the camera origin.
- float distance_min = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_min);
- float distance_max = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_max);
+ float distance_min = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_min);
+ float distance_max = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_max);
if (distance_min * distance_max < 0.0) {
//crossing plane
@@ -1388,7 +1388,6 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
p_render_data->shadows.clear();
p_render_data->directional_shadows.clear();
- Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < p_render_data->render_shadow_count; i++) {
@@ -1407,7 +1406,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
RENDER_TIMESTAMP("Render OmniLight Shadows");
// Cube shadows are rendered in their own way.
for (const int &index : p_render_data->cube_shadows) {
- _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
+ _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
}
if (p_render_data->directional_shadows.size()) {
@@ -1437,11 +1436,11 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
//render directional shadows
for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
}
//render positional shadows
for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform);
}
_render_shadow_process();
@@ -1812,6 +1811,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+ RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment);
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
@@ -1823,7 +1823,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1833,13 +1833,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
- draw_sky = true;
+ draw_sky = !p_render_data->transparent_bg;
} break;
case RS::ENV_BG_CANVAS: {
if (!is_reflection_probe) {
@@ -1859,7 +1859,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
@@ -2289,11 +2289,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
params.delta_time = float(time_step);
params.reset_accumulation = false; // FIXME: The engine does not provide a way to reset the accumulation.
+ Projection correction;
+ correction.set_depth_correction(true, true, false);
+
const Projection &prev_proj = p_render_data->scene_data->prev_cam_projection;
const Projection &cur_proj = p_render_data->scene_data->cam_projection;
const Transform3D &prev_transform = p_render_data->scene_data->prev_cam_transform;
const Transform3D &cur_transform = p_render_data->scene_data->cam_transform;
- params.reprojection = prev_proj.flipped_y() * prev_transform.affine_inverse() * cur_transform * cur_proj.flipped_y().inverse();
+ params.reprojection = (correction * prev_proj) * prev_transform.affine_inverse() * cur_transform * (correction * cur_proj).inverse();
fsr2_effect->upscale(params);
}
@@ -2367,7 +2370,7 @@ void RenderForwardClustered::_render_buffers_debug_draw(const RenderDataRD *p_re
}
}
-void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) {
+void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
ERR_FAIL_COND(!light_storage->owns_light_instance(p_light));
@@ -2522,7 +2525,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas
if (render_cubemap) {
//rendering to cubemap
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size, p_main_cam_transform);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size, p_main_cam_transform);
if (finalize_cubemap) {
_render_shadow_process();
_render_shadow_end();
@@ -2540,7 +2543,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas
} else {
//render shadow
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size, p_main_cam_transform);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size, p_main_cam_transform);
}
}
@@ -2553,7 +2556,7 @@ void RenderForwardClustered::_render_shadow_begin() {
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -2611,7 +2614,6 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
shadow_pass.pass_mode = pass_mode;
shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
- shadow_pass.camera_plane = p_camera_plane;
shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold;
shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier;
@@ -3575,11 +3577,11 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RID RenderForwardClustered::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
- return p_render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? rb_data->get_normal_roughness() : rb_data->get_normal_roughness_msaa();
+ return rb_data->get_normal_roughness();
}
RID RenderForwardClustered::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
- return p_render_buffers->get_velocity_buffer(p_render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED);
+ return p_render_buffers->get_velocity_buffer(false);
}
void RenderForwardClustered::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 1f12d92754..ae9e5e7c10 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -347,7 +347,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PassMode pass_mode;
RID rp_uniform_set;
- Plane camera_plane;
float lod_distance_multiplier;
float screen_mesh_lod_threshold;
@@ -594,9 +593,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
/* Render shadows */
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D());
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D());
void _render_shadow_begin();
- void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D());
+ void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D());
void _render_shadow_process();
void _render_shadow_end();
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 5715d94d95..194a70dc22 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -590,7 +590,6 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
p_render_data->shadows.clear();
p_render_data->directional_shadows.clear();
- Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < p_render_data->render_shadow_count; i++) {
@@ -608,7 +607,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
//cube shadows are rendered in their own way
for (const int &index : p_render_data->cube_shadows) {
- _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, p_render_data->scene_data->cam_transform);
+ _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, p_render_data->scene_data->cam_transform);
}
if (p_render_data->directional_shadows.size()) {
@@ -629,11 +628,11 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
//render directional shadows
for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, p_render_data->scene_data->cam_transform);
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, p_render_data->scene_data->cam_transform);
}
//render positional shadows
for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, p_render_data->scene_data->cam_transform);
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, p_render_data->scene_data->cam_transform);
}
_render_shadow_process();
@@ -830,6 +829,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+ RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment);
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
@@ -841,7 +841,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if (environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -851,13 +851,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if (environment_get_fog_enabled(p_render_data->environment)) {
+ if (!p_render_data->transparent_bg && environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
- draw_sky = true;
+ draw_sky = !p_render_data->transparent_bg;
} break;
case RS::ENV_BG_CANVAS: {
if (rb_data.is_valid()) {
@@ -874,7 +874,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
@@ -1114,7 +1114,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/* these are being called from RendererSceneRenderRD::_pre_opaque_render */
-void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) {
+void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
ERR_FAIL_COND(!light_storage->owns_light_instance(p_light));
@@ -1268,7 +1268,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i
if (render_cubemap) {
//rendering to cubemap
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_main_cam_transform);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_main_cam_transform);
if (finalize_cubemap) {
_render_shadow_process();
_render_shadow_end();
@@ -1287,7 +1287,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i
} else {
//render shadow
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_main_cam_transform);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_main_cam_transform);
}
}
@@ -1299,7 +1299,7 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -1356,7 +1356,6 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
shadow_pass.pass_mode = pass_mode;
shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
- shadow_pass.camera_plane = p_camera_plane;
shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold;
shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier;
@@ -1878,25 +1877,27 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
// LOD
if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
- // Get the LOD support points on the mesh AABB.
- Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
- Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
-
- // Get the distances to those points on the AABB from the camera origin.
- float distance_min = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_min);
- float distance_max = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_max);
-
float distance = 0.0;
- if (distance_min * distance_max < 0.0) {
- //crossing plane
- distance = 0.0;
- } else if (distance_min >= 0.0) {
- distance = distance_min;
- } else if (distance_max <= 0.0) {
- distance = -distance_max;
+ // Check if camera is NOT inside the mesh AABB.
+ if (!inst->transformed_aabb.has_point(p_render_data->scene_data->main_cam_transform.origin)) {
+ // Get the LOD support points on the mesh AABB.
+ Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z));
+ Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z));
+
+ // Get the distances to those points on the AABB from the camera origin.
+ float distance_min = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_min);
+ float distance_max = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_max);
+
+ if (distance_min * distance_max < 0.0) {
+ //crossing plane
+ distance = 0.0;
+ } else if (distance_min >= 0.0) {
+ distance = distance_min;
+ } else if (distance_max <= 0.0) {
+ distance = -distance_max;
+ }
}
-
if (p_render_data->scene_data->cam_orthogonal) {
distance = 1.0;
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index f29503e5ec..aa1b8f34b2 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -178,9 +178,9 @@ private:
/* Render shadows */
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D());
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D());
void _render_shadow_begin();
- void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D());
+ void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D());
void _render_shadow_process();
void _render_shadow_end();
@@ -270,7 +270,6 @@ private:
PassMode pass_mode;
RID rp_uniform_set;
- Plane camera_plane;
float lod_distance_multiplier;
float screen_mesh_lod_threshold;
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 733cbd1ff2..dd722cc2dd 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
@@ -587,7 +587,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
- actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX\n";
+ actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX_USED\n";
actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n";
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 012451a5cd..14d138181f 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -169,7 +169,11 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
return;
}
- RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID);
+ Error err = RD::get_singleton()->screen_prepare_for_drawing(DisplayServer::MAIN_WINDOW_ID);
+ if (err != OK) {
+ // Window is minimized and does not have valid swapchain, skip drawing without printing errors.
+ return;
+ }
RID texture = texture_storage->texture_allocate();
texture_storage->texture_2d_initialize(texture, p_image);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 6cb03871c9..1e4880e67a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1149,6 +1149,10 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
render_data.sdfgi_update_data = p_sdfgi_update_data;
render_data.render_info = r_render_info;
+
+ if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
+ render_data.transparent_bg = texture_storage->render_target_get_transparent(rb->get_render_target());
+ }
}
PagedArray<RID> empty;
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 789c6c2845..1c1b8366e5 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -687,8 +687,8 @@ void ShaderRD::enable_group(int p_group) {
// Compile all versions again to include the new group.
List<RID> all_versions;
version_owner.get_owned_list(&all_versions);
- for (int i = 0; i < all_versions.size(); i++) {
- Version *version = version_owner.get_or_null(all_versions[i]);
+ for (const RID &E : all_versions) {
+ Version *version = version_owner.get_or_null(E);
_compile_version(version, p_group);
}
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index 23b0373eef..b4fcaa4673 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -19,6 +19,14 @@ layout(location = 0) out vec3 uv_interp;
layout(location = 0) out vec2 uv_interp;
#endif
+layout(push_constant, std430) uniform Params {
+ float max_texel_factor;
+ float res1;
+ float res2;
+ float res3;
+}
+params;
+
void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
@@ -53,6 +61,14 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(location = 0) out uint frag_color;
+layout(push_constant, std430) uniform Params {
+ float max_texel_factor;
+ float res1;
+ float res2;
+ float res3;
+}
+params;
+
void main() {
#ifdef USE_MULTIVIEW
vec3 uv = uv_interp;
@@ -60,20 +76,22 @@ void main() {
vec2 uv = uv_interp;
#endif
-#ifdef USE_MULTIVIEW
+ // Input is standardized. R for X, G for Y, 0.0 (0) = 1, 0.33 (85) = 2, 0.66 (170) = 3, 1.0 (255) = 8
vec4 color = textureLod(source_color, uv, 0.0);
- frag_color = uint(color.r * 255.0);
-#else /* USE_MULTIVIEW */
- vec4 color = textureLod(source_color, uv, 0.0);
-
- // for user supplied VRS map we do a color mapping
- color.r *= 3.0;
- frag_color = int(color.r) << 2;
- color.g *= 3.0;
- frag_color += int(color.g);
-
- // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
- // 4x8, 8x4 and 8x8 are only available on some GPUs
-#endif /* USE_MULTIVIEW */
+ // Output image shading rate image for VRS according to VK_KHR_fragment_shading_rate.
+ color.r = clamp(floor(color.r * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
+ color.g = clamp(floor(color.g * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
+
+ // Note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported:
+ if (color.r < (color.g - 1.0)) {
+ color.r = color.g - 1.0;
+ }
+ if (color.g < (color.r - 1.0)) {
+ color.g = color.r - 1.0;
+ }
+
+ // Encode to frag_color;
+ frag_color = int(color.r + 0.1) << 2;
+ frag_color += int(color.g + 0.1);
}
diff --git a/servers/rendering/renderer_rd/shaders/samplers_inc.glsl b/servers/rendering/renderer_rd/shaders/samplers_inc.glsl
index 3f6172795e..ae5dbd4761 100644
--- a/servers/rendering/renderer_rd/shaders/samplers_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/samplers_inc.glsl
@@ -9,4 +9,4 @@ layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 7) uniform sampler SAMP
layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 8) uniform sampler SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT;
layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 9) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT;
layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 10) uniform sampler SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT;
-layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 11) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT; \ No newline at end of file
+layout(set = 0, binding = SAMPLERS_BINDING_FIRST_INDEX + 11) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index d1ff9fc362..3d294ca8cb 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -2025,7 +2025,7 @@ void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits
for (int i = 0; i < 4; i++) {
//clear subdivisions
shadow_atlas->quadrants[i].shadows.clear();
- shadow_atlas->quadrants[i].shadows.resize(int64_t(1) << int64_t(shadow_atlas->quadrants[i].subdivision));
+ shadow_atlas->quadrants[i].shadows.resize(int64_t(shadow_atlas->quadrants[i].subdivision * shadow_atlas->quadrants[i].subdivision));
}
//erase shadow atlas reference from lights
diff --git a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h
index 2f61899a18..3cd397b8ed 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_data_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_data_rd.h
@@ -78,6 +78,9 @@ public:
RenderingMethod::RenderInfo *render_info = nullptr;
+ /* Viewport data */
+ bool transparent_bg = false;
+
/* Shadow data */
const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
int render_shadow_count = 0;
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 76ff566b18..6e5e8f63e0 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -1457,6 +1457,23 @@ void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::Te
}
void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
+ List<RID> textures;
+ texture_owner.get_owned_list(&textures);
+
+ for (List<RID>::Element *E = textures.front(); E; E = E->next()) {
+ Texture *t = texture_owner.get_or_null(E->get());
+ if (!t) {
+ continue;
+ }
+ RS::TextureInfo tinfo;
+ tinfo.path = t->path;
+ tinfo.format = t->format;
+ tinfo.width = t->width;
+ tinfo.height = t->height;
+ tinfo.depth = t->depth;
+ tinfo.bytes = Image::get_image_data_size(t->width, t->height, t->format, t->mipmaps);
+ r_info->push_back(tinfo);
+ }
}
void TextureStorage::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
@@ -3042,6 +3059,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
texture_2d_placeholder_initialize(rt->texture);
Texture *tex = get_texture(rt->texture);
tex->is_render_target = true;
+ tex->path = "Render Target (Internal)";
}
_clear_render_target(rt);
@@ -3960,6 +3978,20 @@ RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_targ
return rt->vrs_mode;
}
+void TextureStorage::render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_NULL(rt);
+
+ rt->vrs_update_mode = p_mode;
+}
+
+RS::ViewportVRSUpdateMode TextureStorage::render_target_get_vrs_update_mode(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_NULL_V(rt, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+
+ return rt->vrs_update_mode;
+}
+
void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL(rt);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 1304b284d5..704f5fb1bd 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -366,6 +366,7 @@ private:
// VRS
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
+ RS::ViewportVRSUpdateMode vrs_update_mode = RS::VIEWPORT_VRS_UPDATE_ONCE;
RID vrs_texture;
// overridden textures
@@ -746,6 +747,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override;
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
virtual RID render_target_get_vrs_texture(RID p_render_target) const override;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 96c0479ac3..b02d3def88 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -958,6 +958,8 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh
if (instance->mesh_instance.is_valid()) {
RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
}
+
+ _instance_queue_update(instance, false, false);
}
void RendererSceneCull::instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) {
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 31d5a9074c..884f8adb8c 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -85,7 +85,7 @@ Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports()
}
while (!nodes.is_empty()) {
- const Viewport *node = nodes[0];
+ const Viewport *node = nodes.front()->get();
nodes.pop_front();
for (int i = active_viewports.size() - 1; i >= 0; --i) {
@@ -678,7 +678,7 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
#endif // _3D_DISABLED
if (Engine::get_singleton()->is_editor_hint()) {
- set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
+ RSG::texture_storage->set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
}
if (sorted_active_viewports_dirty) {
@@ -1450,6 +1450,13 @@ void RendererViewport::viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode
_configure_3d_render_buffers(viewport);
}
+void RendererViewport::viewport_set_vrs_update_mode(RID p_viewport, RS::ViewportVRSUpdateMode p_mode) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_NULL(viewport);
+
+ RSG::texture_storage->render_target_set_vrs_update_mode(viewport->render_target, p_mode);
+}
+
void RendererViewport::viewport_set_vrs_texture(RID p_viewport, RID p_texture) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_NULL(viewport);
@@ -1514,10 +1521,6 @@ void RendererViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time,
}
}
-void RendererViewport::set_default_clear_color(const Color &p_color) {
- RSG::texture_storage->set_default_clear_color(p_color);
-}
-
void RendererViewport::viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_NULL(viewport);
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 5107398c54..b36fc7f57f 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -298,11 +298,11 @@ public:
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode);
+ void viewport_set_vrs_update_mode(RID p_viewport, RS::ViewportVRSUpdateMode p_mode);
void viewport_set_vrs_texture(RID p_viewport, RID p_texture);
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
- void set_default_clear_color(const Color &p_color);
void draw_viewports(bool p_swap_buffers);
bool free(RID p_rid);
diff --git a/servers/rendering/rendering_context_driver.h b/servers/rendering/rendering_context_driver.h
index df1424da95..539b3814a0 100644
--- a/servers/rendering/rendering_context_driver.h
+++ b/servers/rendering/rendering_context_driver.h
@@ -73,10 +73,15 @@ public:
DEVICE_TYPE_MAX = 0x5
};
+ struct Workarounds {
+ bool avoid_compute_after_draw = false;
+ };
+
struct Device {
String name = "Unknown";
Vendor vendor = VENDOR_UNKNOWN;
DeviceType type = DEVICE_TYPE_OTHER;
+ Workarounds workarounds;
};
virtual ~RenderingContextDriver();
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 962531c866..0227472d0e 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -671,9 +671,9 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
TextureFormat format = p_format;
if (format.shareable_formats.size()) {
- ERR_FAIL_COND_V_MSG(format.shareable_formats.find(format.format) == -1, RID(),
+ ERR_FAIL_COND_V_MSG(!format.shareable_formats.has(format.format), RID(),
"If supplied a list of shareable formats, the current format must be present in the list");
- ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && format.shareable_formats.find(p_view.format_override) == -1, RID(),
+ ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && !format.shareable_formats.has(p_view.format_override), RID(),
"If supplied a list of shareable formats, the current view format override must be present in the list");
}
@@ -854,7 +854,7 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with
} else {
ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID());
- ERR_FAIL_COND_V_MSG(texture.allowed_shared_formats.find(p_view.format_override) == -1, RID(),
+ ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(),
"Format override is not in the list of allowed shareable formats for original texture.");
tv.format = p_view.format_override;
}
@@ -984,7 +984,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view,
} else {
ERR_FAIL_INDEX_V(p_view.format_override, DATA_FORMAT_MAX, RID());
- ERR_FAIL_COND_V_MSG(texture.allowed_shared_formats.find(p_view.format_override) == -1, RID(),
+ ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(),
"Format override is not in the list of allowed shareable formats for original texture.");
tv.format = p_view.format_override;
}
@@ -3154,9 +3154,6 @@ Error RenderingDevice::screen_create(DisplayServer::WindowID p_screen) {
RDD::SwapChainID swap_chain = driver->swap_chain_create(surface);
ERR_FAIL_COND_V_MSG(swap_chain.id == 0, ERR_CANT_CREATE, "Unable to create swap chain.");
- Error err = driver->swap_chain_resize(main_queue, swap_chain, _get_swap_chain_desired_count());
- ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_CREATE, "Unable to resize the new swap chain.");
-
screen_swap_chains[p_screen] = swap_chain;
return OK;
@@ -3335,12 +3332,15 @@ Error RenderingDevice::_draw_list_setup_framebuffer(Framebuffer *p_framebuffer,
}
Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i p_viewport_offset, Point2i p_viewport_size, RDD::FramebufferID p_framebuffer_driver_id, RDD::RenderPassID p_render_pass) {
- LocalVector<RDD::RenderPassClearValue> clear_values;
- LocalVector<RDG::ResourceTracker *> resource_trackers;
- LocalVector<RDG::ResourceUsage> resource_usages;
+ thread_local LocalVector<RDD::RenderPassClearValue> clear_values;
+ thread_local LocalVector<RDG::ResourceTracker *> resource_trackers;
+ thread_local LocalVector<RDG::ResourceUsage> resource_usages;
bool uses_color = false;
bool uses_depth = false;
+ clear_values.clear();
clear_values.resize(p_framebuffer->texture_ids.size());
+ resource_trackers.clear();
+ resource_usages.clear();
int clear_values_count = 0;
{
int color_index = 0;
@@ -3451,9 +3451,9 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { // Check custom region.
Rect2i viewport(viewport_offset, viewport_size);
Rect2i regioni = p_region;
- if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
- ((regioni.position.x + regioni.size.x) <= (viewport.position.x + viewport.size.x)) &&
- ((regioni.position.y + regioni.size.y) <= (viewport.position.y + viewport.size.y))) {
+ if (!((regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
+ ((regioni.position.x + regioni.size.x) <= (viewport.position.x + viewport.size.x)) &&
+ ((regioni.position.y + regioni.size.y) <= (viewport.position.y + viewport.size.y)))) {
ERR_FAIL_V_MSG(INVALID_ID, "When supplying a custom region, it must be contained within the framebuffer rectangle");
}
@@ -3774,13 +3774,13 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
#endif
- // Bind descriptor sets.
-
+#ifdef DEBUG_ENABLED
for (uint32_t i = 0; i < dl->state.set_count; i++) {
if (dl->state.sets[i].pipeline_expected_format == 0) {
- continue; // Nothing expected by this pipeline.
+ // Nothing expected by this pipeline.
+ continue;
}
-#ifdef DEBUG_ENABLED
+
if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) {
if (dl->state.sets[i].uniform_set_format == 0) {
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
@@ -3791,9 +3791,22 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(dl->state.pipeline_shader));
}
}
+ }
#endif
- draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i);
+
+ // Prepare descriptor sets if the API doesn't use pipeline barriers.
+ if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
+ for (uint32_t i = 0; i < dl->state.set_count; i++) {
+ if (dl->state.sets[i].pipeline_expected_format == 0) {
+ // Nothing expected by this pipeline.
+ continue;
+ }
+
+ draw_graph.add_draw_list_uniform_set_prepare_for_use(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i);
+ }
}
+
+ // Bind descriptor sets.
for (uint32_t i = 0; i < dl->state.set_count; i++) {
if (dl->state.sets[i].pipeline_expected_format == 0) {
continue; // Nothing expected by this pipeline.
@@ -3858,6 +3871,8 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
draw_graph.add_draw_list_draw(to_draw, p_instances);
}
+
+ dl->state.draw_count++;
}
void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) {
@@ -4165,13 +4180,13 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g
#endif
- // Bind descriptor sets.
-
+#ifdef DEBUG_ENABLED
for (uint32_t i = 0; i < cl->state.set_count; i++) {
if (cl->state.sets[i].pipeline_expected_format == 0) {
- continue; // Nothing expected by this pipeline.
+ // Nothing expected by this pipeline.
+ continue;
}
-#ifdef DEBUG_ENABLED
+
if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) {
if (cl->state.sets[i].uniform_set_format == 0) {
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
@@ -4182,9 +4197,22 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader));
}
}
+ }
#endif
- draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i);
+
+ // Prepare descriptor sets if the API doesn't use pipeline barriers.
+ if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
+ for (uint32_t i = 0; i < cl->state.set_count; i++) {
+ if (cl->state.sets[i].pipeline_expected_format == 0) {
+ // Nothing expected by this pipeline.
+ continue;
+ }
+
+ draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i);
+ }
}
+
+ // Bind descriptor sets.
for (uint32_t i = 0; i < cl->state.set_count; i++) {
if (cl->state.sets[i].pipeline_expected_format == 0) {
continue; // Nothing expected by this pipeline.
@@ -4201,6 +4229,7 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g
}
draw_graph.add_compute_list_dispatch(p_x_groups, p_y_groups, p_z_groups);
+ cl->state.dispatch_count++;
}
void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) {
@@ -4258,16 +4287,16 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p
#endif
- // Bind descriptor sets.
-
+#ifdef DEBUG_ENABLED
for (uint32_t i = 0; i < cl->state.set_count; i++) {
if (cl->state.sets[i].pipeline_expected_format == 0) {
- continue; // Nothing expected by this pipeline.
+ // Nothing expected by this pipeline.
+ continue;
}
-#ifdef DEBUG_ENABLED
+
if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) {
if (cl->state.sets[i].uniform_set_format == 0) {
- ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline");
+ ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline.");
} else if (uniform_set_owner.owns(cl->state.sets[i].uniform_set)) {
UniformSet *us = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set);
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader));
@@ -4275,9 +4304,22 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader));
}
}
+ }
#endif
- draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i);
+
+ // Prepare descriptor sets if the API doesn't use pipeline barriers.
+ if (!driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS)) {
+ for (uint32_t i = 0; i < cl->state.set_count; i++) {
+ if (cl->state.sets[i].pipeline_expected_format == 0) {
+ // Nothing expected by this pipeline.
+ continue;
+ }
+
+ draw_graph.add_compute_list_uniform_set_prepare_for_use(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i);
+ }
}
+
+ // Bind descriptor sets.
for (uint32_t i = 0; i < cl->state.set_count; i++) {
if (cl->state.sets[i].pipeline_expected_format == 0) {
continue; // Nothing expected by this pipeline.
@@ -4294,6 +4336,7 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p
}
draw_graph.add_compute_list_dispatch_indirect(buffer->driver_id, p_offset);
+ cl->state.dispatch_count++;
if (buffer->draw_tracker != nullptr) {
draw_graph.add_compute_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
@@ -4694,6 +4737,10 @@ String RenderingDevice::get_device_api_name() const {
return driver->get_api_name();
}
+bool RenderingDevice::is_composite_alpha_supported() const {
+ return driver->is_composite_alpha_supported(main_queue);
+}
+
String RenderingDevice::get_device_api_version() const {
return driver->get_api_version();
}
@@ -4873,25 +4920,78 @@ void RenderingDevice::_end_frame() {
ERR_PRINT("Found open compute list at the end of the frame, this should never happen (further compute will likely not work).");
}
- draw_graph.end(frames[frame].draw_command_buffer, RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS);
driver->command_buffer_end(frames[frame].setup_command_buffer);
- driver->command_buffer_end(frames[frame].draw_command_buffer);
+
+ // The command buffer must be copied into a stack variable as the driver workarounds can change the command buffer in use.
+ RDD::CommandBufferID command_buffer = frames[frame].draw_command_buffer;
+ draw_graph.end(RENDER_GRAPH_REORDER, RENDER_GRAPH_FULL_BARRIERS, command_buffer, frames[frame].command_buffer_pool);
+ driver->command_buffer_end(command_buffer);
driver->end_segment();
}
void RenderingDevice::_execute_frame(bool p_present) {
+ // Check whether this frame should present the swap chains and in which queue.
const bool frame_can_present = p_present && !frames[frame].swap_chains_to_present.is_empty();
const bool separate_present_queue = main_queue != present_queue;
- const VectorView<RDD::SemaphoreID> execute_draw_semaphore = frame_can_present && separate_present_queue ? frames[frame].draw_semaphore : VectorView<RDD::SemaphoreID>();
- const VectorView<RDD::SwapChainID> execute_draw_swap_chains = frame_can_present && !separate_present_queue ? frames[frame].swap_chains_to_present : VectorView<RDD::SwapChainID>();
+ thread_local LocalVector<RDD::SwapChainID> swap_chains;
+ swap_chains.clear();
+
+ // Execute the setup command buffer.
driver->command_queue_execute_and_present(main_queue, {}, frames[frame].setup_command_buffer, frames[frame].setup_semaphore, {}, {});
- driver->command_queue_execute_and_present(main_queue, frames[frame].setup_semaphore, frames[frame].draw_command_buffer, execute_draw_semaphore, frames[frame].draw_fence, execute_draw_swap_chains);
+
+ // Execute command buffers and use semaphores to wait on the execution of the previous one. Normally there's only one command buffer,
+ // but driver workarounds can force situations where there'll be more.
+ uint32_t command_buffer_count = 1;
+ RDG::CommandBufferPool &buffer_pool = frames[frame].command_buffer_pool;
+ if (buffer_pool.buffers_used > 0) {
+ command_buffer_count += buffer_pool.buffers_used;
+ buffer_pool.buffers_used = 0;
+ }
+
+ RDD::SemaphoreID wait_semaphore = frames[frame].setup_semaphore;
+ for (uint32_t i = 0; i < command_buffer_count; i++) {
+ RDD::CommandBufferID command_buffer;
+ RDD::SemaphoreID signal_semaphore;
+ RDD::FenceID signal_fence;
+ if (i > 0) {
+ command_buffer = buffer_pool.buffers[i - 1];
+ signal_semaphore = buffer_pool.semaphores[i - 1];
+ } else {
+ command_buffer = frames[frame].draw_command_buffer;
+ signal_semaphore = frames[frame].draw_semaphore;
+ }
+
+ bool signal_semaphore_valid;
+ if (i == (command_buffer_count - 1)) {
+ // This is the last command buffer, it should signal the fence.
+ signal_fence = frames[frame].draw_fence;
+ signal_semaphore_valid = false;
+
+ if (frame_can_present && separate_present_queue) {
+ // The semaphore is required if the frame can be presented and a separate present queue is used.
+ signal_semaphore_valid = true;
+ } else if (frame_can_present) {
+ // Just present the swap chains as part of the last command execution.
+ swap_chains = frames[frame].swap_chains_to_present;
+ }
+ } else {
+ // Semaphores always need to be signaled if it's not the last command buffer.
+ signal_semaphore_valid = true;
+ }
+
+ driver->command_queue_execute_and_present(main_queue, wait_semaphore, command_buffer, signal_semaphore_valid ? signal_semaphore : VectorView<RDD::SemaphoreID>(), signal_fence, swap_chains);
+
+ // Make the next command buffer wait on the semaphore signaled by this one.
+ wait_semaphore = signal_semaphore;
+ }
+
+ // Indicate the fence has been signaled so the next time the frame's contents need to be used, the CPU needs to wait on the work to be completed.
frames[frame].draw_fence_signaled = true;
if (frame_can_present) {
if (separate_present_queue) {
// Issue the presentation separately if the presentation queue is different from the main queue.
- driver->command_queue_execute_and_present(present_queue, frames[frame].draw_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present);
+ driver->command_queue_execute_and_present(present_queue, wait_semaphore, {}, {}, {}, frames[frame].swap_chains_to_present);
}
frames[frame].swap_chains_to_present.clear();
@@ -5040,6 +5140,9 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
frames[i].timestamp_cpu_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_values.resize(max_timestamp_query_elements);
frames[i].timestamp_result_count = 0;
+
+ // Assign the main queue family and command pool to the command buffer pool.
+ frames[i].command_buffer_pool.pool = frames[i].command_pool;
}
// Start from frame count, so everything else is immediately old.
@@ -5051,7 +5154,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
driver->command_buffer_begin(frames[0].draw_command_buffer);
// Create draw graph and start it initialized as well.
- draw_graph.initialize(driver, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME);
+ draw_graph.initialize(driver, device, frames.size(), main_queue_family, SECONDARY_COMMAND_BUFFERS_PER_FRAME);
draw_graph.begin();
for (uint32_t i = 0; i < frames.size(); i++) {
@@ -5206,8 +5309,8 @@ void RenderingDevice::_free_rids(T &p_owner, const char *p_type) {
}
void RenderingDevice::capture_timestamp(const String &p_name) {
- ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
- ERR_FAIL_COND_MSG(compute_list != nullptr, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name);
+ ERR_FAIL_COND_MSG(draw_list != nullptr && draw_list->state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
+ ERR_FAIL_COND_MSG(compute_list != nullptr && compute_list->state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name);
ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements);
draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count);
@@ -5384,6 +5487,11 @@ void RenderingDevice::finalize() {
driver->semaphore_free(frames[i].setup_semaphore);
driver->semaphore_free(frames[i].draw_semaphore);
driver->fence_free(frames[i].draw_fence);
+
+ RDG::CommandBufferPool &buffer_pool = frames[i].command_buffer_pool;
+ for (uint32_t j = 0; j < buffer_pool.buffers.size(); j++) {
+ driver->semaphore_free(buffer_pool.semaphores[j]);
+ }
}
if (pipeline_cache_enabled) {
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 9a898a2fca..d0fa4ab1fa 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -797,6 +797,8 @@ private:
#endif
public:
+ RenderingContextDriver *get_context_driver() const { return context; }
+
const RDD::Capabilities &get_device_capabilities() const { return driver->get_capabilities(); }
bool has_feature(const Features p_feature) const;
@@ -1046,6 +1048,7 @@ private:
uint32_t pipeline_shader_layout_hash = 0;
RID vertex_array;
RID index_array;
+ uint32_t draw_count = 0;
} state;
#ifdef DEBUG_ENABLED
@@ -1147,6 +1150,7 @@ private:
uint32_t local_group_size[3] = { 0, 0, 0 };
uint8_t push_constant_data[MAX_PUSH_CONSTANT_SIZE] = {};
uint32_t push_constant_size = 0;
+ uint32_t dispatch_count = 0;
} state;
#ifdef DEBUG_ENABLED
@@ -1259,6 +1263,9 @@ private:
// Swap chains prepared for drawing during the frame that must be presented.
LocalVector<RDD::SwapChainID> swap_chains_to_present;
+ // Extra command buffer pool used for driver workarounds.
+ RDG::CommandBufferPool command_buffer_pool;
+
struct Timestamp {
String description;
uint64_t value = 0;
@@ -1353,6 +1360,8 @@ public:
String get_device_api_version() const;
String get_device_pipeline_cache_uuid() const;
+ bool is_composite_alpha_supported() const;
+
uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0);
static RenderingDevice *get_singleton();
diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h
index 28d641c879..918bf9b834 100644
--- a/servers/rendering/rendering_device_commons.h
+++ b/servers/rendering/rendering_device_commons.h
@@ -810,6 +810,8 @@ public:
LIMIT_SUBGROUP_OPERATIONS,
LIMIT_VRS_TEXEL_WIDTH,
LIMIT_VRS_TEXEL_HEIGHT,
+ LIMIT_VRS_MAX_FRAGMENT_WIDTH,
+ LIMIT_VRS_MAX_FRAGMENT_HEIGHT,
};
enum Features {
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index e9464ba321..f9a861426a 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -769,6 +769,8 @@ public:
virtual String get_pipeline_cache_uuid() const = 0;
virtual const Capabilities &get_capabilities() const = 0;
+ virtual bool is_composite_alpha_supported(CommandQueueID p_queue) const { return false; }
+
/******************/
virtual ~RenderingDeviceDriver();
diff --git a/servers/rendering/rendering_device_graph.cpp b/servers/rendering/rendering_device_graph.cpp
index b04f2ebbaa..c7de5c67cb 100644
--- a/servers/rendering/rendering_device_graph.cpp
+++ b/servers/rendering/rendering_device_graph.cpp
@@ -753,71 +753,96 @@ void RenderingDeviceGraph::_wait_for_secondary_command_buffer_tasks() {
}
}
-void RenderingDeviceGraph::_run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level) {
+void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level) {
for (uint32_t i = 0; i < p_sorted_commands_count; i++) {
const uint32_t command_index = p_sorted_commands[i].index;
const uint32_t command_data_offset = command_data_offsets[command_index];
const RecordedCommand *command = reinterpret_cast<RecordedCommand *>(&command_data[command_data_offset]);
- _run_label_command_change(p_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level);
+ _run_label_command_change(r_command_buffer, command->label_index, p_level, false, true, &p_sorted_commands[i], p_sorted_commands_count - i, r_current_label_index, r_current_label_level);
switch (command->type) {
case RecordedCommand::TYPE_BUFFER_CLEAR: {
const RecordedBufferClearCommand *buffer_clear_command = reinterpret_cast<const RecordedBufferClearCommand *>(command);
- driver->command_clear_buffer(p_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size);
+ driver->command_clear_buffer(r_command_buffer, buffer_clear_command->buffer, buffer_clear_command->offset, buffer_clear_command->size);
} break;
case RecordedCommand::TYPE_BUFFER_COPY: {
const RecordedBufferCopyCommand *buffer_copy_command = reinterpret_cast<const RecordedBufferCopyCommand *>(command);
- driver->command_copy_buffer(p_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region);
+ driver->command_copy_buffer(r_command_buffer, buffer_copy_command->source, buffer_copy_command->destination, buffer_copy_command->region);
} break;
case RecordedCommand::TYPE_BUFFER_GET_DATA: {
const RecordedBufferGetDataCommand *buffer_get_data_command = reinterpret_cast<const RecordedBufferGetDataCommand *>(command);
- driver->command_copy_buffer(p_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region);
+ driver->command_copy_buffer(r_command_buffer, buffer_get_data_command->source, buffer_get_data_command->destination, buffer_get_data_command->region);
} break;
case RecordedCommand::TYPE_BUFFER_UPDATE: {
const RecordedBufferUpdateCommand *buffer_update_command = reinterpret_cast<const RecordedBufferUpdateCommand *>(command);
const RecordedBufferCopy *command_buffer_copies = buffer_update_command->buffer_copies();
for (uint32_t j = 0; j < buffer_update_command->buffer_copies_count; j++) {
- driver->command_copy_buffer(p_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region);
+ driver->command_copy_buffer(r_command_buffer, command_buffer_copies[j].source, buffer_update_command->destination, command_buffer_copies[j].region);
}
} break;
case RecordedCommand::TYPE_COMPUTE_LIST: {
+ if (device.workarounds.avoid_compute_after_draw && workarounds_state.draw_list_found) {
+ // Avoid compute after draw workaround. Refer to the comment that enables this in the Vulkan driver for more information.
+ workarounds_state.draw_list_found = false;
+
+ // Create or reuse a command buffer and finish recording the current one.
+ driver->command_buffer_end(r_command_buffer);
+
+ while (r_command_buffer_pool.buffers_used >= r_command_buffer_pool.buffers.size()) {
+ RDD::CommandBufferID command_buffer = driver->command_buffer_create(r_command_buffer_pool.pool);
+ RDD::SemaphoreID command_semaphore = driver->semaphore_create();
+ r_command_buffer_pool.buffers.push_back(command_buffer);
+ r_command_buffer_pool.semaphores.push_back(command_semaphore);
+ }
+
+ // Start recording on the next usable command buffer from the pool.
+ uint32_t command_buffer_index = r_command_buffer_pool.buffers_used++;
+ r_command_buffer = r_command_buffer_pool.buffers[command_buffer_index];
+ driver->command_buffer_begin(r_command_buffer);
+ }
+
const RecordedComputeListCommand *compute_list_command = reinterpret_cast<const RecordedComputeListCommand *>(command);
- _run_compute_list_command(p_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size);
+ _run_compute_list_command(r_command_buffer, compute_list_command->instruction_data(), compute_list_command->instruction_data_size);
} break;
case RecordedCommand::TYPE_DRAW_LIST: {
+ if (device.workarounds.avoid_compute_after_draw) {
+ // Indicate that a draw list was encountered for the workaround.
+ workarounds_state.draw_list_found = true;
+ }
+
const RecordedDrawListCommand *draw_list_command = reinterpret_cast<const RecordedDrawListCommand *>(command);
const VectorView clear_values(draw_list_command->clear_values(), draw_list_command->clear_values_count);
- driver->command_begin_render_pass(p_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values);
- _run_draw_list_command(p_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size);
- driver->command_end_render_pass(p_command_buffer);
+ driver->command_begin_render_pass(r_command_buffer, draw_list_command->render_pass, draw_list_command->framebuffer, draw_list_command->command_buffer_type, draw_list_command->region, clear_values);
+ _run_draw_list_command(r_command_buffer, draw_list_command->instruction_data(), draw_list_command->instruction_data_size);
+ driver->command_end_render_pass(r_command_buffer);
} break;
case RecordedCommand::TYPE_TEXTURE_CLEAR: {
const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast<const RecordedTextureClearCommand *>(command);
- driver->command_clear_color_texture(p_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range);
+ driver->command_clear_color_texture(r_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range);
} break;
case RecordedCommand::TYPE_TEXTURE_COPY: {
const RecordedTextureCopyCommand *texture_copy_command = reinterpret_cast<const RecordedTextureCopyCommand *>(command);
- driver->command_copy_texture(p_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region);
+ driver->command_copy_texture(r_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region);
} break;
case RecordedCommand::TYPE_TEXTURE_GET_DATA: {
const RecordedTextureGetDataCommand *texture_get_data_command = reinterpret_cast<const RecordedTextureGetDataCommand *>(command);
const VectorView<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_view(texture_get_data_command->buffer_texture_copy_regions(), texture_get_data_command->buffer_texture_copy_regions_count);
- driver->command_copy_texture_to_buffer(p_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view);
+ driver->command_copy_texture_to_buffer(r_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view);
} break;
case RecordedCommand::TYPE_TEXTURE_RESOLVE: {
const RecordedTextureResolveCommand *texture_resolve_command = reinterpret_cast<const RecordedTextureResolveCommand *>(command);
- driver->command_resolve_texture(p_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap);
+ driver->command_resolve_texture(r_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap);
} break;
case RecordedCommand::TYPE_TEXTURE_UPDATE: {
const RecordedTextureUpdateCommand *texture_update_command = reinterpret_cast<const RecordedTextureUpdateCommand *>(command);
const RecordedBufferToTextureCopy *command_buffer_to_texture_copies = texture_update_command->buffer_to_texture_copies();
for (uint32_t j = 0; j < texture_update_command->buffer_to_texture_copies_count; j++) {
- driver->command_copy_buffer_to_texture(p_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region);
+ driver->command_copy_buffer_to_texture(r_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region);
}
} break;
case RecordedCommand::TYPE_CAPTURE_TIMESTAMP: {
const RecordedCaptureTimestampCommand *texture_capture_timestamp_command = reinterpret_cast<const RecordedCaptureTimestampCommand *>(command);
- driver->command_timestamp_write(p_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index);
+ driver->command_timestamp_write(r_command_buffer, texture_capture_timestamp_command->pool, texture_capture_timestamp_command->index);
} break;
default: {
DEV_ASSERT(false && "Unknown recorded command type.");
@@ -1229,8 +1254,9 @@ void RenderingDeviceGraph::_print_compute_list(const uint8_t *p_instruction_data
}
}
-void RenderingDeviceGraph::initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
+void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame) {
driver = p_driver;
+ device = p_device;
frames.resize(p_frame_count);
for (uint32_t i = 0; i < p_frame_count; i++) {
@@ -1805,7 +1831,7 @@ void RenderingDeviceGraph::end_label() {
command_label_index = -1;
}
-void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers) {
+void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool) {
if (command_count == 0) {
// No commands have been logged, do nothing.
return;
@@ -1919,7 +1945,12 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo
if (command_count > 0) {
int32_t current_label_index = -1;
int32_t current_label_level = -1;
- _run_label_command_change(p_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level);
+ _run_label_command_change(r_command_buffer, -1, -1, true, true, nullptr, 0, current_label_index, current_label_level);
+
+ if (device.workarounds.avoid_compute_after_draw) {
+ // Reset the state of the workaround.
+ workarounds_state.draw_list_found = false;
+ }
if (p_reorder_commands) {
#if PRINT_RENDER_GRAPH
@@ -1946,8 +1977,8 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo
RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start];
uint32_t level_command_count = i - current_level_start;
_boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority);
- _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
- _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level);
+ _group_barriers_for_render_commands(r_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
+ _run_render_commands(current_level, level_command_ptr, level_command_count, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level);
current_level = commands_sorted[i].level;
current_level_start = i;
}
@@ -1956,20 +1987,20 @@ void RenderingDeviceGraph::end(RDD::CommandBufferID p_command_buffer, bool p_reo
RecordedCommandSort *level_command_ptr = &commands_sorted[current_level_start];
uint32_t level_command_count = command_count - current_level_start;
_boost_priority_for_render_commands(level_command_ptr, level_command_count, boosted_priority);
- _group_barriers_for_render_commands(p_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
- _run_render_commands(p_command_buffer, current_level, level_command_ptr, level_command_count, current_label_index, current_label_level);
+ _group_barriers_for_render_commands(r_command_buffer, level_command_ptr, level_command_count, p_full_barriers);
+ _run_render_commands(current_level, level_command_ptr, level_command_count, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level);
#if PRINT_RENDER_GRAPH
print_line("COMMANDS", command_count, "LEVELS", current_level + 1);
#endif
} else {
for (uint32_t i = 0; i < command_count; i++) {
- _group_barriers_for_render_commands(p_command_buffer, &commands_sorted[i], 1, p_full_barriers);
- _run_render_commands(p_command_buffer, i, &commands_sorted[i], 1, current_label_index, current_label_level);
+ _group_barriers_for_render_commands(r_command_buffer, &commands_sorted[i], 1, p_full_barriers);
+ _run_render_commands(i, &commands_sorted[i], 1, r_command_buffer, r_command_buffer_pool, current_label_index, current_label_level);
}
}
- _run_label_command_change(p_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level);
+ _run_label_command_change(r_command_buffer, -1, -1, true, false, nullptr, 0, current_label_index, current_label_level);
#if PRINT_COMMAND_RECORDING
print_line(vformat("Recorded %d commands", command_count));
diff --git a/servers/rendering/rendering_device_graph.h b/servers/rendering/rendering_device_graph.h
index 3bc63bb297..a96382e0cc 100644
--- a/servers/rendering/rendering_device_graph.h
+++ b/servers/rendering/rendering_device_graph.h
@@ -184,6 +184,20 @@ public:
}
};
+ struct CommandBufferPool {
+ // Provided by RenderingDevice.
+ RDD::CommandPoolID pool;
+
+ // Created internally by RenderingDeviceGraph.
+ LocalVector<RDD::CommandBufferID> buffers;
+ LocalVector<RDD::SemaphoreID> semaphores;
+ uint32_t buffers_used = 0;
+ };
+
+ struct WorkaroundsState {
+ bool draw_list_found = false;
+ };
+
private:
struct InstructionList {
LocalVector<uint8_t> data;
@@ -560,6 +574,7 @@ private:
};
RDD *driver = nullptr;
+ RenderingContextDriver::Device device;
int64_t tracking_frame = 0;
LocalVector<uint8_t> command_data;
LocalVector<uint32_t> command_data_offsets;
@@ -582,6 +597,7 @@ private:
bool command_synchronization_pending = false;
BarrierGroup barrier_group;
bool driver_honors_barriers = false;
+ WorkaroundsState workarounds_state;
TightLocalVector<Frame> frames;
uint32_t frame = 0;
@@ -608,7 +624,7 @@ private:
void _run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size);
void _run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary);
void _wait_for_secondary_command_buffer_tasks();
- void _run_render_commands(RDD::CommandBufferID p_command_buffer, int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level);
+ void _run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level);
void _run_label_command_change(RDD::CommandBufferID p_command_buffer, int32_t p_new_label_index, int32_t p_new_level, bool p_ignore_previous_value, bool p_use_label_for_empty, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, int32_t &r_current_label_index, int32_t &r_current_label_level);
void _boost_priority_for_render_commands(RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, uint32_t &r_boosted_priority);
void _group_barriers_for_render_commands(RDD::CommandBufferID p_command_buffer, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, bool p_full_memory_barrier);
@@ -619,7 +635,7 @@ private:
public:
RenderingDeviceGraph();
~RenderingDeviceGraph();
- void initialize(RDD *p_driver, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame);
+ void initialize(RDD *p_driver, RenderingContextDriver::Device p_device, uint32_t p_frame_count, RDD::CommandQueueFamilyID p_secondary_command_queue_family, uint32_t p_secondary_command_buffers_per_frame);
void finalize();
void begin();
void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size);
@@ -664,7 +680,7 @@ public:
void add_synchronization();
void begin_label(const String &p_label_name, const Color &p_color);
void end_label();
- void end(RDD::CommandBufferID p_command_buffer, bool p_reorder_commands, bool p_full_barriers);
+ void end(bool p_reorder_commands, bool p_full_barriers, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool);
static ResourceTracker *resource_tracker_create();
static void resource_tracker_free(ResourceTracker *tracker);
};
diff --git a/servers/rendering/rendering_light_culler.cpp b/servers/rendering/rendering_light_culler.cpp
index 0889898f0b..8dc2d85bdf 100644
--- a/servers/rendering/rendering_light_culler.cpp
+++ b/servers/rendering/rendering_light_culler.cpp
@@ -279,9 +279,11 @@ bool RenderingLightCuller::add_light_camera_planes_directional(LightCullPlanes &
// Create a third point from the light direction.
Vector3 pt2 = pt0 - p_light_source.dir;
- // Create plane from 3 points.
- Plane p(pt0, pt1, pt2);
- r_cull_planes.add_cull_plane(p);
+ if (!_is_colinear_tri(pt0, pt1, pt2)) {
+ // Create plane from 3 points.
+ Plane p(pt0, pt1, pt2);
+ r_cull_planes.add_cull_plane(p);
+ }
}
// Last to 0 edge.
@@ -295,9 +297,11 @@ bool RenderingLightCuller::add_light_camera_planes_directional(LightCullPlanes &
// Create a third point from the light direction.
Vector3 pt2 = pt0 - p_light_source.dir;
- // Create plane from 3 points.
- Plane p(pt0, pt1, pt2);
- r_cull_planes.add_cull_plane(p);
+ if (!_is_colinear_tri(pt0, pt1, pt2)) {
+ // Create plane from 3 points.
+ Plane p(pt0, pt1, pt2);
+ r_cull_planes.add_cull_plane(p);
+ }
}
#ifdef LIGHT_CULLER_DEBUG_LOGGING
diff --git a/servers/rendering/rendering_light_culler.h b/servers/rendering/rendering_light_culler.h
index 0bf975430b..b0437d2310 100644
--- a/servers/rendering/rendering_light_culler.h
+++ b/servers/rendering/rendering_light_culler.h
@@ -181,14 +181,14 @@ private:
}
// Prevent divide by zero.
- if (lc > 0.00001f) {
+ if (lc > 0.001f) {
// If the summed length of the smaller two
// sides is close to the length of the longest side,
// the points are colinear, and the triangle is near degenerate.
float ld = ((la + lb) - lc) / lc;
// ld will be close to zero for colinear tris.
- return ld < 0.00001f;
+ return ld < 0.001f;
}
// Don't create planes from tiny triangles,
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 7e5ccee0e3..51ff009eaf 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -69,8 +69,6 @@ void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_call
}
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
- changes = 0;
-
RSG::rasterizer->begin_frame(frame_step);
TIMESTAMP_BEGIN()
@@ -102,19 +100,11 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::canvas->update_visibility_notifiers();
RSG::scene->update_visibility_notifiers();
- while (frame_drawn_callbacks.front()) {
- Callable c = frame_drawn_callbacks.front()->get();
- Variant result;
- Callable::CallError ce;
- c.callp(nullptr, 0, result, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
- ERR_PRINT("Error calling frame drawn function: " + err);
- }
-
- frame_drawn_callbacks.pop_front();
+ if (create_thread) {
+ callable_mp(this, &RenderingServerDefault::_run_post_draw_steps).call_deferred();
+ } else {
+ _run_post_draw_steps();
}
- RS::get_singleton()->emit_signal(SNAME("frame_post_draw"));
if (RSG::utilities->get_captured_timestamps_count()) {
Vector<FrameProfileArea> new_profile;
@@ -194,6 +184,23 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::utilities->update_memory_info();
}
+void RenderingServerDefault::_run_post_draw_steps() {
+ while (frame_drawn_callbacks.front()) {
+ Callable c = frame_drawn_callbacks.front()->get();
+ Variant result;
+ Callable::CallError ce;
+ c.callp(nullptr, 0, result, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
+ ERR_PRINT("Error calling frame drawn function: " + err);
+ }
+
+ frame_drawn_callbacks.pop_front();
+ }
+
+ emit_signal(SNAME("frame_post_draw"));
+}
+
double RenderingServerDefault::get_frame_setup_time_cpu() const {
return frame_setup_time;
}
@@ -203,7 +210,25 @@ bool RenderingServerDefault::has_changed() const {
}
void RenderingServerDefault::_init() {
+ RSG::threaded = create_thread;
+
+ RSG::canvas = memnew(RendererCanvasCull);
+ RSG::viewport = memnew(RendererViewport);
+ RendererSceneCull *sr = memnew(RendererSceneCull);
+ RSG::camera_attributes = memnew(RendererCameraAttributes);
+ RSG::scene = sr;
+ RSG::rasterizer = RendererCompositor::create();
+ RSG::utilities = RSG::rasterizer->get_utilities();
RSG::rasterizer->initialize();
+ RSG::light_storage = RSG::rasterizer->get_light_storage();
+ RSG::material_storage = RSG::rasterizer->get_material_storage();
+ RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
+ RSG::particles_storage = RSG::rasterizer->get_particles_storage();
+ RSG::texture_storage = RSG::rasterizer->get_texture_storage();
+ RSG::gi = RSG::rasterizer->get_gi();
+ RSG::fog = RSG::rasterizer->get_fog();
+ RSG::canvas_render = RSG::rasterizer->get_canvas();
+ sr->set_scene_render(RSG::rasterizer->get_scene());
}
void RenderingServerDefault::_finish() {
@@ -212,26 +237,38 @@ void RenderingServerDefault::_finish() {
}
RSG::canvas->finalize();
+ memdelete(RSG::canvas);
RSG::rasterizer->finalize();
+ memdelete(RSG::viewport);
+ memdelete(RSG::rasterizer);
+ memdelete(RSG::scene);
+ memdelete(RSG::camera_attributes);
}
void RenderingServerDefault::init() {
if (create_thread) {
print_verbose("RenderingServerWrapMT: Starting render thread");
DisplayServer::get_singleton()->release_rendering_thread();
- server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &RenderingServerDefault::_thread_loop), true);
+ WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &RenderingServerDefault::_thread_loop), true);
+ command_queue.set_pump_task_id(tid);
+ command_queue.push(this, &RenderingServerDefault::_assign_mt_ids, tid);
+ command_queue.push_and_sync(this, &RenderingServerDefault::_init);
+ DEV_ASSERT(server_task_id == tid);
} else {
+ server_thread = Thread::MAIN_ID;
_init();
}
}
void RenderingServerDefault::finish() {
if (create_thread) {
+ command_queue.push(this, &RenderingServerDefault::_finish);
command_queue.push(this, &RenderingServerDefault::_thread_exit);
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
}
+ server_thread = Thread::MAIN_ID;
} else {
_finish();
}
@@ -268,17 +305,12 @@ Vector<RenderingServer::FrameProfileArea> RenderingServerDefault::get_frame_prof
/* TESTING */
-void RenderingServerDefault::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
- redraw_request();
- RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter);
-}
-
Color RenderingServerDefault::get_default_clear_color() {
return RSG::texture_storage->get_default_clear_color();
}
void RenderingServerDefault::set_default_clear_color(const Color &p_color) {
- RSG::viewport->set_default_clear_color(p_color);
+ RSG::texture_storage->set_default_clear_color(p_color);
}
#ifndef DISABLE_DEPRECATED
@@ -327,29 +359,23 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const {
}
}
-void RenderingServerDefault::_thread_exit() {
- exit = true;
+void RenderingServerDefault::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
+ server_thread = Thread::get_caller_id();
+ server_task_id = p_pump_task_id;
}
-void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
- _draw(p_swap_buffers, frame_step);
+void RenderingServerDefault::_thread_exit() {
+ exit = true;
}
void RenderingServerDefault::_thread_loop() {
- server_thread = Thread::get_caller_id();
-
DisplayServer::get_singleton()->gl_window_make_current(DisplayServer::MAIN_WINDOW_ID); // Move GL to this thread.
- _init();
- command_queue.set_pump_task_id(server_task_id);
while (!exit) {
WorkerThreadPool::get_singleton()->yield();
command_queue.flush_all();
}
- command_queue.flush_all();
-
- _finish();
DisplayServer::get_singleton()->release_rendering_thread();
}
@@ -366,7 +392,9 @@ void RenderingServerDefault::set_physics_interpolation_enabled(bool p_enabled) {
/* EVENT QUEUING */
void RenderingServerDefault::sync() {
- if (!create_thread) {
+ if (create_thread) {
+ command_queue.sync();
+ } else {
command_queue.flush_all(); // Flush all pending from other threads.
}
}
@@ -375,8 +403,9 @@ void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Manually triggering the draw function from the RenderingServer can only be done on the main thread. Call this function from the main thread or use call_deferred().");
// Needs to be done before changes is reset to 0, to not force the editor to redraw.
RS::get_singleton()->emit_signal(SNAME("frame_pre_draw"));
+ changes = 0;
if (create_thread) {
- command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
+ command_queue.push(this, &RenderingServerDefault::_draw, p_swap_buffers, frame_step);
} else {
_draw(p_swap_buffers, frame_step);
}
@@ -390,36 +419,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) {
RenderingServer::init();
create_thread = p_create_thread;
- if (!create_thread) {
- server_thread = Thread::MAIN_ID;
- }
-
- RSG::threaded = create_thread;
-
- RSG::canvas = memnew(RendererCanvasCull);
- RSG::viewport = memnew(RendererViewport);
- RendererSceneCull *sr = memnew(RendererSceneCull);
- RSG::camera_attributes = memnew(RendererCameraAttributes);
- RSG::scene = sr;
- RSG::rasterizer = RendererCompositor::create();
- RSG::utilities = RSG::rasterizer->get_utilities();
- RSG::light_storage = RSG::rasterizer->get_light_storage();
- RSG::material_storage = RSG::rasterizer->get_material_storage();
- RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
- RSG::particles_storage = RSG::rasterizer->get_particles_storage();
- RSG::texture_storage = RSG::rasterizer->get_texture_storage();
- RSG::gi = RSG::rasterizer->get_gi();
- RSG::fog = RSG::rasterizer->get_fog();
- RSG::canvas_render = RSG::rasterizer->get_canvas();
- sr->set_scene_render(RSG::rasterizer->get_scene());
-
- frame_profile_frame = 0;
}
RenderingServerDefault::~RenderingServerDefault() {
- memdelete(RSG::canvas);
- memdelete(RSG::viewport);
- memdelete(RSG::rasterizer);
- memdelete(RSG::scene);
- memdelete(RSG::camera_attributes);
}
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index e0049e3fa4..164ec3cc09 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -63,7 +63,7 @@ class RenderingServerDefault : public RenderingServer {
static void _changes_changed() {}
- uint64_t frame_profile_frame;
+ uint64_t frame_profile_frame = 0;
Vector<FrameProfileArea> frame_profile;
double frame_setup_time = 0;
@@ -76,18 +76,17 @@ class RenderingServerDefault : public RenderingServer {
mutable CommandQueueMT command_queue;
- void _thread_loop();
-
- Thread::ID server_thread = Thread::UNASSIGNED_ID;
+ Thread::ID server_thread = Thread::MAIN_ID;
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
bool exit = false;
bool create_thread = false;
- void _thread_draw(bool p_swap_buffers, double frame_step);
-
+ void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id);
void _thread_exit();
+ void _thread_loop();
void _draw(bool p_swap_buffers, double frame_step);
+ void _run_post_draw_steps();
void _init();
void _finish();
@@ -672,6 +671,7 @@ public:
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode)
+ FUNC2(viewport_set_vrs_update_mode, RID, ViewportVRSUpdateMode)
FUNC2(viewport_set_vrs_texture, RID, RID)
/* COMPOSITOR EFFECT */
@@ -885,9 +885,9 @@ public:
FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
- FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
- FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
- FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
+ FUNC5(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
+ FUNC4(canvas_item_add_rect, RID, const Rect2 &, const Color &, bool)
+ FUNC5(canvas_item_add_circle, RID, const Point2 &, float, const Color &, bool)
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float)
@@ -997,9 +997,22 @@ public:
FUNC1(global_shader_parameters_load_settings, bool)
FUNC0(global_shader_parameters_clear)
+ /* COMPOSITOR */
+
#undef server_name
#undef ServerName
+#define ServerName RendererCompositor
+#define server_name RSG::rasterizer
+
+ FUNC4S(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
+
/* STATUS INFORMATION */
+
+#undef server_name
+#undef ServerName
+
+ /* UTILITIES */
+
#define ServerName RendererUtilities
#define server_name RSG::utilities
FUNC0RC(String, get_video_adapter_name)
@@ -1055,7 +1068,7 @@ public:
virtual void call_on_render_thread(const Callable &p_callable) override {
if (Thread::get_caller_id() == server_thread) {
command_queue.flush_if_pending();
- _call_on_render_thread(p_callable);
+ p_callable.call();
} else {
command_queue.push(this, &RenderingServerDefault::_call_on_render_thread, p_callable);
}
@@ -1065,7 +1078,6 @@ public:
virtual double get_frame_setup_time_cpu() const override;
- virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override;
virtual Color get_default_clear_color() override;
virtual void set_default_clear_color(const Color &p_color) override;
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 2b49d42f9e..a4ee33ecc0 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -362,7 +362,7 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
}
header += _constr(fnode->arguments[i].is_const);
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
- header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
+ header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].struct_name) + " " + _mkid(fnode->arguments[i].name);
} else {
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
}
@@ -479,8 +479,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
struct_code += _mkid(pnode->vstructs[i].name);
struct_code += " ";
struct_code += "{\n";
- for (int j = 0; j < st->members.size(); j++) {
- SL::MemberNode *m = st->members[j];
+ for (SL::MemberNode *m : st->members) {
if (m->datatype == SL::TYPE_STRUCT) {
struct_code += _mkid(m->struct_name);
} else {
@@ -744,7 +743,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
gcode += _constr(true);
gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type));
if (cnode.type == SL::TYPE_STRUCT) {
- gcode += _mkid(cnode.type_str);
+ gcode += _mkid(cnode.struct_name);
} else {
gcode += _typestr(cnode.type);
}
@@ -807,10 +806,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += _mktab(p_level - 1) + "{\n";
}
- for (int i = 0; i < bnode->statements.size(); i++) {
- String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ int i = 0;
+ for (List<ShaderLanguage::Node *>::ConstIterator itr = bnode->statements.begin(); itr != bnode->statements.end(); ++itr, ++i) {
+ String scode = _dump_node_code(*itr, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (bnode->statements[i]->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) {
+ if ((*itr)->type == SL::Node::NODE_TYPE_CONTROL_FLOW || bnode->single_statement) {
code += scode; //use directly
if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) {
code += ",";
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 99b3f54379..1a4c8ea742 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -1389,7 +1389,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
*r_data_type = function->arguments[i].type;
}
if (r_struct_name) {
- *r_struct_name = function->arguments[i].type_str;
+ *r_struct_name = function->arguments[i].struct_name;
}
if (r_array_size) {
*r_array_size = function->arguments[i].array_size;
@@ -1442,7 +1442,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
*r_array_size = shader->constants[p_identifier].array_size;
}
if (r_struct_name) {
- *r_struct_name = shader->constants[p_identifier].type_str;
+ *r_struct_name = shader->constants[p_identifier].struct_name;
}
if (r_constant_value) {
if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) {
@@ -3432,7 +3432,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
String func_arg_name;
if (pfunc->arguments[j].type == TYPE_STRUCT) {
- func_arg_name = pfunc->arguments[j].type_str;
+ func_arg_name = pfunc->arguments[j].struct_name;
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
@@ -3455,10 +3455,10 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
for (int j = 0; j < args.size(); j++) {
if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::NODE_TYPE_CONSTANT && args3[j] == 0 && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
//all good, but it needs implicit conversion later
- } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) || args3[j] != pfunc->arguments[j].array_size) {
+ } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].struct_name) || args3[j] != pfunc->arguments[j].array_size) {
String func_arg_name;
if (pfunc->arguments[j].type == TYPE_STRUCT) {
- func_arg_name = pfunc->arguments[j].type_str;
+ func_arg_name = pfunc->arguments[j].struct_name;
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
@@ -4076,6 +4076,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_BOOL:
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ pi.hint = PROPERTY_HINT_TYPE_STRING;
+ pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":" + RTR("On");
} else {
pi.type = Variant::BOOL;
}
@@ -4083,6 +4085,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_BVEC2:
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ pi.hint = PROPERTY_HINT_TYPE_STRING;
+ pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":x,y";
} else {
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
@@ -4092,6 +4096,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_BVEC3:
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ pi.hint = PROPERTY_HINT_TYPE_STRING;
+ pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":x,y,z";
} else {
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
@@ -4101,6 +4107,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_BVEC4:
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ pi.hint = PROPERTY_HINT_TYPE_STRING;
+ pi.hint_string = itos(Variant::INT) + "/" + itos(PROPERTY_HINT_FLAGS) + ":x,y,z,w";
} else {
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
@@ -4111,11 +4119,16 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_INT: {
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ // TODO: Handle range and encoding for for unsigned values.
} else {
pi.type = Variant::INT;
+ pi.hint = PROPERTY_HINT_RANGE;
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) {
- pi.hint = PROPERTY_HINT_RANGE;
pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]);
+ } else if (p_uniform.type == ShaderLanguage::TYPE_UINT) {
+ pi.hint_string = "0," + itos(UINT32_MAX);
+ } else {
+ pi.hint_string = itos(INT32_MIN) + "," + itos(INT32_MAX);
}
}
} break;
@@ -4123,6 +4136,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_IVEC2: {
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ // TODO: Handle vector pairs?
} else {
pi.type = Variant::VECTOR2I;
}
@@ -4131,6 +4145,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_IVEC3: {
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ // TODO: Handle vector pairs?
} else {
pi.type = Variant::VECTOR3I;
}
@@ -4139,6 +4154,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_IVEC4: {
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_INT32_ARRAY;
+ // TODO: Handle vector pairs?
} else {
pi.type = Variant::VECTOR4I;
}
@@ -5201,11 +5217,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
funcname->name = name;
func->arguments.push_back(funcname);
- for (int i = 0; i < pstruct->members.size(); i++) {
+ for (List<ShaderLanguage::MemberNode *>::Element *E = pstruct->members.front(); E; E = E->next()) {
Node *nexpr;
- if (pstruct->members[i]->array_size != 0) {
- nexpr = _parse_array_constructor(p_block, p_function_info, pstruct->members[i]->get_datatype(), pstruct->members[i]->struct_name, pstruct->members[i]->array_size);
+ if (E->get()->array_size != 0) {
+ nexpr = _parse_array_constructor(p_block, p_function_info, E->get()->get_datatype(), E->get()->struct_name, E->get()->array_size);
if (!nexpr) {
return nullptr;
}
@@ -5214,12 +5230,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!nexpr) {
return nullptr;
}
- if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) {
+ if (!_compare_datatypes_in_nodes(E->get(), nexpr)) {
return nullptr;
}
}
- if (i + 1 < pstruct->members.size()) {
+ if (E->next()) {
tk = _get_token();
if (tk.type != TK_COMMA) {
_set_expected_error(",");
@@ -7469,8 +7485,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
continue;
} else {
HashSet<int> constants;
- for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates.
- ControlFlowNode *flow = static_cast<ControlFlowNode *>(switch_block->statements[i]);
+ for (ShaderLanguage::Node *statement : switch_block->statements) { // Checks for duplicates.
+ ControlFlowNode *flow = static_cast<ControlFlowNode *>(statement);
if (flow) {
if (flow->flow_op == FLOW_OP_CASE) {
if (flow->expressions[0]->type == Node::NODE_TYPE_CONSTANT) {
@@ -9212,7 +9228,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
ShaderNode::Constant constant;
constant.name = name;
constant.type = is_struct ? TYPE_STRUCT : type;
- constant.type_str = struct_name;
+ constant.struct_name = struct_name;
constant.precision = precision;
constant.initializer = nullptr;
constant.array_size = array_size;
@@ -9391,7 +9407,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
expr->datatype = constant.type;
- expr->struct_name = constant.type_str;
+ expr->struct_name = constant.struct_name;
expr->array_size = constant.array_size;
@@ -9732,7 +9748,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
FunctionNode::Argument arg;
arg.type = param_type;
arg.name = param_name;
- arg.type_str = param_struct_name;
+ arg.struct_name = param_struct_name;
arg.precision = param_precision;
arg.qualifier = param_qualifier;
arg.tex_argument_check = false;
@@ -9846,9 +9862,9 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper
Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) {
bool found = false;
- for (int i = p_block->statements.size() - 1; i >= 0; i--) {
- if (p_block->statements[i]->type == Node::NODE_TYPE_CONTROL_FLOW) {
- ControlFlowNode *flow = static_cast<ControlFlowNode *>(p_block->statements[i]);
+ for (List<ShaderLanguage::Node *>::Element *E = p_block->statements.back(); E; E = E->prev()) {
+ if (E->get()->type == Node::NODE_TYPE_CONTROL_FLOW) {
+ ControlFlowNode *flow = static_cast<ControlFlowNode *>(E->get());
if (flow->flow_op == p_op) {
found = true;
break;
@@ -9858,8 +9874,8 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
break;
}
}
- } else if (p_block->statements[i]->type == Node::NODE_TYPE_BLOCK) {
- BlockNode *block = static_cast<BlockNode *>(p_block->statements[i]);
+ } else if (E->get()->type == Node::NODE_TYPE_BLOCK) {
+ BlockNode *block = static_cast<BlockNode *>(E->get());
if (_find_last_flow_op_in_block(block, p_op) == OK) {
found = true;
break;
@@ -10151,8 +10167,8 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
case COMPLETION_STRUCT: {
if (shader->structs.has(completion_struct)) {
StructNode *node = shader->structs[completion_struct].shader_struct;
- for (int i = 0; i < node->members.size(); i++) {
- ScriptLanguage::CodeCompletionOption option(node->members[i]->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
+ for (ShaderLanguage::MemberNode *member : node->members) {
+ ScriptLanguage::CodeCompletionOption option(member->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
r_options->push_back(option);
}
}
@@ -10355,7 +10371,11 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
if (shader->vfunctions[i].name == completion_function) {
String calltip;
- calltip += get_datatype_name(shader->vfunctions[i].function->return_type);
+ if (shader->vfunctions[i].function->return_type == TYPE_STRUCT) {
+ calltip += String(shader->vfunctions[i].function->return_struct_name);
+ } else {
+ calltip += get_datatype_name(shader->vfunctions[i].function->return_type);
+ }
if (shader->vfunctions[i].function->return_array_size > 0) {
calltip += "[";
@@ -10390,7 +10410,11 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
}
}
- calltip += get_datatype_name(shader->vfunctions[i].function->arguments[j].type);
+ if (shader->vfunctions[i].function->arguments[j].type == TYPE_STRUCT) {
+ calltip += String(shader->vfunctions[i].function->arguments[j].struct_name);
+ } else {
+ calltip += get_datatype_name(shader->vfunctions[i].function->arguments[j].type);
+ }
calltip += " ";
calltip += shader->vfunctions[i].function->arguments[j].name;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 816a202b50..38f304ff31 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -583,7 +583,7 @@ public:
ArgumentQualifier qualifier;
StringName name;
DataType type;
- StringName type_str;
+ StringName struct_name;
DataPrecision precision;
//for passing textures as arguments
bool tex_argument_check;
@@ -618,7 +618,7 @@ public:
struct Constant {
StringName name;
DataType type;
- StringName type_str;
+ StringName struct_name;
DataPrecision precision;
ConstantNode *initializer = nullptr;
int array_size;
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index b2fa0ea9d2..ab9cf666ec 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -496,7 +496,7 @@ ShaderTypes::ShaderTypes() {
shader_types_list.push_back("sky");
shader_types_list.push_back("fog");
- for (int i = 0; i < shader_types_list.size(); i++) {
- shader_types.insert(shader_types_list[i]);
+ for (const String &type : shader_types_list) {
+ shader_types.insert(type);
}
}
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index cf37fbfb4a..72c4dd305b 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -169,6 +169,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0;
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) = 0;
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const = 0;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0;
diff --git a/servers/rendering/storage/variant_converters.h b/servers/rendering/storage/variant_converters.h
index 7dbdb0f517..cee663e878 100644
--- a/servers/rendering/storage/variant_converters.h
+++ b/servers/rendering/storage/variant_converters.h
@@ -239,7 +239,8 @@ inline bool is_convertible_array(Variant::Type type) {
return type == Variant::ARRAY ||
type == Variant::PACKED_VECTOR2_ARRAY ||
type == Variant::PACKED_VECTOR3_ARRAY ||
- type == Variant::PACKED_COLOR_ARRAY;
+ type == Variant::PACKED_COLOR_ARRAY ||
+ type == Variant::PACKED_VECTOR4_ARRAY;
}
template <typename, typename = void>
diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc
index 0cef3c906c..99f2de9a9a 100644
--- a/servers/rendering_server.compat.inc
+++ b/servers/rendering_server.compat.inc
@@ -34,8 +34,23 @@ void RenderingServer::_environment_set_fog_bind_compat_84792(RID p_env, bool p_e
environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL);
}
+void RenderingServer::_canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
+ canvas_item_add_multiline(p_item, p_points, p_colors, p_width, false);
+}
+
+void RenderingServer::_canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color) {
+ canvas_item_add_rect(p_item, p_rect, p_color, false);
+}
+
+void RenderingServer::_canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
+ canvas_item_add_circle(p_item, p_pos, p_radius, p_color, false);
+}
+
void RenderingServer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792);
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::_canvas_item_add_multiline_bind_compat_84523, DEFVAL(-1.0));
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::_canvas_item_add_rect_bind_compat_84523);
+ ClassDB::bind_compatibility_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::_canvas_item_add_circle_bind_compat_84523);
}
#endif
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 60e8f18c19..7637d4e7da 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2229,6 +2229,7 @@ void RenderingServer::_bind_methods() {
BIND_CONSTANT(MAX_GLOW_LEVELS);
BIND_CONSTANT(MAX_CURSORS);
BIND_CONSTANT(MAX_2D_DIRECTIONAL_LIGHTS);
+ BIND_CONSTANT(MAX_MESH_SURFACES);
/* TEXTURE */
@@ -2824,6 +2825,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode);
+ ClassDB::bind_method(D_METHOD("viewport_set_vrs_update_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture);
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
@@ -2832,7 +2834,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
- BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled); must be manually updated.
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled, must be manually updated.
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // Default
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS);
@@ -2914,6 +2916,11 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR);
BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_ONCE); // Then goes to disabled, must be manually updated.
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_ALWAYS);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_MAX);
+
/* SKY API */
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
@@ -3223,9 +3230,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(-1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0));
- ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
- ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
+ ClassDB::bind_method(D_METHOD("canvas_item_add_multiline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_multiline, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color", "antialiased"), &RenderingServer::canvas_item_add_rect, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color", "antialiased"), &RenderingServer::canvas_item_add_circle, DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range", "scale"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 240d82c90b..e15dba4353 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -99,6 +99,10 @@ protected:
#ifndef DISABLE_DEPRECATED
void _environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ void _canvas_item_add_multiline_bind_compat_84523(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
+ void _canvas_item_add_rect_bind_compat_84523(RID p_item, const Rect2 &p_rect, const Color &p_color);
+ void _canvas_item_add_circle_bind_compat_84523(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
+
static void _bind_compatibility_methods();
#endif
@@ -1056,7 +1060,15 @@ public:
VIEWPORT_VRS_MAX,
};
+ enum ViewportVRSUpdateMode {
+ VIEWPORT_VRS_UPDATE_DISABLED,
+ VIEWPORT_VRS_UPDATE_ONCE,
+ VIEWPORT_VRS_UPDATE_ALWAYS,
+ VIEWPORT_VRS_UPDATE_MAX,
+ };
+
virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0;
+ virtual void viewport_set_vrs_update_mode(RID p_viewport, ViewportVRSUpdateMode p_mode) = 0;
virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0;
/* SKY API */
@@ -1457,9 +1469,9 @@ public:
virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
- virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0) = 0;
- virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
- virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
+ virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased = false) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0;
@@ -1815,6 +1827,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode);
+VARIANT_ENUM_CAST(RenderingServer::ViewportVRSUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
VARIANT_ENUM_CAST(RenderingServer::CompositorEffectCallbackType);
VARIANT_ENUM_CAST(RenderingServer::CompositorEffectFlags);
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 8f9797805f..c13f5db5e9 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -332,6 +332,7 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_strip_diacritics, "string");
GDVIRTUAL_BIND(_is_valid_identifier, "string");
+ GDVIRTUAL_BIND(_is_valid_letter, "unicode");
GDVIRTUAL_BIND(_string_get_word_breaks, "string", "language", "chars_per_line");
GDVIRTUAL_BIND(_string_get_character_breaks, "string", "language");
@@ -1492,6 +1493,14 @@ bool TextServerExtension::is_valid_identifier(const String &p_string) const {
return TextServer::is_valid_identifier(p_string);
}
+bool TextServerExtension::is_valid_letter(char32_t p_unicode) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_valid_letter, p_unicode, ret)) {
+ return ret;
+ }
+ return TextServer::is_valid_letter(p_unicode);
+}
+
String TextServerExtension::strip_diacritics(const String &p_string) const {
String ret;
if (GDVIRTUAL_CALL(_strip_diacritics, p_string, ret)) {
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index f447f0f5bd..d5cd1f753e 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -563,6 +563,8 @@ public:
virtual bool is_valid_identifier(const String &p_string) const override;
GDVIRTUAL1RC(bool, _is_valid_identifier, const String &);
+ virtual bool is_valid_letter(char32_t p_unicode) const override;
+ GDVIRTUAL1RC(bool, _is_valid_letter, char32_t);
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 562f2df411..127c674f0c 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -490,6 +490,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier);
+ ClassDB::bind_method(D_METHOD("is_valid_letter", "unicode"), &TextServer::is_valid_letter);
ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
@@ -2182,6 +2183,10 @@ bool TextServer::is_valid_identifier(const String &p_string) const {
return true;
}
+bool TextServer::is_valid_letter(char32_t p_unicode) const {
+ return is_unicode_letter(p_unicode);
+}
+
TextServer::TextServer() {
_init_diacritics_map();
}
diff --git a/servers/text_server.h b/servers/text_server.h
index 775dbb5508..5835b36ec4 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -547,6 +547,7 @@ public:
virtual String strip_diacritics(const String &p_string) const;
virtual bool is_valid_identifier(const String &p_string) const;
+ virtual bool is_valid_letter(char32_t p_unicode) const;
// Other string operations.
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 9ced28fd52..26f315a454 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -132,13 +132,7 @@ void XRInterface::set_primary(bool p_primary) {
XRInterface::XRInterface() {}
-XRInterface::~XRInterface() {
- if (vrs.vrs_texture.is_valid()) {
- ERR_FAIL_NULL(RenderingServer::get_singleton());
- RS::get_singleton()->free(vrs.vrs_texture);
- vrs.vrs_texture = RID();
- }
-}
+XRInterface::~XRInterface() {}
// query if this interface supports this play area mode
bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
@@ -176,80 +170,7 @@ int XRInterface::get_camera_feed_id() {
}
RID XRInterface::get_vrs_texture() {
- // Default logic will return a standard VRS image based on our target size and default projections.
- // Note that this only gets called if VRS is supported on the hardware.
-
- int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
- int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
- int view_count = get_view_count();
- Size2 target_size = get_render_target_size();
- real_t aspect = target_size.x / target_size.y; // is this y/x ?
- Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height));
- real_t radius = vrs_size.length() * 0.5;
- Size2 vrs_sizei = vrs_size;
-
- if (vrs.size != vrs_sizei) {
- const uint8_t densities[] = {
- 0, // 1x1
- 1, // 1x2
- // 2, // 1x4 - not supported
- // 3, // 1x8 - not supported
- // 4, // 2x1
- 5, // 2x2
- 6, // 2x4
- // 9, // 4x2
- 10, // 4x4
- };
-
- // out with the old
- if (vrs.vrs_texture.is_valid()) {
- RS::get_singleton()->free(vrs.vrs_texture);
- vrs.vrs_texture = RID();
- }
-
- // in with the new
- Vector<Ref<Image>> images;
- vrs.size = vrs_sizei;
-
- for (int i = 0; i < view_count && i < 2; i++) {
- PackedByteArray data;
- data.resize(vrs_sizei.x * vrs_sizei.y);
- uint8_t *data_ptr = data.ptrw();
-
- // Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
- Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
- Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
-
- Vector2i view_center;
- view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5);
- view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5);
-
- int d = 0;
- for (int y = 0; y < vrs_sizei.y; y++) {
- for (int x = 0; x < vrs_sizei.x; x++) {
- Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
- offset.y *= aspect;
- real_t distance = offset.length();
- int idx = round(5.0 * distance / radius);
- if (idx > 4) {
- idx = 4;
- }
- uint8_t density = densities[idx];
-
- data_ptr[d++] = density;
- }
- }
- images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data));
- }
-
- if (images.size() == 1) {
- vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
- } else {
- vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
- }
- }
-
- return vrs.vrs_texture;
+ return RID();
}
/** these are optional, so we want dummies **/
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 809800d8b9..7beec219bb 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -34,6 +34,7 @@
#include "core/math/projection.h"
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
+#include "xr_vrs.h"
// forward declaration
struct BlitToScreen;
@@ -133,7 +134,6 @@ public:
// These methods are called from the rendering thread.
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
- virtual RID get_vrs_texture(); /* obtain VRS texture */
virtual RID get_color_texture(); /* obtain color output texture (if applicable) */
virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */
virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */
@@ -149,19 +149,16 @@ public:
virtual bool start_passthrough() { return false; }
virtual void stop_passthrough() {}
- /** environment blend mode. */
+ /** environment blend mode **/
virtual Array get_supported_environment_blend_modes();
virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const { return XR_ENV_BLEND_MODE_OPAQUE; }
virtual bool set_environment_blend_mode(EnvironmentBlendMode mode) { return false; }
+ /** VRS **/
+ virtual RID get_vrs_texture(); /* obtain VRS texture */
+
XRInterface();
~XRInterface();
-
-private:
- struct VRSData {
- RID vrs_texture;
- Size2i size;
- } vrs;
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
diff --git a/servers/xr/xr_vrs.cpp b/servers/xr/xr_vrs.cpp
new file mode 100644
index 0000000000..9d1e2f2068
--- /dev/null
+++ b/servers/xr/xr_vrs.cpp
@@ -0,0 +1,151 @@
+/**************************************************************************/
+/* xr_vrs.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "xr_vrs.h"
+
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+void XRVRS::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &XRVRS::get_vrs_min_radius);
+ ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &XRVRS::set_vrs_min_radius);
+
+ ClassDB::bind_method(D_METHOD("get_vrs_strength"), &XRVRS::get_vrs_strength);
+ ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &XRVRS::set_vrs_strength);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
+
+ ClassDB::bind_method(D_METHOD("make_vrs_texture", "target_size", "eye_foci"), &XRVRS::make_vrs_texture);
+}
+
+XRVRS::~XRVRS() {
+ if (vrs_texture.is_valid()) {
+ ERR_FAIL_NULL(RS::get_singleton());
+ RS::get_singleton()->free(vrs_texture);
+ vrs_texture = RID();
+ }
+}
+
+float XRVRS::get_vrs_min_radius() const {
+ return vrs_min_radius;
+}
+
+void XRVRS::set_vrs_min_radius(float p_vrs_min_radius) {
+ if (p_vrs_min_radius < 1.0) {
+ WARN_PRINT_ONCE("VRS minimum radius can not be set below 1.0");
+ vrs_min_radius = 1.0;
+ } else if (p_vrs_min_radius > 100.0) {
+ WARN_PRINT_ONCE("VRS minimum radius can not be set above 100.0");
+ vrs_min_radius = 100.0;
+ } else {
+ vrs_min_radius = p_vrs_min_radius;
+ vrs_dirty = true;
+ }
+}
+
+float XRVRS::get_vrs_strength() const {
+ return vrs_strength;
+}
+
+void XRVRS::set_vrs_strength(float p_vrs_strength) {
+ if (p_vrs_strength < 0.1) {
+ WARN_PRINT_ONCE("VRS strength can not be set below 0.1");
+ vrs_strength = 0.1;
+ } else if (p_vrs_strength > 10.0) {
+ WARN_PRINT_ONCE("VRS strength can not be set above 10.0");
+ vrs_strength = 10.0;
+ } else {
+ vrs_strength = p_vrs_strength;
+ vrs_dirty = true;
+ }
+}
+
+RID XRVRS::make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci) {
+ ERR_FAIL_COND_V(p_eye_foci.is_empty(), RID());
+
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
+
+ Size2 vrs_size = Size2(0.5 + p_target_size.x / texel_width, 0.5 + p_target_size.y / texel_height).round();
+ float max_radius = 0.5 * MIN(vrs_size.x, vrs_size.y); // Maximum radius that fits inside of our image
+ float min_radius = vrs_min_radius * max_radius / 100.0; // Minimum radius as a percentage of our size
+ real_t outer_radius = MAX(1.0, (max_radius - min_radius) / vrs_strength);
+ Size2 vrs_sizei = vrs_size;
+
+ // Our density map is now unified, with a value of (0.0, 0.0) meaning a 1x1 texel size and (1.0, 1.0) an max texel size.
+ // For our standard VRS extension on Vulkan this means a maximum of 8x8.
+ // For the density map extension this scales depending on the max texel size.
+
+ if (target_size != vrs_sizei || eye_foci != p_eye_foci || vrs_dirty) {
+ // Out with the old.
+ if (vrs_texture.is_valid()) {
+ RS::get_singleton()->free(vrs_texture);
+ vrs_texture = RID();
+ }
+
+ // In with the new.
+ Vector<Ref<Image>> images;
+ target_size = vrs_sizei;
+ eye_foci = p_eye_foci;
+
+ for (int i = 0; i < eye_foci.size() && i < RendererSceneRender::MAX_RENDER_VIEWS; i++) {
+ PackedByteArray data;
+ data.resize(vrs_sizei.x * vrs_sizei.y * 2);
+ uint8_t *data_ptr = data.ptrw();
+
+ Vector2i view_center;
+ view_center.x = int(vrs_size.x * (eye_foci[i].x + 1.0) * 0.5);
+ view_center.y = int(vrs_size.y * (eye_foci[i].y + 1.0) * 0.5);
+
+ int d = 0;
+ for (int y = 0; y < vrs_sizei.y; y++) {
+ for (int x = 0; x < vrs_sizei.x; x++) {
+ Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
+ real_t density = 255.0 * MAX(0.0, (Math::abs(offset.x) - min_radius) / outer_radius);
+ data_ptr[d++] = MIN(255, density);
+ density = 255.0 * MAX(0.0, (Math::abs(offset.y) - min_radius) / outer_radius);
+ data_ptr[d++] = MIN(255, density);
+ }
+ }
+ images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_RG8, data));
+ }
+
+ if (images.size() == 1) {
+ vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
+ } else {
+ vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
+ }
+
+ vrs_dirty = false;
+ }
+
+ return vrs_texture;
+}
diff --git a/servers/xr/xr_vrs.h b/servers/xr/xr_vrs.h
new file mode 100644
index 0000000000..35dfe55620
--- /dev/null
+++ b/servers/xr/xr_vrs.h
@@ -0,0 +1,67 @@
+/**************************************************************************/
+/* xr_vrs.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 XR_VRS_H
+#define XR_VRS_H
+
+#include "core/object/class_db.h"
+#include "core/object/object.h"
+#include "core/templates/rid.h"
+#include "core/variant/variant.h"
+
+/* This is a helper class for generating stereoscopic VRS images */
+
+class XRVRS : public Object {
+ GDCLASS(XRVRS, Object);
+
+private:
+ float vrs_min_radius = 20.0;
+ float vrs_strength = 1.0;
+ bool vrs_dirty = true;
+
+ RID vrs_texture;
+ Size2i target_size;
+ PackedVector2Array eye_foci;
+
+protected:
+ static void _bind_methods();
+
+public:
+ ~XRVRS();
+
+ float get_vrs_min_radius() const;
+ void set_vrs_min_radius(float p_vrs_min_radius);
+ float get_vrs_strength() const;
+ void set_vrs_strength(float p_vrs_strength);
+
+ RID make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci);
+};
+
+#endif // XR_VRS_H