diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gles3/storage/mesh_storage.cpp | 31 | ||||
| -rw-r--r-- | drivers/gles3/storage/mesh_storage.h | 3 | ||||
| -rw-r--r-- | drivers/gles3/storage/utilities.cpp | 5 | ||||
| -rw-r--r-- | drivers/vulkan/rendering_device_driver_vulkan.cpp | 29 |
4 files changed, 52 insertions, 16 deletions
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 928e4e23ce..6c4bef10d5 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1607,6 +1607,9 @@ void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, b void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { ERR_FAIL_COND(multimesh->mesh.is_null()); + if (multimesh->custom_aabb != AABB()) { + return; + } AABB aabb; AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); for (int i = 0; i < p_instances; i++) { @@ -1749,9 +1752,25 @@ RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const { return multimesh->mesh; } +void MeshStorage::multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_NULL(multimesh); + multimesh->custom_aabb = p_aabb; + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); +} + +AABB MeshStorage::multimesh_get_custom_aabb(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_NULL_V(multimesh, AABB()); + return multimesh->custom_aabb; +} + AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_NULL_V(multimesh, AABB()); + if (multimesh->custom_aabb != AABB()) { + return multimesh->custom_aabb; + } if (multimesh->aabb_dirty) { const_cast<MeshStorage *>(this)->_update_dirty_multimeshes(); } @@ -1943,8 +1962,10 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b //if we have a mesh set, we need to re-generate the AABB from the new data const float *data = p_buffer.ptr(); - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); + if (multimesh->custom_aabb != AABB()) { + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); + } } } @@ -2091,9 +2112,11 @@ void MeshStorage::_update_dirty_multimeshes() { } if (multimesh->aabb_dirty && multimesh->mesh.is_valid()) { - _multimesh_re_create_aabb(multimesh, data, visible_instances); multimesh->aabb_dirty = false; - multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); + if (multimesh->custom_aabb != AABB()) { + _multimesh_re_create_aabb(multimesh, data, visible_instances); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); + } } } diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index cea81baa0b..d246e7725c 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -189,6 +189,7 @@ struct MultiMesh { bool uses_custom_data = false; int visible_instances = -1; AABB aabb; + AABB custom_aabb; bool aabb_dirty = false; bool buffer_set = false; uint32_t stride_cache = 0; @@ -505,6 +506,8 @@ public: virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override; virtual RID multimesh_get_mesh(RID p_multimesh) const override; + virtual void multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override; + virtual AABB multimesh_get_custom_aabb(RID p_multimesh) const override; virtual AABB multimesh_get_aabb(RID p_multimesh) const override; virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override; diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp index 8a9e61c725..793b3f64f0 100644 --- a/drivers/gles3/storage/utilities.cpp +++ b/drivers/gles3/storage/utilities.cpp @@ -355,19 +355,16 @@ bool Utilities::has_os_feature(const String &p_feature) const { if (p_feature == "rgtc") { return config->rgtc_supported; } - if (p_feature == "s3tc") { return config->s3tc_supported; } - if (p_feature == "bptc") { return config->bptc_supported; } if (p_feature == "astc") { return config->astc_supported; } - - if (p_feature == "etc" || p_feature == "etc2") { + if (p_feature == "etc2") { return config->etc2_supported; } diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index 1eab2922d1..f48e6eb7ed 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -2244,19 +2244,31 @@ Error RenderingDeviceDriverVulkan::command_queue_present(CommandQueueID p_cmd_qu for (uint32_t i = 0; i < p_swap_chains.size(); i++) { SwapChain *swap_chain = (SwapChain *)(p_swap_chains[i].id); swap_chain->image_index = UINT_MAX; - if (results[i] == VK_ERROR_OUT_OF_DATE_KHR || results[i] == VK_SUBOPTIMAL_KHR) { + if (results[i] == VK_ERROR_OUT_OF_DATE_KHR) { context_driver->surface_set_needs_resize(swap_chain->surface, true); any_result_is_out_of_date = true; } } - if (any_result_is_out_of_date || err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { + if (any_result_is_out_of_date || err == VK_ERROR_OUT_OF_DATE_KHR) { // It is possible for presentation to fail with out of date while acquire might've succeeded previously. This case // will be considered a silent failure as it can be triggered easily by resizing a window in the OS natively. return FAILED; } - ERR_FAIL_COND_V(err != VK_SUCCESS, FAILED); + // Handling VK_SUBOPTIMAL_KHR the same as VK_SUCCESS is completely intentional. + // + // Godot does not currently support native rotation in Android when creating the swap chain. It intentionally uses + // VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR instead of the current transform bits available in the surface capabilities. + // Choosing the transform that leads to optimal presentation leads to distortion that makes the application unusable, + // as the rotation of all the content is not handled at the moment. + // + // VK_SUBOPTIMAL_KHR is accepted as a successful case even if it's not the most efficient solution to work around this + // problem. This behavior should not be changed unless the swap chain recreation uses the current transform bits, as + // it'll lead to very low performance in Android by entering an endless loop where it'll always resize the swap chain + // every frame. + + ERR_FAIL_COND_V(err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR, FAILED); return OK; } @@ -2581,6 +2593,8 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue, } // Prefer identity transform if it's supported, use the current transform otherwise. + // This behavior is intended as Godot does not supported native rotation in platforms that use these bits. + // Refer to the comment in command_queue_present() for more details. VkSurfaceTransformFlagBitsKHR surface_transform_bits; if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { surface_transform_bits = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; @@ -2718,18 +2732,17 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(C swap_chain->command_queues_acquired_semaphores.push_back(semaphore_index); err = device_functions.AcquireNextImageKHR(vk_device, swap_chain->vk_swapchain, UINT64_MAX, semaphore, VK_NULL_HANDLE, &swap_chain->image_index); - if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { - // We choose to treat out of date and suboptimal as the same case, as they both need to be recreated and - // we don't get much use out of presenting a suboptimal image anyway. Either case leaves the semaphore in - // a signaled state that will never finish, so it's necessary to recreate it. + if (err == VK_ERROR_OUT_OF_DATE_KHR) { + // Out of date leaves the semaphore in a signaled state that will never finish, so it's necessary to recreate it. bool semaphore_recreated = _recreate_image_semaphore(command_queue, semaphore_index, true); ERR_FAIL_COND_V(!semaphore_recreated, FramebufferID()); // Swap chain is out of date and must be recreated. r_resize_required = true; return FramebufferID(); - } else if (err != VK_SUCCESS) { + } else if (err != VK_SUCCESS && err != VK_SUBOPTIMAL_KHR) { // Swap chain failed to present but the reason is unknown. + // Refer to the comment in command_queue_present() as to why VK_SUBOPTIMAL_KHR is handled the same as VK_SUCCESS. return FramebufferID(); } |
