swapchain.cpp revision 0e74f00af03b7e705774d0dcf69c2ba8ce7a15a8
1b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall/* 2b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * Copyright 2015 The Android Open Source Project 3b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * 4b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * Licensed under the Apache License, Version 2.0 (the "License"); 5b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * you may not use this file except in compliance with the License. 6b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * You may obtain a copy of the License at 7b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * 8b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * http://www.apache.org/licenses/LICENSE-2.0 9b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * 10b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * Unless required by applicable law or agreed to in writing, software 11b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * distributed under the License is distributed on an "AS IS" BASIS, 12b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * See the License for the specific language governing permissions and 14b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall * limitations under the License. 15b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall */ 16b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 17d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// #define LOG_NDEBUG 0 18d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 19d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <algorithm> 20d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <memory> 21d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 22d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <gui/BufferQueue.h> 23b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall#include <log/log.h> 24d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include <sync/sync.h> 25d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 26d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#include "loader.h" 27d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 28d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallusing namespace vulkan; 29d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 305ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// TODO(jessehall): Currently we don't have a good error code for when a native 315ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// window operation fails. Just returning INITIALIZATION_FAILED for now. Later 325ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// versions (post SDK 0.9) of the API/extension have a better error code. 335ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall// When updating to that version, audit all error returns. 345ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall 35d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallnamespace { 36d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 37d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ---------------------------------------------------------------------------- 38d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// These functions/classes form an adaptor that allows objects to be refcounted 39d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// by both android::sp<> and std::shared_ptr<> simultaneously, and delegates 403fbc856120217247c72fb5ed88500000f3881c45Jesse Hall// allocation of the shared_ptr<> control structure to VkAllocationCallbacks. 413fbc856120217247c72fb5ed88500000f3881c45Jesse Hall// The 42d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// platform holds a reference to the ANativeWindow using its embedded reference 43d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// count, and the ANativeWindow implementation holds references to the 44d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ANativeWindowBuffers using their embedded reference counts, so the 45d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// shared_ptr *must* cooperate with these and hold at least one reference to 46d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// the object using the embedded reference count. 47d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 48d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Halltemplate <typename T> 49d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallstruct NativeBaseDeleter { 50d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall void operator()(T* obj) { obj->common.decRef(&obj->common); } 51d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}; 52d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 5303b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Halltemplate <typename Host> 5403b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hallstruct AllocScope {}; 5503b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall 5603b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Halltemplate <> 5703b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hallstruct AllocScope<VkInstance> { 583fbc856120217247c72fb5ed88500000f3881c45Jesse Hall static const VkSystemAllocationScope kScope = 593fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE; 6003b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall}; 6103b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall 6203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Halltemplate <> 6303b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hallstruct AllocScope<VkDevice> { 643fbc856120217247c72fb5ed88500000f3881c45Jesse Hall static const VkSystemAllocationScope kScope = 653fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_SYSTEM_ALLOCATION_SCOPE_DEVICE; 6603b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall}; 6703b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall 681356b0d3179254a7a27e88abb2d2500385469f14Jesse Halltemplate <typename T, typename Host> 69d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallclass VulkanAllocator { 70d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall public: 71d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall typedef T value_type; 72d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 731356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall explicit VulkanAllocator(Host host) : host_(host) {} 74d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 75d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall template <typename U> 761356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall explicit VulkanAllocator(const VulkanAllocator<U, Host>& other) 771356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall : host_(other.host_) {} 78d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 79d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall T* allocate(size_t n) const { 801356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall return static_cast<T*>(AllocMem(host_, n * sizeof(T), alignof(T), 8103b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall AllocScope<Host>::kScope)); 82d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 831356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall void deallocate(T* p, size_t) const { return FreeMem(host_, p); } 84d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 85d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall private: 861356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall template <typename U, typename H> 87d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall friend class VulkanAllocator; 881356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Host host_; 89d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}; 90d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 911356b0d3179254a7a27e88abb2d2500385469f14Jesse Halltemplate <typename T, typename Host> 921356b0d3179254a7a27e88abb2d2500385469f14Jesse Hallstd::shared_ptr<T> InitSharedPtr(Host host, T* obj) { 93d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall obj->common.incRef(&obj->common); 94d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return std::shared_ptr<T>(obj, NativeBaseDeleter<T>(), 951356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall VulkanAllocator<T, Host>(host)); 96d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall} 97d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 98d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// ---------------------------------------------------------------------------- 99d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 1001356b0d3179254a7a27e88abb2d2500385469f14Jesse Hallstruct Surface { 1011356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall std::shared_ptr<ANativeWindow> window; 1021356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall}; 1031356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall 1041356b0d3179254a7a27e88abb2d2500385469f14Jesse HallVkSurfaceKHR HandleFromSurface(Surface* surface) { 1051356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface)); 1061356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall} 1071356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall 1081356b0d3179254a7a27e88abb2d2500385469f14Jesse HallSurface* SurfaceFromHandle(VkSurfaceKHR handle) { 109a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall return reinterpret_cast<Surface*>(handle); 1101356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall} 1111356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall 112d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hallstruct Swapchain { 1131356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Swapchain(Surface& surface_, uint32_t num_images_) 1141356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall : surface(surface_), num_images(num_images_) {} 115d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 1161356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Surface& surface; 117d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall uint32_t num_images; 118d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 119d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall struct Image { 120d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {} 121d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkImage image; 122d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall std::shared_ptr<ANativeWindowBuffer> buffer; 123d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // The fence is only valid when the buffer is dequeued, and should be 124d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // -1 any other time. When valid, we own the fd, and must ensure it is 125d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // closed: either by closing it explicitly when queueing the buffer, 126d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // or by passing ownership e.g. to ANativeWindow::cancelBuffer(). 127d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int dequeue_fence; 128d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall bool dequeued; 129d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } images[android::BufferQueue::NUM_BUFFER_SLOTS]; 130d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall}; 131d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 132d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallVkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) { 133d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain)); 134d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall} 135d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 136d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallSwapchain* SwapchainFromHandle(VkSwapchainKHR handle) { 137a3a7a1d37bdfad56245b75edac49f8aceded321dJesse Hall return reinterpret_cast<Swapchain*>(handle); 138d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall} 139d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 140d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall} // anonymous namespace 141b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 142b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hallnamespace vulkan { 143b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 144e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 1451356b0d3179254a7a27e88abb2d2500385469f14Jesse HallVkResult CreateAndroidSurfaceKHR(VkInstance instance, 1461356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall ANativeWindow* window, 1470e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall const VkAllocationCallbacks* /*allocator*/, 1481356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall VkSurfaceKHR* out_surface) { 1491356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall void* mem = AllocMem(instance, sizeof(Surface), alignof(Surface), 1503fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1511356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall if (!mem) 1521356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall return VK_ERROR_OUT_OF_HOST_MEMORY; 1531356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Surface* surface = new (mem) Surface; 154b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 1551356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall surface->window = InitSharedPtr(instance, window); 156b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 1571356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN. 1581356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall int err = 1591356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL); 1601356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall if (err != 0) { 1611356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 1621356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // errors and translate them to valid Vulkan result codes? 1631356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err), 1641356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err); 1651356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall surface->~Surface(); 1661356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall FreeMem(instance, surface); 1671356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 1681356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall } 169b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 1701356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall *out_surface = HandleFromSurface(surface); 171b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall return VK_SUCCESS; 172b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 173b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 174e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 1750e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hallvoid DestroySurfaceKHR(VkInstance instance, 1760e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall VkSurfaceKHR surface_handle, 1770e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall const VkAllocationCallbacks* /*allocator*/) { 1781356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Surface* surface = SurfaceFromHandle(surface_handle); 1791356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall if (!surface) 1801356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall return; 1811356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL); 1821356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall surface->~Surface(); 1831356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall FreeMem(instance, surface); 1841356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall} 1851356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall 186e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 187a64292517b1876c4bbe5d3e62c577812f40bd922Jesse HallVkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/, 1881356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall uint32_t /*queue_family*/, 189b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkSurfaceKHR /*surface*/, 1900e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall VkBool32* supported) { 1910e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall *supported = VK_TRUE; 192a64292517b1876c4bbe5d3e62c577812f40bd922Jesse Hall return VK_SUCCESS; 1931356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall} 1941356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall 195e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 196b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse HallVkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( 197b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkPhysicalDevice /*pdev*/, 198b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkSurfaceKHR surface, 199b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkSurfaceCapabilitiesKHR* capabilities) { 200d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int err; 2011356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); 202d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 203d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int width, height; 204d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); 205d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 206d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", 207d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall strerror(-err), err); 2085ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 209d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 210d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); 211d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 212d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", 213d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall strerror(-err), err); 2145ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 215d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 216d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 217b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->currentExtent = VkExtent2D{width, height}; 218d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 219d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Figure out what the min/max values should be. 220b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->minImageCount = 2; 221b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->maxImageCount = 3; 222d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 223d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Figure out what the max extent should be. Maximum 224d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // texture dimension maybe? 225b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->minImageExtent = VkExtent2D{1, 1}; 226b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->maxImageExtent = VkExtent2D{4096, 4096}; 227d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 228d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): We can support all transforms, fix this once 229d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // implemented. 230b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_KHR; 231d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 232d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Implement based on NATIVE_WINDOW_TRANSFORM_HINT. 233b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->currentTransform = VK_SURFACE_TRANSFORM_NONE_KHR; 234d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 235b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->maxImageArraySize = 1; 236d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 237d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): I think these are right, but haven't thought hard about 238d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // it. Do we need to query the driver for support of any of these? 239d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // Currently not included: 240d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // - VK_IMAGE_USAGE_GENERAL: maybe? does this imply cpu mappable? 241d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not 242d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not 243b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall capabilities->supportedUsageFlags = 2443fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | 2453fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | 2463fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 247d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 248d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 249b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall return VK_SUCCESS; 250b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 251b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 252e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 253b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse HallVkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice /*pdev*/, 254b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkSurfaceKHR /*surface*/, 255b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall uint32_t* count, 256b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkSurfaceFormatKHR* formats) { 2571356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // TODO(jessehall): Fill out the set of supported formats. Longer term, add 2581356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // a new gralloc method to query whether a (format, usage) pair is 2591356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // supported, and check that for each gralloc format that corresponds to a 2601356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // Vulkan format. Shorter term, just add a few more formats to the ones 2611356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall // hardcoded below. 262d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 263d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const VkSurfaceFormatKHR kFormats[] = { 264d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall {VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR}, 265d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR}, 266d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall }; 267d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); 268d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 269d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult result = VK_SUCCESS; 270d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (formats) { 271d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (*count < kNumFormats) 272d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall result = VK_INCOMPLETE; 273d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall std::copy(kFormats, kFormats + std::min(*count, kNumFormats), formats); 274d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 275d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall *count = kNumFormats; 276d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return result; 277b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 278b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 279e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 280b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse HallVkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice /*pdev*/, 281b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkSurfaceKHR /*surface*/, 282b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall uint32_t* count, 283b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall VkPresentModeKHR* modes) { 284d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const VkPresentModeKHR kModes[] = { 285d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR, 286d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall }; 287d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const uint32_t kNumModes = sizeof(kModes) / sizeof(kModes[0]); 288d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 289d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult result = VK_SUCCESS; 290d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (modes) { 291d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (*count < kNumModes) 292d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall result = VK_INCOMPLETE; 293d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall std::copy(kModes, kModes + std::min(*count, kNumModes), modes); 294d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 295d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall *count = kNumModes; 296d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return result; 297b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 298b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 299e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 300b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse HallVkResult CreateSwapchainKHR(VkDevice device, 301b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall const VkSwapchainCreateInfoKHR* create_info, 3020e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall const VkAllocationCallbacks* /*allocator*/, 303d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkSwapchainKHR* swapchain_handle) { 304d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int err; 305d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult result = VK_SUCCESS; 306d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 307d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGV_IF(create_info->imageArraySize != 1, 308d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "Swapchain imageArraySize (%u) != 1 not supported", 309d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall create_info->imageArraySize); 310d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 311d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE_IF(create_info->imageFormat != VK_FORMAT_R8G8B8A8_UNORM, 312d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "swapchain formats other than R8G8B8A8_UNORM not yet implemented"); 313d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE_IF(create_info->imageColorSpace != VK_COLORSPACE_SRGB_NONLINEAR_KHR, 314d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "color spaces other than SRGB_NONLINEAR not yet implemented"); 315d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE_IF(create_info->oldSwapchain, 316d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "swapchain re-creation not yet implemented"); 317d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE_IF(create_info->preTransform != VK_SURFACE_TRANSFORM_NONE_KHR, 318d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "swapchain preTransform not yet implemented"); 319d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE_IF(create_info->presentMode != VK_PRESENT_MODE_FIFO_KHR, 320d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "present modes other than FIFO are not yet implemented"); 321d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 322d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // -- Configure the native window -- 323d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 3241356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Surface& surface = *SurfaceFromHandle(create_info->surface); 32570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall const DeviceVtbl& driver_vtbl = GetDriverVtbl(device); 32670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall 3271356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = native_window_set_buffers_dimensions(surface.window.get(), 328d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall create_info->imageExtent.width, 329d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall create_info->imageExtent.height); 330d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 331d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 332d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // errors and translate them to valid Vulkan result codes? 333d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)", 334d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall create_info->imageExtent.width, create_info->imageExtent.height, 335d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall strerror(-err), err); 3365ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 337d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 338d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 339f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall err = native_window_set_scaling_mode( 3401356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 341f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall if (err != 0) { 342f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 343f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall // errors and translate them to valid Vulkan result codes? 344f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)", 345f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall strerror(-err), err); 346f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 347f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall } 348f64ca1209c4b67baf36d6f489d3c73067113d419Jesse Hall 349d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall uint32_t min_undequeued_buffers; 3501356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = surface.window->query( 3511356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall surface.window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 3521356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall reinterpret_cast<int*>(&min_undequeued_buffers)); 353d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 354d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 355d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // errors and translate them to valid Vulkan result codes? 356d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("window->query failed: %s (%d)", strerror(-err), err); 3575ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 358d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 359d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall uint32_t num_images = 360d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall (create_info->minImageCount - 1) + min_undequeued_buffers; 3611356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = native_window_set_buffer_count(surface.window.get(), num_images); 362d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 363d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 364d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // errors and translate them to valid Vulkan result codes? 365d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 366d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall err); 3675ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 368d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 369d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 37070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall int gralloc_usage = 0; 37170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall // TODO(jessehall): Remove conditional once all drivers have been updated 37270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall if (driver_vtbl.GetSwapchainGrallocUsageANDROID) { 37370f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall result = driver_vtbl.GetSwapchainGrallocUsageANDROID( 37470f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall device, create_info->imageFormat, create_info->imageUsageFlags, 37570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall &gralloc_usage); 37670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall if (result != VK_SUCCESS) { 37770f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result); 37870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 37970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall } 38070f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall } else { 38170f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; 38270f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall } 3831356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = native_window_set_usage(surface.window.get(), gralloc_usage); 38470f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall if (err != 0) { 38570f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 38670f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall // errors and translate them to valid Vulkan result codes? 38770f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err); 38870f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 38970f9335d77282e34fa1cdb8d1baed89892ccd2e1Jesse Hall } 390d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 391d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // -- Allocate our Swapchain object -- 392d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // After this point, we must deallocate the swapchain on error. 393d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 3941356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall void* mem = AllocMem(device, sizeof(Swapchain), alignof(Swapchain), 3953fbc856120217247c72fb5ed88500000f3881c45Jesse Hall VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 3961356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall if (!mem) 397d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return VK_ERROR_OUT_OF_HOST_MEMORY; 3981356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall Swapchain* swapchain = new (mem) Swapchain(surface, num_images); 399d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 400d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // -- Dequeue all buffers and create a VkImage for each -- 401d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // Any failures during or after this must cancel the dequeued buffers. 402d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 403d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkNativeBufferANDROID image_native_buffer = { 404d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall// TODO(jessehall): Figure out how to make extension headers not horrible. 405d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push 406d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast" 407d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID, 408d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic pop 409d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .pNext = nullptr, 410d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall }; 411d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkImageCreateInfo image_create = { 412d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 413d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .pNext = &image_native_buffer, 414d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .imageType = VK_IMAGE_TYPE_2D, 415d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .format = VK_FORMAT_R8G8B8A8_UNORM, // TODO(jessehall) 416d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .extent = {0, 0, 1}, 417d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .mipLevels = 1, 418a15a4bf4bafd6114ae8f28c2df2fc622cb3baaceJesse Hall .arrayLayers = 1, 419091ed9e69400edcc549c9b11635d1a305d6b5a83Jesse Hall .samples = VK_SAMPLE_COUNT_1_BIT, 420d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .tiling = VK_IMAGE_TILING_OPTIMAL, 421d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .usage = create_info->imageUsageFlags, 422d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .flags = 0, 423d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .sharingMode = create_info->sharingMode, 42403b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall .queueFamilyIndexCount = create_info->queueFamilyIndexCount, 425d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall .pQueueFamilyIndices = create_info->pQueueFamilyIndices, 426d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall }; 427d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 428d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall for (uint32_t i = 0; i < num_images; i++) { 429d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain::Image& img = swapchain->images[i]; 430d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 431d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ANativeWindowBuffer* buffer; 4321356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = surface.window->dequeueBuffer(surface.window.get(), &buffer, 4331356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall &img.dequeue_fence); 434d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 435d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate 436d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // possible errors and translate them to valid Vulkan result codes? 437d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err); 4385ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall result = VK_ERROR_INITIALIZATION_FAILED; 439d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall break; 440d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 441d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.buffer = InitSharedPtr(device, buffer); 442d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeued = true; 443d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 444d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall image_create.extent = 445d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkExtent3D{img.buffer->width, img.buffer->height, 1}; 446d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall image_native_buffer.handle = img.buffer->handle; 447d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall image_native_buffer.stride = img.buffer->stride; 448d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall image_native_buffer.format = img.buffer->format; 449d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall image_native_buffer.usage = img.buffer->usage; 450d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 45103b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall result = 45203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall driver_vtbl.CreateImage(device, &image_create, nullptr, &img.image); 453d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (result != VK_SUCCESS) { 454d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGD("vkCreateImage w/ native buffer failed: %u", result); 455d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall break; 456d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 457d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 458d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 459d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // -- Cancel all buffers, returning them to the queue -- 460d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // If an error occurred before, also destroy the VkImage and release the 461d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // buffer reference. Otherwise, we retain a strong reference to the buffer. 462d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // 463d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): The error path here is the same as DestroySwapchain, 464d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // but not the non-error path. Should refactor/unify. 465d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall for (uint32_t i = 0; i < num_images; i++) { 466d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain::Image& img = swapchain->images[i]; 467d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (img.dequeued) { 4681356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall surface.window->cancelBuffer(surface.window.get(), img.buffer.get(), 4691356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall img.dequeue_fence); 470d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeue_fence = -1; 471d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeued = false; 472d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 473d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (result != VK_SUCCESS) { 474d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (img.image) 47503b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall driver_vtbl.DestroyImage(device, img.image, nullptr); 476d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 477d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 478d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 479d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (result != VK_SUCCESS) { 480d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall swapchain->~Swapchain(); 4811356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall FreeMem(device, swapchain); 482d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return result; 483d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 484d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 485d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall *swapchain_handle = HandleFromSwapchain(swapchain); 486b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall return VK_SUCCESS; 487b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 488b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 489e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 4900e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse HallVkResult DestroySwapchainKHR(VkDevice device, 4910e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall VkSwapchainKHR swapchain_handle, 4920e74f00af03b7e705774d0dcf69c2ba8ce7a15a8Jesse Hall const VkAllocationCallbacks* /*allocator*/) { 493d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const DeviceVtbl& driver_vtbl = GetDriverVtbl(device); 494d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain* swapchain = SwapchainFromHandle(swapchain_handle); 4951356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window; 496d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 497d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall for (uint32_t i = 0; i < swapchain->num_images; i++) { 498d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain::Image& img = swapchain->images[i]; 499d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (img.dequeued) { 500d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall window->cancelBuffer(window.get(), img.buffer.get(), 501d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeue_fence); 502d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeue_fence = -1; 503d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeued = false; 504d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 505d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (img.image) { 50603b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall driver_vtbl.DestroyImage(device, img.image, nullptr); 507d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 508d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 509d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 510d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall swapchain->~Swapchain(); 5111356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall FreeMem(device, swapchain); 512d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 513b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall return VK_SUCCESS; 514b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 515b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 516e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 517d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse HallVkResult GetSwapchainImagesKHR(VkDevice, 518d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkSwapchainKHR swapchain_handle, 519b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall uint32_t* count, 520d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkImage* images) { 521d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 522d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult result = VK_SUCCESS; 523d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (images) { 524d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall uint32_t n = swapchain.num_images; 525d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (*count < swapchain.num_images) { 526d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall n = *count; 527d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall result = VK_INCOMPLETE; 528d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 529d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall for (uint32_t i = 0; i < n; i++) 530d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall images[i] = swapchain.images[i].image; 531d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 532d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall *count = swapchain.num_images; 533d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return result; 534b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 535b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 536e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 537b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse HallVkResult AcquireNextImageKHR(VkDevice device, 538d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkSwapchainKHR swapchain_handle, 539b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall uint64_t timeout, 540b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall VkSemaphore semaphore, 541b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall uint32_t* image_index) { 542d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); 5431356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall ANativeWindow* window = swapchain.surface.window.get(); 544d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult result; 545d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int err; 546d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 547d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGW_IF( 548d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall timeout != UINT64_MAX, 549d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented"); 550d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 551d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ANativeWindowBuffer* buffer; 552d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int fence; 5531356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = window->dequeueBuffer(window, &buffer, &fence); 554d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 555d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): Improve error reporting. Can we enumerate possible 556d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // errors and translate them to valid Vulkan result codes? 557d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err); 5585ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall return VK_ERROR_INITIALIZATION_FAILED; 559d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 560d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 561d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall uint32_t idx; 562d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall for (idx = 0; idx < swapchain.num_images; idx++) { 563d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (swapchain.images[idx].buffer.get() == buffer) { 564d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall swapchain.images[idx].dequeued = true; 565d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall swapchain.images[idx].dequeue_fence = fence; 566d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall break; 567d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 568d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 569d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (idx == swapchain.num_images) { 570d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("dequeueBuffer returned unrecognized buffer"); 5711356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall window->cancelBuffer(window, buffer, fence); 572d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push 573d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast" 574d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return VK_ERROR_OUT_OF_DATE_KHR; 575d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic pop 576d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 577d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 578d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int fence_clone = -1; 579d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (fence != -1) { 580d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall fence_clone = dup(fence); 581d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (fence_clone == -1) { 582d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", 583d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall strerror(errno), errno); 584d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall sync_wait(fence, -1 /* forever */); 585d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 586d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 587d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 588d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const DeviceVtbl& driver_vtbl = GetDriverVtbl(device); 589ab9aeef063119445b59166f781c464c64e3909dbJesse Hall if (driver_vtbl.AcquireImageANDROID) { 590ab9aeef063119445b59166f781c464c64e3909dbJesse Hall result = driver_vtbl.AcquireImageANDROID( 591ab9aeef063119445b59166f781c464c64e3909dbJesse Hall device, swapchain.images[idx].image, fence_clone, semaphore); 592ab9aeef063119445b59166f781c464c64e3909dbJesse Hall } else { 593ab9aeef063119445b59166f781c464c64e3909dbJesse Hall ALOG_ASSERT(driver_vtbl.ImportNativeFenceANDROID, 594ab9aeef063119445b59166f781c464c64e3909dbJesse Hall "Have neither vkAcquireImageANDROID nor " 595ab9aeef063119445b59166f781c464c64e3909dbJesse Hall "vkImportNativeFenceANDROID"); 596ab9aeef063119445b59166f781c464c64e3909dbJesse Hall result = driver_vtbl.ImportNativeFenceANDROID(device, semaphore, 597ab9aeef063119445b59166f781c464c64e3909dbJesse Hall fence_clone); 598ab9aeef063119445b59166f781c464c64e3909dbJesse Hall } 599d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (result != VK_SUCCESS) { 600ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // NOTE: we're relying on AcquireImageANDROID to close fence_clone, 601ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // even if the call fails. We could close it ourselves on failure, but 602ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // that would create a race condition if the driver closes it on a 603ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // failure path: some other thread might create an fd with the same 604ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // number between the time the driver closes it and the time we close 605ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // it. We must assume one of: the driver *always* closes it even on 606ab9aeef063119445b59166f781c464c64e3909dbJesse Hall // failure, or *never* closes it on failure. 6071356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall window->cancelBuffer(window, buffer, fence); 608d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall swapchain.images[idx].dequeued = false; 609d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall swapchain.images[idx].dequeue_fence = -1; 610d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return result; 611d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 612d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 613d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall *image_index = idx; 614b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall return VK_SUCCESS; 615b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} 616b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 617e1b12783fff0b8e2defcc94c54fac8d737e6b996Jesse HallVKAPI_ATTR 618b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse HallVkResult QueuePresentKHR(VkQueue queue, VkPresentInfoKHR* present_info) { 619d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic push 620d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wold-style-cast" 621d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall#pragma clang diagnostic ignored "-Wsign-conversion" 622d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 623d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d", 624d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall present_info->sType); 625b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall#pragma clang diagnostic pop 626d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL"); 627d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 628d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall const DeviceVtbl& driver_vtbl = GetDriverVtbl(queue); 629d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult final_result = VK_SUCCESS; 630d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) { 631d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall Swapchain& swapchain = 63203b6fe1b099764c6010c173c1416ea102cdfe5a4Jesse Hall *SwapchainFromHandle(present_info->pSwapchains[sc]); 6331356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall ANativeWindow* window = swapchain.surface.window.get(); 634d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall uint32_t image_idx = present_info->imageIndices[sc]; 6355ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall Swapchain::Image& img = swapchain.images[image_idx]; 636d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall VkResult result; 637d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int err; 638d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 639d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall int fence = -1; 640ab9aeef063119445b59166f781c464c64e3909dbJesse Hall if (driver_vtbl.QueueSignalReleaseImageANDROID) { 641ab9aeef063119445b59166f781c464c64e3909dbJesse Hall result = driver_vtbl.QueueSignalReleaseImageANDROID( 642ab9aeef063119445b59166f781c464c64e3909dbJesse Hall queue, img.image, &fence); 643ab9aeef063119445b59166f781c464c64e3909dbJesse Hall } else { 644ab9aeef063119445b59166f781c464c64e3909dbJesse Hall ALOG_ASSERT(driver_vtbl.QueueSignalNativeFenceANDROID, 645ab9aeef063119445b59166f781c464c64e3909dbJesse Hall "Have neither vkQueueSignalReleaseImageANDROID nor " 646ab9aeef063119445b59166f781c464c64e3909dbJesse Hall "vkQueueSignalNativeFenceANDROID"); 647ab9aeef063119445b59166f781c464c64e3909dbJesse Hall result = driver_vtbl.QueueSignalNativeFenceANDROID(queue, &fence); 648ab9aeef063119445b59166f781c464c64e3909dbJesse Hall } 649d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (result != VK_SUCCESS) { 650ab9aeef063119445b59166f781c464c64e3909dbJesse Hall ALOGE("QueueSignalReleaseImageANDROID failed: %d", result); 651a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall if (present_info->pResults) 652a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall present_info->pResults[sc] = result; 653d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (final_result == VK_SUCCESS) 654d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall final_result = result; 655d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): What happens to the buffer here? Does the app 656d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // still own it or not, i.e. should we cancel the buffer? Hard to 657d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // do correctly without synchronizing, though I guess we could wait 658d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // for the queue to idle. 659d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall continue; 660d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 661d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 6621356b0d3179254a7a27e88abb2d2500385469f14Jesse Hall err = window->queueBuffer(window, img.buffer.get(), fence); 663d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (err != 0) { 664d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // TODO(jessehall): What now? We should probably cancel the buffer, 665d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall // I guess? 666d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err); 667a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall if (present_info->pResults) 668a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall present_info->pResults[sc] = result; 669d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (final_result == VK_SUCCESS) 6705ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall final_result = VK_ERROR_INITIALIZATION_FAILED; 671d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall continue; 672d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 673d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 674d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall if (img.dequeue_fence != -1) { 675d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall close(img.dequeue_fence); 676d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeue_fence = -1; 677d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 678d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall img.dequeued = false; 679a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall 680a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall if (present_info->pResults) 681a9e5703e380d9d7f096d177adb792621a1e8d4baJesse Hall present_info->pResults[sc] = VK_SUCCESS; 682d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall } 683d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall 684d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall return final_result; 685d7b994a0cfb9054aafc1dadc85085a7d0ef8789aJesse Hall} 686b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall 687b1352bce9cd82ceaef287b8b3cd7a5c39703a14cJesse Hall} // namespace vulkan 688