summaryrefslogtreecommitdiffstats
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio_server.cpp6
-rw-r--r--servers/display_server_headless.h42
-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/forward_clustered/render_forward_clustered.cpp13
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp9
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_data_rd.h3
-rw-r--r--servers/rendering/rendering_context_driver.h5
-rw-r--r--servers/rendering/rendering_device.cpp75
-rw-r--r--servers/rendering/rendering_device.h3
-rw-r--r--servers/rendering/rendering_device_graph.cpp83
-rw-r--r--servers/rendering/rendering_device_graph.h22
-rw-r--r--servers/rendering/rendering_server_default.h6
-rw-r--r--servers/rendering_server.compat.inc15
-rw-r--r--servers/rendering_server.cpp6
-rw-r--r--servers/rendering_server.h10
17 files changed, 495 insertions, 101 deletions
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/display_server_headless.h b/servers/display_server_headless.h
index 7a44645b1e..38baa6a4fa 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -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/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/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 8175010caf..068f9d9ef2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1812,6 +1812,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 +1824,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 +1834,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 +1860,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");
@@ -3578,11 +3579,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_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 5715d94d95..878ea7bcfb 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -830,6 +830,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 +842,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 +852,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 +875,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");
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/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/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 31fc51efaa..6746a1dde1 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -4877,25 +4877,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();
@@ -5044,6 +5097,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.
@@ -5055,7 +5111,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++) {
@@ -5388,6 +5444,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 9db2fdfbf4..020be6be18 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1261,6 +1261,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;
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_server_default.h b/servers/rendering/rendering_server_default.h
index d0b6bc492d..164ec3cc09 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -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)
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 ab82e42f43..5cfd8d3cd2 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -3229,9 +3229,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 5bc028dfdd..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
@@ -1465,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;