summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/config/project_settings.cpp17
-rw-r--r--core/input/input_event.cpp3
-rw-r--r--core/input/input_event.h5
-rw-r--r--core/input/input_map.cpp4
-rw-r--r--core/input/input_map.h5
-rw-r--r--core/io/json.cpp2
-rw-r--r--core/string/translation_server.cpp35
-rw-r--r--core/string/translation_server.h2
-rw-r--r--core/variant/variant.h13
-rw-r--r--core/variant/variant_parser.cpp2
-rw-r--r--doc/classes/Control.xml10
-rw-r--r--doc/classes/Material.xml2
-rw-r--r--doc/classes/Shader.xml6
-rw-r--r--doc/classes/Window.xml10
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp4
-rw-r--r--drivers/metal/metal_objects.h53
-rw-r--r--drivers/metal/metal_objects.mm130
-rw-r--r--drivers/metal/rendering_device_driver_metal.mm6
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.cpp1
-rw-r--r--editor/event_listener_line_edit.cpp2
-rw-r--r--editor/gui/editor_file_dialog.cpp7
-rw-r--r--editor/input_event_configuration_dialog.cpp15
-rw-r--r--editor/plugins/gizmos/lightmap_gi_gizmo_plugin.cpp5
-rw-r--r--editor/plugins/shader_editor_plugin.cpp8
-rw-r--r--editor/plugins/shader_editor_plugin.h1
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp9
-rw-r--r--modules/gdscript/editor/gdscript_docgen.cpp2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs4
-rw-r--r--modules/mono/editor/bindings_generator.cpp4
-rw-r--r--scene/3d/lightmap_gi.cpp15
-rw-r--r--scene/gui/color_picker.cpp20
-rw-r--r--scene/gui/control.cpp20
-rw-r--r--scene/gui/control.h9
-rw-r--r--scene/gui/menu_bar.cpp1
-rw-r--r--scene/main/window.cpp18
-rw-r--r--scene/main/window.h9
-rw-r--r--scene/resources/shader.cpp12
-rw-r--r--scene/resources/shader.h2
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl1
-rw-r--r--servers/rendering/renderer_scene_cull.cpp3
-rw-r--r--servers/rendering/rendering_device.cpp46
-rw-r--r--servers/rendering/rendering_device.h5
-rw-r--r--servers/rendering/rendering_device_driver.cpp2
-rw-r--r--servers/rendering/rendering_device_driver.h2
-rw-r--r--tests/core/variant/test_variant.h8
49 files changed, 403 insertions, 145 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 01f15f9c8e..d9cf65b63c 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -494,6 +494,7 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_f
}
void ProjectSettings::_convert_to_last_version(int p_from_version) {
+#ifndef DISABLE_DEPRECATED
if (p_from_version <= 3) {
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
@@ -507,6 +508,22 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
}
}
}
+ if (p_from_version <= 5) {
+ // Converts the device in events from -1 (emulated events) to -3 (all events).
+ for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
+ if (String(E.key).begins_with("input/")) {
+ Dictionary action = E.value.variant;
+ Array events = action["events"];
+ for (int i = 0; i < events.size(); i++) {
+ Ref<InputEvent> x = events[i];
+ if (x->get_device() == -1) { // -1 was the previous value (GH-97707).
+ x->set_device(InputEvent::DEVICE_ID_ALL_DEVICES);
+ }
+ }
+ }
+ }
+ }
+#endif // DISABLE_DEPRECATED
}
/*
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 905526bbbd..d125bad252 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -35,9 +35,6 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
-const int InputEvent::DEVICE_ID_EMULATION = -1;
-const int InputEvent::DEVICE_ID_INTERNAL = -2;
-
void InputEvent::set_device(int p_device) {
device = p_device;
emit_changed();
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 19176f748e..80bca28fbf 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -62,8 +62,9 @@ protected:
static void _bind_methods();
public:
- static const int DEVICE_ID_EMULATION;
- static const int DEVICE_ID_INTERNAL;
+ inline static constexpr int DEVICE_ID_EMULATION = -1;
+ inline static constexpr int DEVICE_ID_INTERNAL = -2;
+ inline static constexpr int DEVICE_ID_ALL_DEVICES = -3; // Signify that a given Action can be triggered by any device.
void set_device(int p_device);
int get_device() const;
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 27a50c79f6..5b9377fe59 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -39,8 +39,6 @@
InputMap *InputMap::singleton = nullptr;
-int InputMap::ALL_DEVICES = -1;
-
void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
@@ -163,7 +161,7 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re
int i = 0;
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
int device = E->get()->get_device();
- if (device == ALL_DEVICES || device == p_event->get_device()) {
+ if (device == InputEvent::DEVICE_ID_ALL_DEVICES || device == p_event->get_device()) {
if (E->get()->action_match(p_event, p_exact_match, p_action.deadzone, r_pressed, r_strength, r_raw_strength)) {
if (r_event_index) {
*r_event_index = i;
diff --git a/core/input/input_map.h b/core/input/input_map.h
index b29687d144..45798490f7 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -43,11 +43,6 @@ class InputMap : public Object {
GDCLASS(InputMap, Object);
public:
- /**
- * A special value used to signify that a given Action can be triggered by any device
- */
- static int ALL_DEVICES;
-
struct Action {
int id;
float deadzone;
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 664ff7857b..22219fca29 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -121,7 +121,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
d.get_key_list(&keys);
if (p_sort_keys) {
- keys.sort();
+ keys.sort_custom<StringLikeVariantOrder>();
}
bool first_key = true;
diff --git a/core/string/translation_server.cpp b/core/string/translation_server.cpp
index 89b37d0b8a..92b473b61f 100644
--- a/core/string/translation_server.cpp
+++ b/core/string/translation_server.cpp
@@ -228,32 +228,41 @@ int TranslationServer::compare_locales(const String &p_locale_a, const String &p
return 10;
}
+ const String cache_key = p_locale_a + "|" + p_locale_b;
+ const int *cached_result = locale_compare_cache.getptr(cache_key);
+ if (cached_result) {
+ return *cached_result;
+ }
+
String locale_a = _standardize_locale(p_locale_a, true);
String locale_b = _standardize_locale(p_locale_b, true);
if (locale_a == locale_b) {
// Exact match.
+ locale_compare_cache.insert(cache_key, 10);
return 10;
}
Vector<String> locale_a_elements = locale_a.split("_");
Vector<String> locale_b_elements = locale_b.split("_");
- if (locale_a_elements[0] == locale_b_elements[0]) {
- // Matching language, both locales have extra parts.
- // Return number of matching elements.
- int matching_elements = 1;
- for (int i = 1; i < locale_a_elements.size(); i++) {
- for (int j = 1; j < locale_b_elements.size(); j++) {
- if (locale_a_elements[i] == locale_b_elements[j]) {
- matching_elements++;
- }
- }
- }
- return matching_elements;
- } else {
+ if (locale_a_elements[0] != locale_b_elements[0]) {
// No match.
+ locale_compare_cache.insert(cache_key, 0);
return 0;
}
+
+ // Matching language, both locales have extra parts.
+ // Return number of matching elements.
+ int matching_elements = 1;
+ for (int i = 1; i < locale_a_elements.size(); i++) {
+ for (int j = 1; j < locale_b_elements.size(); j++) {
+ if (locale_a_elements[i] == locale_b_elements[j]) {
+ matching_elements++;
+ }
+ }
+ }
+ locale_compare_cache.insert(cache_key, matching_elements);
+ return matching_elements;
}
String TranslationServer::get_locale_name(const String &p_locale) const {
diff --git a/core/string/translation_server.h b/core/string/translation_server.h
index a09230c019..2438349a69 100644
--- a/core/string/translation_server.h
+++ b/core/string/translation_server.h
@@ -46,6 +46,8 @@ class TranslationServer : public Object {
Ref<TranslationDomain> doc_domain;
HashMap<StringName, Ref<TranslationDomain>> custom_domains;
+ mutable HashMap<String, int> locale_compare_cache;
+
bool enabled = true;
static TranslationServer *singleton;
diff --git a/core/variant/variant.h b/core/variant/variant.h
index c76b849abd..3b1924e8ea 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -854,6 +854,19 @@ struct StringLikeVariantComparator {
static bool compare(const Variant &p_lhs, const Variant &p_rhs);
};
+struct StringLikeVariantOrder {
+ static _ALWAYS_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) {
+ if (p_lhs.is_string() && p_rhs.is_string()) {
+ return p_lhs.operator String() < p_rhs.operator String();
+ }
+ return p_lhs < p_rhs;
+ }
+
+ _ALWAYS_INLINE_ bool operator()(const Variant &p_lhs, const Variant &p_rhs) const {
+ return compare(p_lhs, p_rhs);
+ }
+};
+
Variant::ObjData &Variant::_get_obj() {
return *reinterpret_cast<ObjData *>(&_data._mem[0]);
}
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index f5f96456d3..f05b9cd83a 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -2245,7 +2245,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
} else {
List<Variant> keys;
dict.get_key_list(&keys);
- keys.sort();
+ keys.sort_custom<StringLikeVariantOrder>();
if (keys.is_empty()) {
// Avoid unnecessary line break.
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 9d36bc657b..516b01bd7d 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1365,7 +1365,7 @@
<constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection">
Automatic layout direction, determined from the parent control layout direction.
</constant>
- <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection">
+ <constant name="LAYOUT_DIRECTION_APPLICATION_LOCALE" value="1" enum="LayoutDirection">
Automatic layout direction, determined from the current locale.
</constant>
<constant name="LAYOUT_DIRECTION_LTR" value="2" enum="LayoutDirection">
@@ -1374,6 +1374,14 @@
<constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection">
Right-to-left layout direction.
</constant>
+ <constant name="LAYOUT_DIRECTION_SYSTEM_LOCALE" value="4" enum="LayoutDirection">
+ Automatic layout direction, determined from the system locale.
+ </constant>
+ <constant name="LAYOUT_DIRECTION_MAX" value="5" enum="LayoutDirection">
+ Represents the size of the [enum LayoutDirection] enum.
+ </constant>
+ <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection" deprecated="Use [constant LAYOUT_DIRECTION_APPLICATION_LOCALE] instead.">
+ </constant>
<constant name="TEXT_DIRECTION_INHERITED" value="3" enum="TextDirection">
Text writing direction is the same as layout direction.
</constant>
diff --git a/doc/classes/Material.xml b/doc/classes/Material.xml
index 760773d5d9..94d12018ca 100644
--- a/doc/classes/Material.xml
+++ b/doc/classes/Material.xml
@@ -45,7 +45,7 @@
<method name="inspect_native_shader_code">
<return type="void" />
<description>
- Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code.
+ Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. See also [method Shader.inspect_native_shader_code].
</description>
</method>
</methods>
diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml
index 68176dea14..1e7f9e5ee5 100644
--- a/doc/classes/Shader.xml
+++ b/doc/classes/Shader.xml
@@ -35,6 +35,12 @@
If argument [param get_groups] is true, parameter grouping hints will be provided.
</description>
</method>
+ <method name="inspect_native_shader_code">
+ <return type="void" />
+ <description>
+ Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. See also [method Material.inspect_native_shader_code].
+ </description>
+ </method>
<method name="set_default_texture_parameter">
<return type="void" />
<param index="0" name="name" type="StringName" />
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index ca155881c8..a37e64ee12 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -878,7 +878,7 @@
<constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection">
Automatic layout direction, determined from the parent window layout direction.
</constant>
- <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection">
+ <constant name="LAYOUT_DIRECTION_APPLICATION_LOCALE" value="1" enum="LayoutDirection">
Automatic layout direction, determined from the current locale.
</constant>
<constant name="LAYOUT_DIRECTION_LTR" value="2" enum="LayoutDirection">
@@ -887,6 +887,14 @@
<constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection">
Right-to-left layout direction.
</constant>
+ <constant name="LAYOUT_DIRECTION_SYSTEM_LOCALE" value="4" enum="LayoutDirection">
+ Automatic layout direction, determined from the system locale.
+ </constant>
+ <constant name="LAYOUT_DIRECTION_MAX" value="5" enum="LayoutDirection">
+ Represents the size of the [enum LayoutDirection] enum.
+ </constant>
+ <constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection" deprecated="Use [constant LAYOUT_DIRECTION_APPLICATION_LOCALE] instead.">
+ </constant>
<constant name="WINDOW_INITIAL_POSITION_ABSOLUTE" value="0" enum="WindowInitialPosition">
Initial window position is determined by [member position].
</constant>
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index 0ef88e7d52..479afbba93 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -2003,6 +2003,8 @@ static D3D12_BARRIER_LAYOUT _rd_texture_layout_to_d3d12_barrier_layout(RDD::Text
switch (p_texture_layout) {
case RDD::TEXTURE_LAYOUT_UNDEFINED:
return D3D12_BARRIER_LAYOUT_UNDEFINED;
+ case RDD::TEXTURE_LAYOUT_GENERAL:
+ return D3D12_BARRIER_LAYOUT_COMMON;
case RDD::TEXTURE_LAYOUT_STORAGE_OPTIMAL:
return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS;
case RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
@@ -6175,6 +6177,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
return false;
case API_TRAIT_CLEARS_WITH_COPY_ENGINE:
return false;
+ case API_TRAIT_USE_GENERAL_IN_COPY_QUEUES:
+ return true;
default:
return RenderingDeviceDriver::api_trait_get(p_trait);
}
diff --git a/drivers/metal/metal_objects.h b/drivers/metal/metal_objects.h
index 030b353ee8..38d5b53ffa 100644
--- a/drivers/metal/metal_objects.h
+++ b/drivers/metal/metal_objects.h
@@ -96,6 +96,22 @@ _FORCE_INLINE_ ShaderStageUsage &operator|=(ShaderStageUsage &p_a, int p_b) {
return p_a;
}
+enum StageResourceUsage : uint32_t {
+ VertexRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_VERTEX * 2),
+ VertexWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_VERTEX * 2),
+ FragmentRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_FRAGMENT * 2),
+ FragmentWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_FRAGMENT * 2),
+ TesselationControlRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
+ TesselationControlWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
+ TesselationEvaluationRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
+ TesselationEvaluationWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
+ ComputeRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_COMPUTE * 2),
+ ComputeWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_COMPUTE * 2),
+};
+
+typedef LocalVector<__unsafe_unretained id<MTLResource>> ResourceVector;
+typedef HashMap<StageResourceUsage, ResourceVector> ResourceUsageMap;
+
enum class MDCommandBufferStateType {
None,
Render,
@@ -230,6 +246,7 @@ public:
uint32_t index_offset = 0;
LocalVector<id<MTLBuffer> __unsafe_unretained> vertex_buffers;
LocalVector<NSUInteger> vertex_offsets;
+ ResourceUsageMap resource_usage;
// clang-format off
enum DirtyFlag: uint8_t {
DIRTY_NONE = 0b0000'0000,
@@ -271,8 +288,14 @@ public:
blend_constants.reset();
vertex_buffers.clear();
vertex_offsets.clear();
+ // Keep the keys, as they are likely to be used again.
+ for (KeyValue<StageResourceUsage, LocalVector<__unsafe_unretained id<MTLResource>>> &kv : resource_usage) {
+ kv.value.clear();
+ }
}
+ void end_encoding();
+
_FORCE_INLINE_ void mark_viewport_dirty() {
if (viewports.is_empty()) {
return;
@@ -356,13 +379,20 @@ public:
} render;
// State specific for a compute pass.
- struct {
+ struct ComputeState {
MDComputePipeline *pipeline = nullptr;
id<MTLComputeCommandEncoder> encoder = nil;
+ ResourceUsageMap resource_usage;
_FORCE_INLINE_ void reset() {
pipeline = nil;
encoder = nil;
+ // Keep the keys, as they are likely to be used again.
+ for (KeyValue<StageResourceUsage, LocalVector<__unsafe_unretained id<MTLResource>>> &kv : resource_usage) {
+ kv.value.clear();
+ }
}
+
+ void end_encoding();
} compute;
// State specific to a blit pass.
@@ -632,19 +662,6 @@ public:
MDRenderShader(CharString p_name, Vector<UniformSet> p_sets, MDLibrary *p_vert, MDLibrary *p_frag);
};
-enum StageResourceUsage : uint32_t {
- VertexRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_VERTEX * 2),
- VertexWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_VERTEX * 2),
- FragmentRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_FRAGMENT * 2),
- FragmentWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_FRAGMENT * 2),
- TesselationControlRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
- TesselationControlWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
- TesselationEvaluationRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
- TesselationEvaluationWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
- ComputeRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_COMPUTE * 2),
- ComputeWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_COMPUTE * 2),
-};
-
_FORCE_INLINE_ StageResourceUsage &operator|=(StageResourceUsage &p_a, uint32_t p_b) {
p_a = StageResourceUsage(uint32_t(p_a) | p_b);
return p_a;
@@ -667,7 +684,13 @@ struct HashMapComparatorDefault<RDD::ShaderID> {
struct BoundUniformSet {
id<MTLBuffer> buffer;
- HashMap<id<MTLResource>, StageResourceUsage> bound_resources;
+ ResourceUsageMap usage_to_resources;
+
+ /// Perform a 2-way merge each key of `ResourceVector` resources from this set into the
+ /// destination set.
+ ///
+ /// Assumes the vectors of resources are sorted.
+ void merge_into(ResourceUsageMap &p_dst) const;
};
class API_AVAILABLE(macos(11.0), ios(14.0)) MDUniformSet {
diff --git a/drivers/metal/metal_objects.mm b/drivers/metal/metal_objects.mm
index 596728212a..c3906af159 100644
--- a/drivers/metal/metal_objects.mm
+++ b/drivers/metal/metal_objects.mm
@@ -58,7 +58,7 @@
void MDCommandBuffer::begin() {
DEV_ASSERT(commandBuffer == nil);
- commandBuffer = queue.commandBuffer;
+ commandBuffer = queue.commandBufferWithUnretainedReferences;
}
void MDCommandBuffer::end() {
@@ -390,6 +390,38 @@ void MDCommandBuffer::render_set_blend_constants(const Color &p_constants) {
}
}
+void BoundUniformSet::merge_into(ResourceUsageMap &p_dst) const {
+ for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : usage_to_resources) {
+ ResourceVector *resources = p_dst.getptr(keyval.key);
+ if (resources == nullptr) {
+ resources = &p_dst.insert(keyval.key, ResourceVector())->value;
+ }
+ // Reserve space for the new resources, assuming they are all added.
+ resources->reserve(resources->size() + keyval.value.size());
+
+ uint32_t i = 0, j = 0;
+ __unsafe_unretained id<MTLResource> *resources_ptr = resources->ptr();
+ const __unsafe_unretained id<MTLResource> *keyval_ptr = keyval.value.ptr();
+ // 2-way merge.
+ while (i < resources->size() && j < keyval.value.size()) {
+ if (resources_ptr[i] < keyval_ptr[j]) {
+ i++;
+ } else if (resources_ptr[i] > keyval_ptr[j]) {
+ resources->insert(i, keyval_ptr[j]);
+ i++;
+ j++;
+ } else {
+ i++;
+ j++;
+ }
+ }
+ // Append the remaining resources.
+ for (; j < keyval.value.size(); j++) {
+ resources->push_back(keyval_ptr[j]);
+ }
+ }
+}
+
void MDCommandBuffer::_render_bind_uniform_sets() {
DEV_ASSERT(type == MDCommandBufferStateType::Render);
if (!render.dirty.has_flag(RenderState::DIRTY_UNIFORMS)) {
@@ -408,7 +440,7 @@ void MDCommandBuffer::_render_bind_uniform_sets() {
// Find the index of the next set bit.
int index = __builtin_ctzll(set_uniforms);
// Clear the set bit.
- set_uniforms &= ~(1ULL << index);
+ set_uniforms &= (set_uniforms - 1);
MDUniformSet *set = render.uniform_sets[index];
if (set == nullptr || set->index >= (uint32_t)shader->sets.size()) {
continue;
@@ -416,17 +448,7 @@ void MDCommandBuffer::_render_bind_uniform_sets() {
UniformSet const &set_info = shader->sets[set->index];
BoundUniformSet &bus = set->boundUniformSetForShader(shader, device);
-
- for (KeyValue<id<MTLResource>, StageResourceUsage> const &keyval : bus.bound_resources) {
- MTLResourceUsage usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_VERTEX);
- if (usage != 0) {
- [enc useResource:keyval.key usage:usage stages:MTLRenderStageVertex];
- }
- usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_FRAGMENT);
- if (usage != 0) {
- [enc useResource:keyval.key usage:usage stages:MTLRenderStageFragment];
- }
- }
+ bus.merge_into(render.resource_usage);
// Set the buffer for the vertex stage.
{
@@ -545,8 +567,7 @@ void MDCommandBuffer::_end_render_pass() {
// see: https://github.com/KhronosGroup/MoltenVK/blob/d20d13fe2735adb845636a81522df1b9d89c0fba/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm#L407
}
- [render.encoder endEncoding];
- render.encoder = nil;
+ render.end_encoding();
}
void MDCommandBuffer::_render_clear_render_area() {
@@ -792,10 +813,59 @@ void MDCommandBuffer::render_draw_indirect_count(RDD::BufferID p_indirect_buffer
ERR_FAIL_MSG("not implemented");
}
+void MDCommandBuffer::RenderState::end_encoding() {
+ if (encoder == nil) {
+ return;
+ }
+
+ // Bind all resources.
+ for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : resource_usage) {
+ if (keyval.value.is_empty()) {
+ continue;
+ }
+
+ MTLResourceUsage vert_usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_VERTEX);
+ MTLResourceUsage frag_usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_FRAGMENT);
+ if (vert_usage == frag_usage) {
+ [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:vert_usage stages:MTLRenderStageVertex | MTLRenderStageFragment];
+ } else {
+ if (vert_usage != 0) {
+ [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:vert_usage stages:MTLRenderStageVertex];
+ }
+ if (frag_usage != 0) {
+ [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:frag_usage stages:MTLRenderStageFragment];
+ }
+ }
+ }
+
+ [encoder endEncoding];
+ encoder = nil;
+}
+
+void MDCommandBuffer::ComputeState::end_encoding() {
+ if (encoder == nil) {
+ return;
+ }
+
+ // Bind all resources.
+ for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : resource_usage) {
+ if (keyval.value.is_empty()) {
+ continue;
+ }
+ MTLResourceUsage usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_COMPUTE);
+ if (usage != 0) {
+ [encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:usage];
+ }
+ }
+
+ [encoder endEncoding];
+ encoder = nil;
+}
+
void MDCommandBuffer::render_end_pass() {
DEV_ASSERT(type == MDCommandBufferStateType::Render);
- [render.encoder endEncoding];
+ render.end_encoding();
render.reset();
type = MDCommandBufferStateType::None;
}
@@ -813,13 +883,7 @@ void MDCommandBuffer::compute_bind_uniform_set(RDD::UniformSetID p_uniform_set,
MDUniformSet *set = (MDUniformSet *)(p_uniform_set.id);
BoundUniformSet &bus = set->boundUniformSetForShader(shader, device);
-
- for (KeyValue<id<MTLResource>, StageResourceUsage> &keyval : bus.bound_resources) {
- MTLResourceUsage usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_COMPUTE);
- if (usage != 0) {
- [enc useResource:keyval.key usage:usage];
- }
- }
+ bus.merge_into(compute.resource_usage);
uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_COMPUTE);
if (offset) {
@@ -848,7 +912,7 @@ void MDCommandBuffer::compute_dispatch_indirect(RDD::BufferID p_indirect_buffer,
void MDCommandBuffer::_end_compute_dispatch() {
DEV_ASSERT(type == MDCommandBufferStateType::Compute);
- [compute.encoder endEncoding];
+ compute.end_encoding();
compute.reset();
type = MDCommandBufferStateType::None;
}
@@ -1052,7 +1116,20 @@ BoundUniformSet &MDUniformSet::boundUniformSetForShader(MDShader *p_shader, id<M
}
}
- BoundUniformSet bs = { .buffer = enc_buffer, .bound_resources = bound_resources };
+ SearchArray<__unsafe_unretained id<MTLResource>> search;
+ ResourceUsageMap usage_to_resources;
+ for (KeyValue<id<MTLResource>, StageResourceUsage> const &keyval : bound_resources) {
+ ResourceVector *resources = usage_to_resources.getptr(keyval.value);
+ if (resources == nullptr) {
+ resources = &usage_to_resources.insert(keyval.value, ResourceVector())->value;
+ }
+ int64_t pos = search.bisect(resources->ptr(), resources->size(), keyval.key, true);
+ if (pos == resources->size() || (*resources)[pos] != keyval.key) {
+ resources->insert(pos, keyval.key);
+ }
+ }
+
+ BoundUniformSet bs = { .buffer = enc_buffer, .usage_to_resources = usage_to_resources };
bound_uniforms.insert(p_shader, bs);
return bound_uniforms.get(p_shader);
}
@@ -1211,8 +1288,7 @@ vertex VaryingsPos vertClear(AttributesPos attributes [[stage_in]], constant Cle
varyings.layer = uint(attributes.a_position.w);
return varyings;
}
-)",
- ClearAttKey::DEPTH_INDEX];
+)", ClearAttKey::DEPTH_INDEX];
return new_func(msl, @"vertClear", nil);
}
diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm
index a4a408356a..4da11ecd21 100644
--- a/drivers/metal/rendering_device_driver_metal.mm
+++ b/drivers/metal/rendering_device_driver_metal.mm
@@ -2060,6 +2060,10 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec
case BT::Sampler: {
primary.dataType = MTLDataTypeSampler;
+ primary.arrayLength = 1;
+ for (uint32_t const &a : a_type.array) {
+ primary.arrayLength *= a;
+ }
} break;
default: {
@@ -2067,7 +2071,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec
} break;
}
- // Find array length.
+ // Find array length of image.
if (basetype == BT::Image || basetype == BT::SampledImage) {
primary.arrayLength = 1;
for (uint32_t const &a : a_type.array) {
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp
index d20f396281..154095552b 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp
@@ -266,6 +266,7 @@ static const VkFormat RD_TO_VK_FORMAT[RDD::DATA_FORMAT_MAX] = {
static VkImageLayout RD_TO_VK_LAYOUT[RDD::TEXTURE_LAYOUT_MAX] = {
VK_IMAGE_LAYOUT_UNDEFINED, // TEXTURE_LAYOUT_UNDEFINED
+ VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_GENERAL
VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_STORAGE_OPTIMAL
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
diff --git a/editor/event_listener_line_edit.cpp b/editor/event_listener_line_edit.cpp
index a6b30233fc..8fde728027 100644
--- a/editor/event_listener_line_edit.cpp
+++ b/editor/event_listener_line_edit.cpp
@@ -121,7 +121,7 @@ String EventListenerLineEdit::get_event_text(const Ref<InputEvent> &p_event, boo
}
String EventListenerLineEdit::get_device_string(int p_device) {
- if (p_device == InputMap::ALL_DEVICES) {
+ if (p_device == InputEvent::DEVICE_ID_ALL_DEVICES) {
return TTR("All Devices");
}
return TTR("Device") + " " + itos(p_device);
diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp
index 91b7810f77..7600748685 100644
--- a/editor/gui/editor_file_dialog.cpp
+++ b/editor/gui/editor_file_dialog.cpp
@@ -1355,6 +1355,13 @@ EditorFileDialog::Access EditorFileDialog::get_access() const {
void EditorFileDialog::_make_dir_confirm() {
const String stripped_dirname = makedirname->get_text().strip_edges();
+ if (stripped_dirname.is_empty()) {
+ error_dialog->set_text(TTR("The path specified is invalid."));
+ error_dialog->popup_centered(Size2(250, 50) * EDSCALE);
+ makedirname->set_text(""); // Reset label.
+ return;
+ }
+
if (dir_access->dir_exists(stripped_dirname)) {
error_dialog->set_text(TTR("Could not create folder. File with that name already exists."));
error_dialog->popup_centered(Size2(250, 50) * EDSCALE);
diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp
index c60197b96b..a2aeeb11bd 100644
--- a/editor/input_event_configuration_dialog.cpp
+++ b/editor/input_event_configuration_dialog.cpp
@@ -551,18 +551,18 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
}
void InputEventConfigurationDialog::_device_selection_changed(int p_option_button_index) {
- // Subtract 1 as option index 0 corresponds to "All Devices" (value of -1)
- // and option index 1 corresponds to device 0, etc...
- event->set_device(p_option_button_index - 1);
+ // Option index 0 corresponds to "All Devices" (value of -3).
+ // Otherwise subtract 1 as option index 1 corresponds to device 0, etc...
+ event->set_device(p_option_button_index == 0 ? InputEvent::DEVICE_ID_ALL_DEVICES : p_option_button_index - 1);
event_as_text->set_text(EventListenerLineEdit::get_event_text(event, true));
}
void InputEventConfigurationDialog::_set_current_device(int p_device) {
- device_id_option->select(p_device + 1);
+ device_id_option->select(p_device == InputEvent::DEVICE_ID_ALL_DEVICES ? 0 : p_device + 1);
}
int InputEventConfigurationDialog::_get_current_device() const {
- return device_id_option->get_selected() - 1;
+ return device_id_option->get_selected() == 0 ? InputEvent::DEVICE_ID_ALL_DEVICES : device_id_option->get_selected() - 1;
}
void InputEventConfigurationDialog::_notification(int p_what) {
@@ -705,11 +705,12 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_id_option = memnew(OptionButton);
device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- for (int i = -1; i < 8; i++) {
+ device_id_option->add_item(EventListenerLineEdit::get_device_string(InputEvent::DEVICE_ID_ALL_DEVICES));
+ for (int i = 0; i < 8; i++) {
device_id_option->add_item(EventListenerLineEdit::get_device_string(i));
}
device_id_option->connect(SceneStringName(item_selected), callable_mp(this, &InputEventConfigurationDialog::_device_selection_changed));
- _set_current_device(InputMap::ALL_DEVICES);
+ _set_current_device(InputEvent::DEVICE_ID_ALL_DEVICES);
device_container->add_child(device_id_option);
device_container->hide();
diff --git a/editor/plugins/gizmos/lightmap_gi_gizmo_plugin.cpp b/editor/plugins/gizmos/lightmap_gi_gizmo_plugin.cpp
index 748f770d4d..007cc0636a 100644
--- a/editor/plugins/gizmos/lightmap_gi_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/lightmap_gi_gizmo_plugin.cpp
@@ -44,7 +44,10 @@ LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() {
Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
+ // Fade out probes when camera gets too close to them.
+ mat->set_distance_fade(StandardMaterial3D::DISTANCE_FADE_PIXEL_DITHER);
+ mat->set_distance_fade_min_distance(0.5);
+ mat->set_distance_fade_max_distance(1.5);
mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, false);
mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 6b00a2c9c5..5166619f90 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -396,6 +396,7 @@ void ShaderEditorPlugin::_setup_popup_menu(PopupMenuType p_type, PopupMenu *p_me
if (p_type == FILE) {
p_menu->add_separator();
p_menu->add_item(TTR("Open File in Inspector"), FILE_INSPECT);
+ p_menu->add_item(TTR("Inspect Native Shader Code..."), FILE_INSPECT_NATIVE_SHADER_CODE);
p_menu->add_separator();
p_menu->add_shortcut(ED_SHORTCUT("shader_editor/close_file", TTR("Close File"), KeyModifierMask::CMD_OR_CTRL | Key::W), FILE_CLOSE);
} else {
@@ -554,6 +555,12 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
EditorNode::get_singleton()->push_item(edited_shaders[index].shader_inc.ptr());
}
} break;
+ case FILE_INSPECT_NATIVE_SHADER_CODE: {
+ int index = shader_tabs->get_current_tab();
+ if (edited_shaders[index].shader.is_valid()) {
+ edited_shaders[index].shader->inspect_native_shader_code();
+ }
+ } break;
case FILE_CLOSE: {
_close_shader(shader_tabs->get_current_tab());
} break;
@@ -754,6 +761,7 @@ void ShaderEditorPlugin::_set_file_specific_items_disabled(bool p_disabled) {
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE), p_disabled);
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE_AS), p_disabled);
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT), p_disabled);
+ file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT_NATIVE_SHADER_CODE), p_disabled);
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_CLOSE), p_disabled);
}
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 43e6af79fa..19e43921c3 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -69,6 +69,7 @@ class ShaderEditorPlugin : public EditorPlugin {
FILE_SAVE,
FILE_SAVE_AS,
FILE_INSPECT,
+ FILE_INSPECT_NATIVE_SHADER_CODE,
FILE_CLOSE,
CLOSE_ALL,
CLOSE_OTHER_TABS,
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index ede8351e41..a5df9edcf0 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -2128,12 +2128,11 @@ void VisualShaderEditor::_update_nodes() {
}
}
- Array keys = added.keys();
- keys.sort();
-
- for (int i = 0; i < keys.size(); i++) {
- const Variant &key = keys.get(i);
+ List<Variant> keys;
+ added.get_key_list(&keys);
+ keys.sort_custom<StringLikeVariantOrder>();
+ for (const Variant &key : keys) {
const Dictionary &value = (Dictionary)added[key];
add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]);
diff --git a/modules/gdscript/editor/gdscript_docgen.cpp b/modules/gdscript/editor/gdscript_docgen.cpp
index 32ef429b0d..758887a723 100644
--- a/modules/gdscript/editor/gdscript_docgen.cpp
+++ b/modules/gdscript/editor/gdscript_docgen.cpp
@@ -217,7 +217,7 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
List<Variant> keys;
dict.get_key_list(&keys);
- keys.sort();
+ keys.sort_custom<StringLikeVariantOrder>();
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
if (E->prev()) {
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs
index 188972e6fe..f54058b0d9 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/EventSignals_ScriptSignals.generated.cs
@@ -32,7 +32,7 @@ partial class EventSignals
add => backing_MySignal += value;
remove => backing_MySignal -= value;
}
- protected void OnMySignal(string str, int num)
+ protected void EmitSignalMySignal(string str, int num)
{
EmitSignal(SignalName.MySignal, str, num);
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs
index c734dc7be1..ffde135930 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedFields_ScriptProperties.generated.cs
@@ -807,7 +807,7 @@ partial class ExportedFields
properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@_fieldRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)38, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.@_fieldEmptyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
return properties;
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs
index 0de840aa34..94d447f61a 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs
@@ -925,7 +925,7 @@ partial class ExportedProperties
properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@PropertyRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
- properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)38, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
+ properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
return properties;
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index 0f86b3b91c..fc67e4f592 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -791,7 +791,7 @@ namespace Godot.SourceGenerators
}
}
- hint = PropertyHint.DictionaryType;
+ hint = PropertyHint.TypeString;
hintString = keyHintString != null && valueHintString != null ? $"{keyHintString};{valueHintString}" : null;
return hintString != null;
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
index 0dda43ab4c..702c50d461 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs
@@ -282,7 +282,7 @@ namespace Godot.SourceGenerators
.Append(" -= value;\n")
.Append("}\n");
- // Generate On{EventName} method to raise the event
+ // Generate EmitSignal{EventName} method to raise the event
var invokeMethodSymbol = signalDelegate.InvokeMethodData.Method;
int paramCount = invokeMethodSymbol.Parameters.Length;
@@ -291,7 +291,7 @@ namespace Godot.SourceGenerators
"private" :
"protected";
- source.Append($" {raiseMethodModifiers} void On{signalName}(");
+ source.Append($" {raiseMethodModifiers} void EmitSignal{signalName}(");
for (int i = 0; i < paramCount; i++)
{
var paramSymbol = invokeMethodSymbol.Parameters[i];
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 946e997c1b..e97229c621 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -3275,10 +3275,10 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output.append(CLOSE_BLOCK_L1);
- // Generate On{EventName} method to raise the event.
+ // Generate EmitSignal{EventName} method to raise the event.
if (!p_itype.is_singleton) {
p_output.append(MEMBER_BEGIN "protected void ");
- p_output << "On" << p_isignal.proxy_name;
+ p_output << "EmitSignal" << p_isignal.proxy_name;
if (is_parameterless) {
p_output.append("()\n" OPEN_BLOCK_L1 INDENT2);
p_output << "EmitSignal(SignalName." << p_isignal.proxy_name << ");\n";
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index a1f32fccbe..012ef7860d 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1602,19 +1602,16 @@ Ref<CameraAttributes> LightmapGI::get_camera_attributes() const {
PackedStringArray LightmapGI::get_configuration_warnings() const {
PackedStringArray warnings = VisualInstance3D::get_configuration_warnings();
-#ifndef MODULE_LIGHTMAPPER_RD_ENABLED
-#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
- warnings.push_back(vformat(RTR("Lightmaps cannot be baked on %s. Rendering existing baked lightmaps will still work."), OS::get_singleton()->get_name()));
-#else
- warnings.push_back(RTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time. Rendering existing baked lightmaps will still work."));
-#endif
- return warnings;
-#endif
-
+#ifdef MODULE_LIGHTMAPPER_RD_ENABLED
if (!DisplayServer::get_singleton()->can_create_rendering_device()) {
warnings.push_back(vformat(RTR("Lightmaps can only be baked from a GPU that supports the RenderingDevice backends.\nYour GPU (%s) does not support RenderingDevice, as it does not support Vulkan, Direct3D 12, or Metal.\nLightmap baking will not be available on this device, although rendering existing baked lightmaps will work."), RenderingServer::get_singleton()->get_video_adapter_name()));
return warnings;
}
+#elif defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
+ warnings.push_back(vformat(RTR("Lightmaps cannot be baked on %s. Rendering existing baked lightmaps will still work."), OS::get_singleton()->get_name()));
+#else
+ warnings.push_back(RTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time. Rendering existing baked lightmaps will still work."));
+#endif
return warnings;
}
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index fe4c91cb56..e92f979c32 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -245,21 +245,7 @@ void ColorPicker::finish_shaders() {
}
void ColorPicker::set_focus_on_line_edit() {
- bool has_hardware_keyboard = true;
-#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
- has_hardware_keyboard = DisplayServer::get_singleton()->has_hardware_keyboard();
-#endif // ANDROID_ENABLED || IOS_ENABLED
- if (has_hardware_keyboard) {
- callable_mp((Control *)c_text, &Control::grab_focus).call_deferred();
- } else {
- // A hack to avoid showing the virtual keyboard when the ColorPicker window popups and
- // no hardware keyboard is detected on Android and IOS.
- // This will only focus the LineEdit without editing, the virtual keyboard will only be visible when
- // we touch the LineEdit to enter edit mode.
- callable_mp(c_text, &LineEdit::set_editable).call_deferred(false);
- callable_mp((Control *)c_text, &Control::grab_focus).call_deferred();
- callable_mp(c_text, &LineEdit::set_editable).call_deferred(true);
- }
+ callable_mp((Control *)c_text, &Control::grab_focus).call_deferred();
}
void ColorPicker::_update_controls() {
@@ -2103,7 +2089,9 @@ void ColorPickerButton::pressed() {
float v_offset = show_above ? -minsize.y : get_size().y;
popup->set_position(get_screen_position() + Vector2(h_offset, v_offset));
popup->popup();
- picker->set_focus_on_line_edit();
+ if (DisplayServer::get_singleton()->has_hardware_keyboard()) {
+ picker->set_focus_on_line_edit();
+ }
}
void ColorPickerButton::_notification(int p_what) {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index c1d197ea9b..5052deb65a 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -3042,7 +3042,7 @@ void Control::set_layout_direction(Control::LayoutDirection p_direction) {
if (data.layout_dir == p_direction) {
return;
}
- ERR_FAIL_INDEX((int)p_direction, 4);
+ ERR_FAIL_INDEX(p_direction, LAYOUT_DIRECTION_MAX);
data.layout_dir = p_direction;
@@ -3115,13 +3115,20 @@ bool Control::is_layout_rtl() const {
String locale = TranslationServer::get_singleton()->get_tool_locale();
const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
}
- } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
+ } else if (data.layout_dir == LAYOUT_DIRECTION_APPLICATION_LOCALE) {
if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
const_cast<Control *>(this)->data.is_rtl = true;
} else {
String locale = TranslationServer::get_singleton()->get_tool_locale();
const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
}
+ } else if (data.layout_dir == LAYOUT_DIRECTION_SYSTEM_LOCALE) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ const_cast<Control *>(this)->data.is_rtl = true;
+ } else {
+ String locale = OS::get_singleton()->get_locale();
+ const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ }
} else {
const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL);
}
@@ -3574,7 +3581,7 @@ void Control::_bind_methods() {
ADD_GROUP("Layout", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Based on Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Based on Application Locale,Left-to-Right,Right-to-Left,Based on System Locale"), "set_layout_direction", "get_layout_direction");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode");
ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION);
@@ -3723,9 +3730,14 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(ANCHOR_END);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED);
- BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_APPLICATION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL);
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_SYSTEM_LOCALE);
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_MAX);
+#ifndef DISABLE_DEPRECATED
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
+#endif // DISABLE_DEPRECATED
BIND_ENUM_CONSTANT(TEXT_DIRECTION_INHERITED);
BIND_ENUM_CONSTANT(TEXT_DIRECTION_AUTO);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 6e1621ce58..6cabf10971 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -140,9 +140,14 @@ public:
enum LayoutDirection {
LAYOUT_DIRECTION_INHERITED,
- LAYOUT_DIRECTION_LOCALE,
+ LAYOUT_DIRECTION_APPLICATION_LOCALE,
LAYOUT_DIRECTION_LTR,
- LAYOUT_DIRECTION_RTL
+ LAYOUT_DIRECTION_RTL,
+ LAYOUT_DIRECTION_SYSTEM_LOCALE,
+ LAYOUT_DIRECTION_MAX,
+#ifndef DISABLE_DEPRECATED
+ LAYOUT_DIRECTION_LOCALE = LAYOUT_DIRECTION_APPLICATION_LOCALE,
+#endif // DISABLE_DEPRECATED
};
enum TextDirection {
diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp
index 46c9c7cccc..9853d699d4 100644
--- a/scene/gui/menu_bar.cpp
+++ b/scene/gui/menu_bar.cpp
@@ -510,6 +510,7 @@ void MenuBar::_refresh_menu_names() {
if (!popups[i]->has_meta("_menu_name") && String(popups[i]->get_name()) != get_menu_title(i)) {
menu_cache.write[i].name = popups[i]->get_name();
shape(menu_cache.write[i]);
+ queue_redraw();
if (is_global && menu_cache[i].submenu_rid.is_valid()) {
int item_idx = nmenu->find_item_index_with_submenu(main_menu, menu_cache[i].submenu_rid);
if (item_idx >= 0) {
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 803ce89bc9..1b2025ca78 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -2635,7 +2635,7 @@ void Window::set_unparent_when_invisible(bool p_unparent) {
void Window::set_layout_direction(Window::LayoutDirection p_direction) {
ERR_MAIN_THREAD_GUARD;
- ERR_FAIL_INDEX((int)p_direction, 4);
+ ERR_FAIL_INDEX(p_direction, LAYOUT_DIRECTION_MAX);
layout_dir = p_direction;
propagate_notification(Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED);
@@ -2700,13 +2700,20 @@ bool Window::is_layout_rtl() const {
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
- } else if (layout_dir == LAYOUT_DIRECTION_LOCALE) {
+ } else if (layout_dir == LAYOUT_DIRECTION_APPLICATION_LOCALE) {
if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
return true;
} else {
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
+ } else if (layout_dir == LAYOUT_DIRECTION_SYSTEM_LOCALE) {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ return true;
+ } else {
+ String locale = OS::get_singleton()->get_locale();
+ return TS->is_locale_right_to_left(locale);
+ }
} else {
return (layout_dir == LAYOUT_DIRECTION_RTL);
}
@@ -3070,9 +3077,14 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(CONTENT_SCALE_STRETCH_INTEGER);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED);
- BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_APPLICATION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL);
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_SYSTEM_LOCALE);
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_MAX);
+#ifndef DISABLE_DEPRECATED
+ BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
+#endif // DISABLE_DEPRECATED
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_ABSOLUTE);
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_PRIMARY_SCREEN);
diff --git a/scene/main/window.h b/scene/main/window.h
index 47aaf73728..c2937d6168 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -86,9 +86,14 @@ public:
enum LayoutDirection {
LAYOUT_DIRECTION_INHERITED,
- LAYOUT_DIRECTION_LOCALE,
+ LAYOUT_DIRECTION_APPLICATION_LOCALE,
LAYOUT_DIRECTION_LTR,
- LAYOUT_DIRECTION_RTL
+ LAYOUT_DIRECTION_RTL,
+ LAYOUT_DIRECTION_SYSTEM_LOCALE,
+ LAYOUT_DIRECTION_MAX,
+#ifndef DISABLE_DEPRECATED
+ LAYOUT_DIRECTION_LOCALE = LAYOUT_DIRECTION_APPLICATION_LOCALE,
+#endif // DISABLE_DEPRECATED
};
enum {
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 24d17108d5..d163a42fa9 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -32,6 +32,7 @@
#include "shader.compat.inc"
#include "core/io/file_access.h"
+#include "scene/main/scene_tree.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/shader_preprocessor.h"
#include "servers/rendering_server.h"
@@ -138,6 +139,14 @@ String Shader::get_code() const {
return code;
}
+void Shader::inspect_native_shader_code() {
+ SceneTree *st = SceneTree::get_singleton();
+ RID _shader = get_rid();
+ if (st && _shader.is_valid()) {
+ st->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_native_shader_source_visualizer", "_inspect_shader", _shader);
+ }
+}
+
void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups) const {
_update_shader();
_check_shader_rid();
@@ -267,6 +276,9 @@ void Shader::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_shader_uniform_list", "get_groups"), &Shader::_get_shader_uniform_list, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("inspect_native_shader_code"), &Shader::inspect_native_shader_code);
+ ClassDB::set_method_flags(get_class_static(), _scs_create("inspect_native_shader_code"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+
ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code");
BIND_ENUM_CONSTANT(MODE_SPATIAL);
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index 18197419f3..7234d37579 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -88,6 +88,8 @@ public:
void set_code(const String &p_code);
String get_code() const;
+ void inspect_native_shader_code();
+
void get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups = false) const;
void set_default_texture_parameter(const StringName &p_name, const Ref<Texture> &p_texture, int p_index = 0);
diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index a797891ab6..90bbdfe685 100644
--- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -513,6 +513,7 @@ void main() {
shadow_sample.z = 1.0 + abs(shadow_sample.z);
vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - omni_lights.data[light_index].shadow_bias);
pos.z *= omni_lights.data[light_index].inv_radius;
+ pos.z = 1.0 - pos.z;
pos.xy = pos.xy * 0.5 + 0.5;
pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 8b7ec08868..ca07444465 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1998,6 +1998,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
}
pair.cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base);
+ } else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+ pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
+ pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) {
pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index aee23ab476..942d5631e4 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -1243,6 +1243,7 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
TransferWorker *transfer_worker = nullptr;
const uint8_t *read_ptr = p_data.ptr();
uint8_t *write_ptr = nullptr;
+ const RDD::TextureLayout copy_dst_layout = driver->api_trait_get(RDD::API_TRAIT_USE_GENERAL_IN_COPY_QUEUES) ? RDD::TEXTURE_LAYOUT_GENERAL : RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
for (uint32_t pass = 0; pass < 2; pass++) {
const bool copy_pass = (pass == 1);
if (copy_pass) {
@@ -1267,7 +1268,7 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
tb.texture = texture->driver_id;
tb.dst_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
- tb.next_layout = RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
+ tb.next_layout = copy_dst_layout;
tb.subresources.aspect = texture->barrier_aspect_flags;
tb.subresources.mipmap_count = texture->mipmaps;
tb.subresources.base_layer = p_layer;
@@ -1313,7 +1314,7 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
copy_region.texture_subresources.layer_count = 1;
copy_region.texture_offset = Vector3i(0, 0, z);
copy_region.texture_region_size = Vector3i(logic_width, logic_height, 1);
- driver->command_copy_buffer_to_texture(transfer_worker->command_buffer, transfer_worker->staging_buffer, texture->driver_id, RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL, copy_region);
+ driver->command_copy_buffer_to_texture(transfer_worker->command_buffer, transfer_worker->staging_buffer, texture->driver_id, copy_dst_layout, copy_region);
}
staging_local_offset += to_allocate;
@@ -1332,14 +1333,13 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
RDD::TextureBarrier tb;
tb.texture = texture->driver_id;
tb.src_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
- tb.prev_layout = RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
+ tb.prev_layout = copy_dst_layout;
tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
tb.subresources.aspect = texture->barrier_aspect_flags;
tb.subresources.mipmap_count = texture->mipmaps;
tb.subresources.base_layer = p_layer;
tb.subresources.layer_count = 1;
-
- driver->command_pipeline_barrier(transfer_worker->command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, {}, tb);
+ transfer_worker->texture_barriers.push_back(tb);
}
_release_transfer_worker(transfer_worker);
@@ -5152,6 +5152,21 @@ void RenderingDevice::_wait_for_transfer_worker(TransferWorker *p_transfer_worke
MutexLock lock(p_transfer_worker->operations_mutex);
p_transfer_worker->operations_processed = p_transfer_worker->operations_submitted;
}
+
+ if (!p_transfer_worker->texture_barriers.is_empty()) {
+ MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
+ _flush_barriers_for_transfer_worker(p_transfer_worker);
+ }
+}
+
+void RenderingDevice::_flush_barriers_for_transfer_worker(TransferWorker *p_transfer_worker) {
+ if (!p_transfer_worker->texture_barriers.is_empty()) {
+ for (uint32_t i = 0; i < p_transfer_worker->texture_barriers.size(); i++) {
+ transfer_worker_pool_texture_barriers.push_back(p_transfer_worker->texture_barriers[i]);
+ }
+
+ p_transfer_worker->texture_barriers.clear();
+ }
}
void RenderingDevice::_check_transfer_worker_operation(uint32_t p_transfer_worker_index, uint64_t p_transfer_worker_operation) {
@@ -5193,11 +5208,11 @@ void RenderingDevice::_check_transfer_worker_index_array(IndexArray *p_index_arr
}
}
-void RenderingDevice::_submit_transfer_workers(bool p_operations_used_by_draw) {
+void RenderingDevice::_submit_transfer_workers(RDD::CommandBufferID p_draw_command_buffer) {
MutexLock transfer_worker_lock(transfer_worker_pool_mutex);
for (uint32_t i = 0; i < transfer_worker_pool.size(); i++) {
TransferWorker *worker = transfer_worker_pool[i];
- if (p_operations_used_by_draw) {
+ if (p_draw_command_buffer) {
MutexLock lock(worker->operations_mutex);
if (worker->operations_processed >= transfer_worker_operation_used_by_draw[worker->index]) {
// The operation used by the draw has already been processed, we don't need to wait on the worker.
@@ -5208,12 +5223,21 @@ void RenderingDevice::_submit_transfer_workers(bool p_operations_used_by_draw) {
{
MutexLock lock(worker->thread_mutex);
if (worker->recording) {
- VectorView<RDD::SemaphoreID> semaphores = p_operations_used_by_draw ? frames[frame].transfer_worker_semaphores[i] : VectorView<RDD::SemaphoreID>();
+ VectorView<RDD::SemaphoreID> semaphores = p_draw_command_buffer ? frames[frame].transfer_worker_semaphores[i] : VectorView<RDD::SemaphoreID>();
_end_transfer_worker(worker);
_submit_transfer_worker(worker, semaphores);
}
+
+ if (p_draw_command_buffer) {
+ _flush_barriers_for_transfer_worker(worker);
+ }
}
}
+
+ if (p_draw_command_buffer && !transfer_worker_pool_texture_barriers.is_empty()) {
+ driver->command_pipeline_barrier(p_draw_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, {}, {}, transfer_worker_pool_texture_barriers);
+ transfer_worker_pool_texture_barriers.clear();
+ }
}
void RenderingDevice::_wait_for_transfer_workers() {
@@ -5807,10 +5831,10 @@ 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).");
}
- _submit_transfer_workers(true);
-
// 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].command_buffer;
+ _submit_transfer_workers(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();
@@ -6387,7 +6411,7 @@ void RenderingDevice::finalize() {
}
// Wait for transfer workers to finish.
- _submit_transfer_workers(false);
+ _submit_transfer_workers();
_wait_for_transfer_workers();
// Delete everything the graph has created.
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index b61418b1fc..71ffbfbd88 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1267,6 +1267,7 @@ private:
RDD::CommandBufferID command_buffer;
RDD::CommandPoolID command_pool;
RDD::FenceID command_fence;
+ LocalVector<RDD::TextureBarrier> texture_barriers;
bool recording = false;
bool submitted = false;
BinaryMutex thread_mutex;
@@ -1280,6 +1281,7 @@ private:
uint32_t transfer_worker_pool_max_size = 1;
LocalVector<uint64_t> transfer_worker_operation_used_by_draw;
LocalVector<uint32_t> transfer_worker_pool_available_list;
+ LocalVector<RDD::TextureBarrier> transfer_worker_pool_texture_barriers;
BinaryMutex transfer_worker_pool_mutex;
ConditionVariable transfer_worker_pool_condition;
@@ -1288,12 +1290,13 @@ private:
void _end_transfer_worker(TransferWorker *p_transfer_worker);
void _submit_transfer_worker(TransferWorker *p_transfer_worker, VectorView<RDD::SemaphoreID> p_signal_semaphores = VectorView<RDD::SemaphoreID>());
void _wait_for_transfer_worker(TransferWorker *p_transfer_worker);
+ void _flush_barriers_for_transfer_worker(TransferWorker *p_transfer_worker);
void _check_transfer_worker_operation(uint32_t p_transfer_worker_index, uint64_t p_transfer_worker_operation);
void _check_transfer_worker_buffer(Buffer *p_buffer);
void _check_transfer_worker_texture(Texture *p_texture);
void _check_transfer_worker_vertex_array(VertexArray *p_vertex_array);
void _check_transfer_worker_index_array(IndexArray *p_index_array);
- void _submit_transfer_workers(bool p_operations_used_by_draw);
+ void _submit_transfer_workers(RDD::CommandBufferID p_draw_command_buffer = RDD::CommandBufferID());
void _wait_for_transfer_workers();
void _free_transfer_workers();
diff --git a/servers/rendering/rendering_device_driver.cpp b/servers/rendering/rendering_device_driver.cpp
index 3b8e3efeb8..9ff7b83215 100644
--- a/servers/rendering/rendering_device_driver.cpp
+++ b/servers/rendering/rendering_device_driver.cpp
@@ -374,6 +374,8 @@ uint64_t RenderingDeviceDriver::api_trait_get(ApiTrait p_trait) {
return 1;
case API_TRAIT_CLEARS_WITH_COPY_ENGINE:
return true;
+ case API_TRAIT_USE_GENERAL_IN_COPY_QUEUES:
+ return false;
default:
ERR_FAIL_V(0);
}
diff --git a/servers/rendering/rendering_device_driver.h b/servers/rendering/rendering_device_driver.h
index 91da67c8d7..637d52c060 100644
--- a/servers/rendering/rendering_device_driver.h
+++ b/servers/rendering/rendering_device_driver.h
@@ -220,6 +220,7 @@ public:
enum TextureLayout {
TEXTURE_LAYOUT_UNDEFINED,
+ TEXTURE_LAYOUT_GENERAL,
TEXTURE_LAYOUT_STORAGE_OPTIMAL,
TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
@@ -750,6 +751,7 @@ public:
API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP,
API_TRAIT_SECONDARY_VIEWPORT_SCISSOR,
API_TRAIT_CLEARS_WITH_COPY_ENGINE,
+ API_TRAIT_USE_GENERAL_IN_COPY_QUEUES,
};
enum ShaderChangeInvalidation {
diff --git a/tests/core/variant/test_variant.h b/tests/core/variant/test_variant.h
index be615975f8..599a282b20 100644
--- a/tests/core/variant/test_variant.h
+++ b/tests/core/variant/test_variant.h
@@ -1806,6 +1806,14 @@ TEST_CASE("[Variant] Writer and parser dictionary") {
CHECK_MESSAGE(d_parsed == Variant(d), "Should parse back.");
}
+TEST_CASE("[Variant] Writer key sorting") {
+ Dictionary d = build_dictionary(StringName("C"), 3, "A", 1, StringName("B"), 2, "D", 4);
+ String d_str;
+ VariantWriter::write_to_string(d, d_str);
+
+ CHECK_EQ(d_str, "{\n\"A\": 1,\n&\"B\": 2,\n&\"C\": 3,\n\"D\": 4\n}");
+}
+
TEST_CASE("[Variant] Writer recursive dictionary") {
// There is no way to accurately represent a recursive dictionary,
// the only thing we can do is make sure the writer doesn't blow up