summaryrefslogtreecommitdiff
path: root/vulkan/libvulkan/swapchain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vulkan/libvulkan/swapchain.cpp')
-rw-r--r--vulkan/libvulkan/swapchain.cpp151
1 files changed, 74 insertions, 77 deletions
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 271558784e..d3ed88d2eb 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -258,11 +258,7 @@ struct Swapchain {
bool shared;
struct Image {
- Image()
- : image(VK_NULL_HANDLE),
- dequeue_fence(-1),
- release_fence(-1),
- dequeued(false) {}
+ Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
VkImage image;
android::sp<ANativeWindowBuffer> buffer;
// The fence is only valid when the buffer is dequeued, and should be
@@ -270,10 +266,6 @@ struct Swapchain {
// closed: either by closing it explicitly when queueing the buffer,
// or by passing ownership e.g. to ANativeWindow::cancelBuffer().
int dequeue_fence;
- // This fence is a dup of the sync fd returned from the driver via
- // vkQueueSignalReleaseImageANDROID upon vkQueuePresentKHR. We must
- // ensure it is closed upon re-presenting or releasing the image.
- int release_fence;
bool dequeued;
} images[android::BufferQueueDefs::NUM_BUFFER_SLOTS];
@@ -288,19 +280,10 @@ Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
return reinterpret_cast<Swapchain*>(handle);
}
-static bool IsFencePending(int fd) {
- if (fd < 0)
- return false;
-
- errno = 0;
- return sync_wait(fd, 0 /* timeout */) == -1 && errno == ETIME;
-}
-
void ReleaseSwapchainImage(VkDevice device,
ANativeWindow* window,
int release_fence,
- Swapchain::Image& image,
- bool defer_if_pending) {
+ Swapchain::Image& image) {
ATRACE_CALL();
ALOG_ASSERT(release_fence == -1 || image.dequeued,
@@ -336,16 +319,8 @@ void ReleaseSwapchainImage(VkDevice device,
close(release_fence);
}
}
- release_fence = -1;
- image.dequeued = false;
- }
-
- if (defer_if_pending && IsFencePending(image.release_fence))
- return;
- if (image.release_fence >= 0) {
- close(image.release_fence);
- image.release_fence = -1;
+ image.dequeued = false;
}
if (image.image) {
@@ -363,8 +338,7 @@ void OrphanSwapchain(VkDevice device, Swapchain* swapchain) {
return;
for (uint32_t i = 0; i < swapchain->num_images; i++) {
if (!swapchain->images[i].dequeued)
- ReleaseSwapchainImage(device, nullptr, -1, swapchain->images[i],
- true);
+ ReleaseSwapchainImage(device, nullptr, -1, swapchain->images[i]);
}
swapchain->surface.swapchain_handle = VK_NULL_HANDLE;
swapchain->timing.clear();
@@ -537,30 +511,6 @@ android_dataspace GetNativeDataspace(VkColorSpaceKHR colorspace) {
}
}
-int get_min_buffer_count(ANativeWindow* window,
- uint32_t* out_min_buffer_count) {
- constexpr int kExtraBuffers = 2;
-
- int err;
- int min_undequeued_buffers;
- err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- &min_undequeued_buffers);
- if (err != android::OK || min_undequeued_buffers < 0) {
- ALOGE(
- "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
- "value=%d",
- strerror(-err), err, min_undequeued_buffers);
- if (err == android::OK) {
- err = android::UNKNOWN_ERROR;
- }
- return err;
- }
-
- *out_min_buffer_count =
- static_cast<uint32_t>(min_undequeued_buffers + kExtraBuffers);
- return android::OK;
-}
-
} // anonymous namespace
VKAPI_ATTR
@@ -630,9 +580,44 @@ void DestroySurfaceKHR(VkInstance instance,
VKAPI_ATTR
VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
uint32_t /*queue_family*/,
- VkSurfaceKHR /*surface_handle*/,
+ VkSurfaceKHR surface_handle,
VkBool32* supported) {
- *supported = VK_TRUE;
+ ATRACE_CALL();
+
+ const Surface* surface = SurfaceFromHandle(surface_handle);
+ if (!surface) {
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ const ANativeWindow* window = surface->window.get();
+
+ int query_value;
+ int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
+ if (err != android::OK || query_value < 0) {
+ ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
+ strerror(-err), err, query_value);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+
+ android_pixel_format native_format =
+ static_cast<android_pixel_format>(query_value);
+
+ bool format_supported = false;
+ switch (native_format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ format_supported = true;
+ break;
+ default:
+ break;
+ }
+
+ *supported = static_cast<VkBool32>(
+ format_supported || (surface->consumer_usage &
+ (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
+ AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
+
return VK_SUCCESS;
}
@@ -872,13 +857,15 @@ VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
int err;
int query_value;
- uint32_t min_buffer_count;
ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
- err = get_min_buffer_count(window, &min_buffer_count);
- if (err != android::OK) {
+ err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
+ if (err != android::OK || query_value < 0) {
+ ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) value=%d",
+ strerror(-err), err, query_value);
return VK_ERROR_SURFACE_LOST_KHR;
}
+ uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
if (err != android::OK || query_value < 0) {
@@ -889,15 +876,16 @@ VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev,
uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
std::vector<VkPresentModeKHR> present_modes;
- if (min_buffer_count < max_buffer_count)
+ if (min_undequeued_buffers + 1 < max_buffer_count)
present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
VkPhysicalDevicePresentationPropertiesANDROID present_properties;
- QueryPresentationProperties(pdev, &present_properties);
- if (present_properties.sharedImage) {
- present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
- present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
+ if (QueryPresentationProperties(pdev, &present_properties)) {
+ if (present_properties.sharedImage) {
+ present_modes.push_back(VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR);
+ present_modes.push_back(VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR);
+ }
}
uint32_t num_modes = uint32_t(present_modes.size());
@@ -982,6 +970,7 @@ VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,
strerror(-err), err);
}
+ // TODO(b/143294545): Return something better than "whole window"
pRects[0].offset.x = 0;
pRects[0].offset.y = 0;
pRects[0].extent = VkExtent2D{static_cast<uint32_t>(width),
@@ -1009,7 +998,7 @@ static void DestroySwapchainInternal(VkDevice device,
}
for (uint32_t i = 0; i < swapchain->num_images; i++) {
- ReleaseSwapchainImage(device, window, -1, swapchain->images[i], false);
+ ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
}
if (active) {
@@ -1108,14 +1097,20 @@ VkResult CreateSwapchainKHR(VkDevice device,
ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)",
strerror(-err), err);
- err =
- window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1});
+ err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, -1);
if (err != android::OK) {
ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)",
strerror(-err), err);
return VK_ERROR_SURFACE_LOST_KHR;
}
+ err = native_window_set_buffer_count(window, 0);
+ if (err != android::OK) {
+ ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
+ strerror(-err), err);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+
int swap_interval =
create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
err = window->setSwapInterval(window, swap_interval);
@@ -1210,14 +1205,19 @@ VkResult CreateSwapchainKHR(VkDevice device,
}
}
- uint32_t min_buffer_count;
- err = get_min_buffer_count(window, &min_buffer_count);
- if (err != android::OK) {
+ int query_value;
+ err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &query_value);
+ if (err != android::OK || query_value < 0) {
+ ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
+ query_value);
return VK_ERROR_SURFACE_LOST_KHR;
}
-
+ uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
uint32_t num_images =
- std::max(min_buffer_count, create_info->minImageCount);
+ (swap_interval ? create_info->minImageCount
+ : std::max(3u, create_info->minImageCount)) -
+ 1 + min_undequeued_buffers;
// Lower layer insists that we have at least two buffers. This is wasteful
// and we'd like to relax it in the shared case, but not all the pieces are
@@ -1630,9 +1630,6 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
swapchain_result = result;
}
- if (img.release_fence >= 0)
- close(img.release_fence);
- img.release_fence = fence < 0 ? -1 : dup(fence);
if (swapchain.surface.swapchain_handle ==
present_info->pSwapchains[sc]) {
@@ -1718,7 +1715,7 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
if (err != android::OK) {
ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
swapchain_result = WorstPresentResult(
- swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
+ swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
} else {
if (img.dequeue_fence >= 0) {
close(img.dequeue_fence);
@@ -1766,7 +1763,7 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
}
} else {
- ReleaseSwapchainImage(device, nullptr, fence, img, true);
+ ReleaseSwapchainImage(device, nullptr, fence, img);
swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;
}