diff options
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 |