summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp31
-rw-r--r--drivers/gles3/storage/mesh_storage.h3
-rw-r--r--drivers/gles3/storage/utilities.cpp5
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.cpp29
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();
}