| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2015 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 17 | #include <algorithm> | 
 | 18 | #include <memory> | 
 | 19 |  | 
 | 20 | #include <gui/BufferQueue.h> | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 21 | #include <log/log.h> | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 22 | #include <sync/sync.h> | 
 | 23 |  | 
 | 24 | #include "loader.h" | 
 | 25 |  | 
 | 26 | using namespace vulkan; | 
 | 27 |  | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 28 | // TODO(jessehall): Currently we don't have a good error code for when a native | 
 | 29 | // window operation fails. Just returning INITIALIZATION_FAILED for now. Later | 
 | 30 | // versions (post SDK 0.9) of the API/extension have a better error code. | 
 | 31 | // When updating to that version, audit all error returns. | 
 | 32 |  | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 33 | namespace { | 
 | 34 |  | 
 | 35 | // ---------------------------------------------------------------------------- | 
 | 36 | // These functions/classes form an adaptor that allows objects to be refcounted | 
 | 37 | // by both android::sp<> and std::shared_ptr<> simultaneously, and delegates | 
| Jesse Hall | 3fbc856 | 2015-11-29 22:10:52 -0800 | [diff] [blame] | 38 | // allocation of the shared_ptr<> control structure to VkAllocationCallbacks. | 
 | 39 | // The | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 40 | // platform holds a reference to the ANativeWindow using its embedded reference | 
 | 41 | // count, and the ANativeWindow implementation holds references to the | 
 | 42 | // ANativeWindowBuffers using their embedded reference counts, so the | 
 | 43 | // shared_ptr *must* cooperate with these and hold at least one reference to | 
 | 44 | // the object using the embedded reference count. | 
 | 45 |  | 
 | 46 | template <typename T> | 
 | 47 | struct NativeBaseDeleter { | 
 | 48 |     void operator()(T* obj) { obj->common.decRef(&obj->common); } | 
 | 49 | }; | 
 | 50 |  | 
| Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 51 | template <typename Host> | 
 | 52 | struct AllocScope {}; | 
 | 53 |  | 
 | 54 | template <> | 
 | 55 | struct AllocScope<VkInstance> { | 
| Jesse Hall | 3fbc856 | 2015-11-29 22:10:52 -0800 | [diff] [blame] | 56 |     static const VkSystemAllocationScope kScope = | 
 | 57 |         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE; | 
| Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 58 | }; | 
 | 59 |  | 
 | 60 | template <> | 
 | 61 | struct AllocScope<VkDevice> { | 
| Jesse Hall | 3fbc856 | 2015-11-29 22:10:52 -0800 | [diff] [blame] | 62 |     static const VkSystemAllocationScope kScope = | 
 | 63 |         VK_SYSTEM_ALLOCATION_SCOPE_DEVICE; | 
| Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 64 | }; | 
 | 65 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 66 | template <typename T> | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 67 | class VulkanAllocator { | 
 | 68 |    public: | 
 | 69 |     typedef T value_type; | 
 | 70 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 71 |     VulkanAllocator(const VkAllocationCallbacks& allocator, | 
 | 72 |                     VkSystemAllocationScope scope) | 
 | 73 |         : allocator_(allocator), scope_(scope) {} | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 74 |  | 
 | 75 |     template <typename U> | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 76 |     explicit VulkanAllocator(const VulkanAllocator<U>& other) | 
 | 77 |         : allocator_(other.allocator_), scope_(other.scope_) {} | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 78 |  | 
 | 79 |     T* allocate(size_t n) const { | 
| Jesse Hall | 26cecff | 2016-01-21 19:52:25 -0800 | [diff] [blame] | 80 |         T* p = static_cast<T*>(allocator_.pfnAllocation( | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 81 |             allocator_.pUserData, n * sizeof(T), alignof(T), scope_)); | 
| Jesse Hall | 26cecff | 2016-01-21 19:52:25 -0800 | [diff] [blame] | 82 |         if (!p) | 
 | 83 |             throw std::bad_alloc(); | 
 | 84 |         return p; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 85 |     } | 
| Jesse Hall | 26cecff | 2016-01-21 19:52:25 -0800 | [diff] [blame] | 86 |     void deallocate(T* p, size_t) const noexcept { | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 87 |         return allocator_.pfnFree(allocator_.pUserData, p); | 
 | 88 |     } | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 89 |  | 
 | 90 |    private: | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 91 |     template <typename U> | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 92 |     friend class VulkanAllocator; | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 93 |     const VkAllocationCallbacks& allocator_; | 
 | 94 |     const VkSystemAllocationScope scope_; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 95 | }; | 
 | 96 |  | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 97 | template <typename T, typename Host> | 
 | 98 | std::shared_ptr<T> InitSharedPtr(Host host, T* obj) { | 
| Jesse Hall | 26cecff | 2016-01-21 19:52:25 -0800 | [diff] [blame] | 99 |     try { | 
 | 100 |         obj->common.incRef(&obj->common); | 
 | 101 |         return std::shared_ptr<T>( | 
 | 102 |             obj, NativeBaseDeleter<T>(), | 
 | 103 |             VulkanAllocator<T>(*GetAllocator(host), AllocScope<Host>::kScope)); | 
 | 104 |     } catch (std::bad_alloc&) { | 
 | 105 |         obj->common.decRef(&obj->common); | 
 | 106 |         return nullptr; | 
 | 107 |     } | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 108 | } | 
 | 109 |  | 
 | 110 | // ---------------------------------------------------------------------------- | 
 | 111 |  | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 112 | struct Surface { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 113 |     std::shared_ptr<ANativeWindow> window; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 114 | }; | 
 | 115 |  | 
 | 116 | VkSurfaceKHR HandleFromSurface(Surface* surface) { | 
 | 117 |     return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface)); | 
 | 118 | } | 
 | 119 |  | 
 | 120 | Surface* SurfaceFromHandle(VkSurfaceKHR handle) { | 
| Jesse Hall | a3a7a1d | 2015-11-24 11:37:23 -0800 | [diff] [blame] | 121 |     return reinterpret_cast<Surface*>(handle); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 122 | } | 
 | 123 |  | 
 | 124 | struct Swapchain { | 
 | 125 |     Swapchain(Surface& surface_, uint32_t num_images_) | 
 | 126 |         : surface(surface_), num_images(num_images_) {} | 
 | 127 |  | 
 | 128 |     Surface& surface; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 129 |     uint32_t num_images; | 
 | 130 |  | 
 | 131 |     struct Image { | 
 | 132 |         Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {} | 
 | 133 |         VkImage image; | 
 | 134 |         std::shared_ptr<ANativeWindowBuffer> buffer; | 
 | 135 |         // The fence is only valid when the buffer is dequeued, and should be | 
 | 136 |         // -1 any other time. When valid, we own the fd, and must ensure it is | 
 | 137 |         // closed: either by closing it explicitly when queueing the buffer, | 
 | 138 |         // or by passing ownership e.g. to ANativeWindow::cancelBuffer(). | 
 | 139 |         int dequeue_fence; | 
 | 140 |         bool dequeued; | 
 | 141 |     } images[android::BufferQueue::NUM_BUFFER_SLOTS]; | 
 | 142 | }; | 
 | 143 |  | 
 | 144 | VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) { | 
 | 145 |     return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain)); | 
 | 146 | } | 
 | 147 |  | 
 | 148 | Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) { | 
| Jesse Hall | a3a7a1d | 2015-11-24 11:37:23 -0800 | [diff] [blame] | 149 |     return reinterpret_cast<Swapchain*>(handle); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 150 | } | 
 | 151 |  | 
 | 152 | }  // anonymous namespace | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 153 |  | 
 | 154 | namespace vulkan { | 
 | 155 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 156 | VKAPI_ATTR | 
| Jesse Hall | f9fa9a5 | 2016-01-08 16:08:51 -0800 | [diff] [blame] | 157 | VkResult CreateAndroidSurfaceKHR_Bottom( | 
 | 158 |     VkInstance instance, | 
 | 159 |     const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, | 
 | 160 |     const VkAllocationCallbacks* allocator, | 
 | 161 |     VkSurfaceKHR* out_surface) { | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 162 |     if (!allocator) | 
 | 163 |         allocator = GetAllocator(instance); | 
 | 164 |     void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface), | 
 | 165 |                                          alignof(Surface), | 
 | 166 |                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 167 |     if (!mem) | 
 | 168 |         return VK_ERROR_OUT_OF_HOST_MEMORY; | 
 | 169 |     Surface* surface = new (mem) Surface; | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 170 |  | 
| Jesse Hall | f9fa9a5 | 2016-01-08 16:08:51 -0800 | [diff] [blame] | 171 |     surface->window = InitSharedPtr(instance, pCreateInfo->window); | 
| Jesse Hall | 26cecff | 2016-01-21 19:52:25 -0800 | [diff] [blame] | 172 |     if (!surface->window) { | 
 | 173 |         ALOGE("surface creation failed: out of memory"); | 
 | 174 |         surface->~Surface(); | 
 | 175 |         allocator->pfnFree(allocator->pUserData, surface); | 
 | 176 |         return VK_ERROR_OUT_OF_HOST_MEMORY; | 
 | 177 |     } | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 178 |  | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 179 |     // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN. | 
 | 180 |     int err = | 
 | 181 |         native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL); | 
 | 182 |     if (err != 0) { | 
 | 183 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 184 |         // errors and translate them to valid Vulkan result codes? | 
 | 185 |         ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err), | 
 | 186 |               err); | 
 | 187 |         surface->~Surface(); | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 188 |         allocator->pfnFree(allocator->pUserData, surface); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 189 |         return VK_ERROR_INITIALIZATION_FAILED; | 
 | 190 |     } | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 191 |  | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 192 |     *out_surface = HandleFromSurface(surface); | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 193 |     return VK_SUCCESS; | 
 | 194 | } | 
 | 195 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 196 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 197 | void DestroySurfaceKHR_Bottom(VkInstance instance, | 
 | 198 |                               VkSurfaceKHR surface_handle, | 
 | 199 |                               const VkAllocationCallbacks* allocator) { | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 200 |     Surface* surface = SurfaceFromHandle(surface_handle); | 
 | 201 |     if (!surface) | 
 | 202 |         return; | 
 | 203 |     native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL); | 
 | 204 |     surface->~Surface(); | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 205 |     if (!allocator) | 
 | 206 |         allocator = GetAllocator(instance); | 
 | 207 |     allocator->pfnFree(allocator->pUserData, surface); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 208 | } | 
 | 209 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 210 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 211 | VkResult GetPhysicalDeviceSurfaceSupportKHR_Bottom(VkPhysicalDevice /*pdev*/, | 
 | 212 |                                                    uint32_t /*queue_family*/, | 
 | 213 |                                                    VkSurfaceKHR /*surface*/, | 
 | 214 |                                                    VkBool32* supported) { | 
| Jesse Hall | 0e74f00 | 2015-11-30 11:37:59 -0800 | [diff] [blame] | 215 |     *supported = VK_TRUE; | 
| Jesse Hall | a642925 | 2015-11-29 18:59:42 -0800 | [diff] [blame] | 216 |     return VK_SUCCESS; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 217 | } | 
 | 218 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 219 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 220 | VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom( | 
| Jesse Hall | b00daad | 2015-11-29 19:46:20 -0800 | [diff] [blame] | 221 |     VkPhysicalDevice /*pdev*/, | 
 | 222 |     VkSurfaceKHR surface, | 
 | 223 |     VkSurfaceCapabilitiesKHR* capabilities) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 224 |     int err; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 225 |     ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 226 |  | 
 | 227 |     int width, height; | 
 | 228 |     err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); | 
 | 229 |     if (err != 0) { | 
 | 230 |         ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", | 
 | 231 |               strerror(-err), err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 232 |         return VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 233 |     } | 
 | 234 |     err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); | 
 | 235 |     if (err != 0) { | 
 | 236 |         ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", | 
 | 237 |               strerror(-err), err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 238 |         return VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 239 |     } | 
 | 240 |  | 
| Jesse Hall | 3dd678a | 2016-01-08 21:52:01 -0800 | [diff] [blame] | 241 |     capabilities->currentExtent = | 
 | 242 |         VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)}; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 243 |  | 
 | 244 |     // TODO(jessehall): Figure out what the min/max values should be. | 
| Jesse Hall | b00daad | 2015-11-29 19:46:20 -0800 | [diff] [blame] | 245 |     capabilities->minImageCount = 2; | 
 | 246 |     capabilities->maxImageCount = 3; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 247 |  | 
 | 248 |     // TODO(jessehall): Figure out what the max extent should be. Maximum | 
 | 249 |     // texture dimension maybe? | 
| Jesse Hall | b00daad | 2015-11-29 19:46:20 -0800 | [diff] [blame] | 250 |     capabilities->minImageExtent = VkExtent2D{1, 1}; | 
 | 251 |     capabilities->maxImageExtent = VkExtent2D{4096, 4096}; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 252 |  | 
 | 253 |     // TODO(jessehall): We can support all transforms, fix this once | 
 | 254 |     // implemented. | 
| Jesse Hall | f9fa9a5 | 2016-01-08 16:08:51 -0800 | [diff] [blame] | 255 |     capabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 256 |  | 
 | 257 |     // TODO(jessehall): Implement based on NATIVE_WINDOW_TRANSFORM_HINT. | 
| Jesse Hall | f9fa9a5 | 2016-01-08 16:08:51 -0800 | [diff] [blame] | 258 |     capabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 259 |  | 
| Jesse Hall | f4ab2b1 | 2015-11-30 16:04:55 -0800 | [diff] [blame] | 260 |     capabilities->maxImageArrayLayers = 1; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 261 |  | 
 | 262 |     // TODO(jessehall): I think these are right, but haven't thought hard about | 
 | 263 |     // it. Do we need to query the driver for support of any of these? | 
 | 264 |     // Currently not included: | 
 | 265 |     // - VK_IMAGE_USAGE_GENERAL: maybe? does this imply cpu mappable? | 
 | 266 |     // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not | 
 | 267 |     // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not | 
| Jesse Hall | b00daad | 2015-11-29 19:46:20 -0800 | [diff] [blame] | 268 |     capabilities->supportedUsageFlags = | 
| Jesse Hall | 3fbc856 | 2015-11-29 22:10:52 -0800 | [diff] [blame] | 269 |         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | | 
 | 270 |         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | | 
 | 271 |         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 272 |         VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; | 
 | 273 |  | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 274 |     return VK_SUCCESS; | 
 | 275 | } | 
 | 276 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 277 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 278 | VkResult GetPhysicalDeviceSurfaceFormatsKHR_Bottom( | 
 | 279 |     VkPhysicalDevice /*pdev*/, | 
 | 280 |     VkSurfaceKHR /*surface*/, | 
 | 281 |     uint32_t* count, | 
 | 282 |     VkSurfaceFormatKHR* formats) { | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 283 |     // TODO(jessehall): Fill out the set of supported formats. Longer term, add | 
 | 284 |     // a new gralloc method to query whether a (format, usage) pair is | 
 | 285 |     // supported, and check that for each gralloc format that corresponds to a | 
 | 286 |     // Vulkan format. Shorter term, just add a few more formats to the ones | 
 | 287 |     // hardcoded below. | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 288 |  | 
 | 289 |     const VkSurfaceFormatKHR kFormats[] = { | 
 | 290 |         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR}, | 
 | 291 |         {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR}, | 
 | 292 |     }; | 
 | 293 |     const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); | 
 | 294 |  | 
 | 295 |     VkResult result = VK_SUCCESS; | 
 | 296 |     if (formats) { | 
 | 297 |         if (*count < kNumFormats) | 
 | 298 |             result = VK_INCOMPLETE; | 
 | 299 |         std::copy(kFormats, kFormats + std::min(*count, kNumFormats), formats); | 
 | 300 |     } | 
 | 301 |     *count = kNumFormats; | 
 | 302 |     return result; | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 303 | } | 
 | 304 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 305 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 306 | VkResult GetPhysicalDeviceSurfacePresentModesKHR_Bottom( | 
 | 307 |     VkPhysicalDevice /*pdev*/, | 
 | 308 |     VkSurfaceKHR /*surface*/, | 
 | 309 |     uint32_t* count, | 
 | 310 |     VkPresentModeKHR* modes) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 311 |     const VkPresentModeKHR kModes[] = { | 
 | 312 |         VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR, | 
 | 313 |     }; | 
 | 314 |     const uint32_t kNumModes = sizeof(kModes) / sizeof(kModes[0]); | 
 | 315 |  | 
 | 316 |     VkResult result = VK_SUCCESS; | 
 | 317 |     if (modes) { | 
 | 318 |         if (*count < kNumModes) | 
 | 319 |             result = VK_INCOMPLETE; | 
 | 320 |         std::copy(kModes, kModes + std::min(*count, kNumModes), modes); | 
 | 321 |     } | 
 | 322 |     *count = kNumModes; | 
 | 323 |     return result; | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 324 | } | 
 | 325 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 326 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 327 | VkResult CreateSwapchainKHR_Bottom(VkDevice device, | 
 | 328 |                                    const VkSwapchainCreateInfoKHR* create_info, | 
 | 329 |                                    const VkAllocationCallbacks* allocator, | 
 | 330 |                                    VkSwapchainKHR* swapchain_handle) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 331 |     int err; | 
 | 332 |     VkResult result = VK_SUCCESS; | 
 | 333 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 334 |     if (!allocator) | 
 | 335 |         allocator = GetAllocator(device); | 
 | 336 |  | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 337 |     ALOGV_IF(create_info->imageArrayLayers != 1, | 
 | 338 |              "Swapchain imageArrayLayers (%u) != 1 not supported", | 
 | 339 |              create_info->imageArrayLayers); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 340 |  | 
 | 341 |     ALOGE_IF(create_info->imageFormat != VK_FORMAT_R8G8B8A8_UNORM, | 
 | 342 |              "swapchain formats other than R8G8B8A8_UNORM not yet implemented"); | 
 | 343 |     ALOGE_IF(create_info->imageColorSpace != VK_COLORSPACE_SRGB_NONLINEAR_KHR, | 
 | 344 |              "color spaces other than SRGB_NONLINEAR not yet implemented"); | 
 | 345 |     ALOGE_IF(create_info->oldSwapchain, | 
 | 346 |              "swapchain re-creation not yet implemented"); | 
| Jesse Hall | f9fa9a5 | 2016-01-08 16:08:51 -0800 | [diff] [blame] | 347 |     ALOGE_IF(create_info->preTransform != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 348 |              "swapchain preTransform not yet implemented"); | 
| Courtney Goeltzenleuchter | 9ec497c | 2016-01-29 13:02:06 -0700 | [diff] [blame] | 349 |     ALOGE_IF(create_info->presentMode != VK_PRESENT_MODE_FIFO_KHR, | 
 | 350 |              "present modes other than FIFO are not yet implemented"); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 351 |  | 
 | 352 |     // -- Configure the native window -- | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 353 |  | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 354 |     Surface& surface = *SurfaceFromHandle(create_info->surface); | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 355 |     const DriverDispatchTable& dispatch = GetDriverDispatch(device); | 
| Jesse Hall | 70f9335 | 2015-11-04 09:41:31 -0800 | [diff] [blame] | 356 |  | 
| Jesse Hall | 3dd678a | 2016-01-08 21:52:01 -0800 | [diff] [blame] | 357 |     err = native_window_set_buffers_dimensions( | 
 | 358 |         surface.window.get(), static_cast<int>(create_info->imageExtent.width), | 
 | 359 |         static_cast<int>(create_info->imageExtent.height)); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 360 |     if (err != 0) { | 
 | 361 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 362 |         // errors and translate them to valid Vulkan result codes? | 
 | 363 |         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)", | 
 | 364 |               create_info->imageExtent.width, create_info->imageExtent.height, | 
 | 365 |               strerror(-err), err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 366 |         return VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 367 |     } | 
 | 368 |  | 
| Jesse Hall | f64ca12 | 2015-11-03 16:11:10 -0800 | [diff] [blame] | 369 |     err = native_window_set_scaling_mode( | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 370 |         surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); | 
| Jesse Hall | f64ca12 | 2015-11-03 16:11:10 -0800 | [diff] [blame] | 371 |     if (err != 0) { | 
 | 372 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 373 |         // errors and translate them to valid Vulkan result codes? | 
 | 374 |         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)", | 
 | 375 |               strerror(-err), err); | 
| Jesse Hall | f64ca12 | 2015-11-03 16:11:10 -0800 | [diff] [blame] | 376 |         return VK_ERROR_INITIALIZATION_FAILED; | 
 | 377 |     } | 
 | 378 |  | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 379 |     uint32_t min_undequeued_buffers; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 380 |     err = surface.window->query( | 
 | 381 |         surface.window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, | 
 | 382 |         reinterpret_cast<int*>(&min_undequeued_buffers)); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 383 |     if (err != 0) { | 
 | 384 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 385 |         // errors and translate them to valid Vulkan result codes? | 
 | 386 |         ALOGE("window->query failed: %s (%d)", strerror(-err), err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 387 |         return VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 388 |     } | 
 | 389 |     uint32_t num_images = | 
 | 390 |         (create_info->minImageCount - 1) + min_undequeued_buffers; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 391 |     err = native_window_set_buffer_count(surface.window.get(), num_images); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 392 |     if (err != 0) { | 
 | 393 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 394 |         // errors and translate them to valid Vulkan result codes? | 
 | 395 |         ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), | 
 | 396 |               err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 397 |         return VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 398 |     } | 
 | 399 |  | 
| Jesse Hall | 70f9335 | 2015-11-04 09:41:31 -0800 | [diff] [blame] | 400 |     int gralloc_usage = 0; | 
 | 401 |     // TODO(jessehall): Remove conditional once all drivers have been updated | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 402 |     if (dispatch.GetSwapchainGrallocUsageANDROID) { | 
 | 403 |         result = dispatch.GetSwapchainGrallocUsageANDROID( | 
| Jesse Hall | f4ab2b1 | 2015-11-30 16:04:55 -0800 | [diff] [blame] | 404 |             device, create_info->imageFormat, create_info->imageUsage, | 
| Jesse Hall | 70f9335 | 2015-11-04 09:41:31 -0800 | [diff] [blame] | 405 |             &gralloc_usage); | 
 | 406 |         if (result != VK_SUCCESS) { | 
 | 407 |             ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result); | 
| Jesse Hall | 70f9335 | 2015-11-04 09:41:31 -0800 | [diff] [blame] | 408 |             return VK_ERROR_INITIALIZATION_FAILED; | 
 | 409 |         } | 
 | 410 |     } else { | 
 | 411 |         gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; | 
 | 412 |     } | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 413 |     err = native_window_set_usage(surface.window.get(), gralloc_usage); | 
| Jesse Hall | 70f9335 | 2015-11-04 09:41:31 -0800 | [diff] [blame] | 414 |     if (err != 0) { | 
 | 415 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 416 |         // errors and translate them to valid Vulkan result codes? | 
 | 417 |         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err); | 
| Jesse Hall | 70f9335 | 2015-11-04 09:41:31 -0800 | [diff] [blame] | 418 |         return VK_ERROR_INITIALIZATION_FAILED; | 
 | 419 |     } | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 420 |  | 
 | 421 |     // -- Allocate our Swapchain object -- | 
 | 422 |     // After this point, we must deallocate the swapchain on error. | 
 | 423 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 424 |     void* mem = allocator->pfnAllocation(allocator->pUserData, | 
 | 425 |                                          sizeof(Swapchain), alignof(Swapchain), | 
 | 426 |                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 427 |     if (!mem) | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 428 |         return VK_ERROR_OUT_OF_HOST_MEMORY; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 429 |     Swapchain* swapchain = new (mem) Swapchain(surface, num_images); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 430 |  | 
 | 431 |     // -- Dequeue all buffers and create a VkImage for each -- | 
 | 432 |     // Any failures during or after this must cancel the dequeued buffers. | 
 | 433 |  | 
 | 434 |     VkNativeBufferANDROID image_native_buffer = { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 435 | #pragma clang diagnostic push | 
 | 436 | #pragma clang diagnostic ignored "-Wold-style-cast" | 
 | 437 |         .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID, | 
 | 438 | #pragma clang diagnostic pop | 
 | 439 |         .pNext = nullptr, | 
 | 440 |     }; | 
 | 441 |     VkImageCreateInfo image_create = { | 
 | 442 |         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | 
 | 443 |         .pNext = &image_native_buffer, | 
 | 444 |         .imageType = VK_IMAGE_TYPE_2D, | 
 | 445 |         .format = VK_FORMAT_R8G8B8A8_UNORM,  // TODO(jessehall) | 
 | 446 |         .extent = {0, 0, 1}, | 
 | 447 |         .mipLevels = 1, | 
| Jesse Hall | a15a4bf | 2015-11-19 22:48:02 -0800 | [diff] [blame] | 448 |         .arrayLayers = 1, | 
| Jesse Hall | 091ed9e | 2015-11-30 00:55:29 -0800 | [diff] [blame] | 449 |         .samples = VK_SAMPLE_COUNT_1_BIT, | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 450 |         .tiling = VK_IMAGE_TILING_OPTIMAL, | 
| Jesse Hall | f4ab2b1 | 2015-11-30 16:04:55 -0800 | [diff] [blame] | 451 |         .usage = create_info->imageUsage, | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 452 |         .flags = 0, | 
| Jesse Hall | f4ab2b1 | 2015-11-30 16:04:55 -0800 | [diff] [blame] | 453 |         .sharingMode = create_info->imageSharingMode, | 
| Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 454 |         .queueFamilyIndexCount = create_info->queueFamilyIndexCount, | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 455 |         .pQueueFamilyIndices = create_info->pQueueFamilyIndices, | 
 | 456 |     }; | 
 | 457 |  | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 458 |     for (uint32_t i = 0; i < num_images; i++) { | 
 | 459 |         Swapchain::Image& img = swapchain->images[i]; | 
 | 460 |  | 
 | 461 |         ANativeWindowBuffer* buffer; | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 462 |         err = surface.window->dequeueBuffer(surface.window.get(), &buffer, | 
 | 463 |                                             &img.dequeue_fence); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 464 |         if (err != 0) { | 
 | 465 |             // TODO(jessehall): Improve error reporting. Can we enumerate | 
 | 466 |             // possible errors and translate them to valid Vulkan result codes? | 
 | 467 |             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 468 |             result = VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 469 |             break; | 
 | 470 |         } | 
 | 471 |         img.buffer = InitSharedPtr(device, buffer); | 
| Jesse Hall | 26cecff | 2016-01-21 19:52:25 -0800 | [diff] [blame] | 472 |         if (!img.buffer) { | 
 | 473 |             ALOGE("swapchain creation failed: out of memory"); | 
 | 474 |             surface.window->cancelBuffer(surface.window.get(), buffer, | 
 | 475 |                                          img.dequeue_fence); | 
 | 476 |             result = VK_ERROR_OUT_OF_HOST_MEMORY; | 
 | 477 |             break; | 
 | 478 |         } | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 479 |         img.dequeued = true; | 
 | 480 |  | 
 | 481 |         image_create.extent = | 
| Jesse Hall | 3dd678a | 2016-01-08 21:52:01 -0800 | [diff] [blame] | 482 |             VkExtent3D{static_cast<uint32_t>(img.buffer->width), | 
 | 483 |                        static_cast<uint32_t>(img.buffer->height), | 
 | 484 |                        1}; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 485 |         image_native_buffer.handle = img.buffer->handle; | 
 | 486 |         image_native_buffer.stride = img.buffer->stride; | 
 | 487 |         image_native_buffer.format = img.buffer->format; | 
 | 488 |         image_native_buffer.usage = img.buffer->usage; | 
 | 489 |  | 
| Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 490 |         result = | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 491 |             dispatch.CreateImage(device, &image_create, nullptr, &img.image); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 492 |         if (result != VK_SUCCESS) { | 
 | 493 |             ALOGD("vkCreateImage w/ native buffer failed: %u", result); | 
 | 494 |             break; | 
 | 495 |         } | 
 | 496 |     } | 
 | 497 |  | 
 | 498 |     // -- Cancel all buffers, returning them to the queue -- | 
 | 499 |     // If an error occurred before, also destroy the VkImage and release the | 
 | 500 |     // buffer reference. Otherwise, we retain a strong reference to the buffer. | 
 | 501 |     // | 
 | 502 |     // TODO(jessehall): The error path here is the same as DestroySwapchain, | 
 | 503 |     // but not the non-error path. Should refactor/unify. | 
 | 504 |     for (uint32_t i = 0; i < num_images; i++) { | 
 | 505 |         Swapchain::Image& img = swapchain->images[i]; | 
 | 506 |         if (img.dequeued) { | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 507 |             surface.window->cancelBuffer(surface.window.get(), img.buffer.get(), | 
 | 508 |                                          img.dequeue_fence); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 509 |             img.dequeue_fence = -1; | 
 | 510 |             img.dequeued = false; | 
 | 511 |         } | 
 | 512 |         if (result != VK_SUCCESS) { | 
 | 513 |             if (img.image) | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 514 |                 dispatch.DestroyImage(device, img.image, nullptr); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 515 |         } | 
 | 516 |     } | 
 | 517 |  | 
 | 518 |     if (result != VK_SUCCESS) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 519 |         swapchain->~Swapchain(); | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 520 |         allocator->pfnFree(allocator->pUserData, swapchain); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 521 |         return result; | 
 | 522 |     } | 
 | 523 |  | 
 | 524 |     *swapchain_handle = HandleFromSwapchain(swapchain); | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 525 |     return VK_SUCCESS; | 
 | 526 | } | 
 | 527 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 528 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 529 | void DestroySwapchainKHR_Bottom(VkDevice device, | 
 | 530 |                                 VkSwapchainKHR swapchain_handle, | 
 | 531 |                                 const VkAllocationCallbacks* allocator) { | 
 | 532 |     const DriverDispatchTable& dispatch = GetDriverDispatch(device); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 533 |     Swapchain* swapchain = SwapchainFromHandle(swapchain_handle); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 534 |     const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 535 |  | 
 | 536 |     for (uint32_t i = 0; i < swapchain->num_images; i++) { | 
 | 537 |         Swapchain::Image& img = swapchain->images[i]; | 
 | 538 |         if (img.dequeued) { | 
 | 539 |             window->cancelBuffer(window.get(), img.buffer.get(), | 
 | 540 |                                  img.dequeue_fence); | 
 | 541 |             img.dequeue_fence = -1; | 
 | 542 |             img.dequeued = false; | 
 | 543 |         } | 
 | 544 |         if (img.image) { | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 545 |             dispatch.DestroyImage(device, img.image, nullptr); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 546 |         } | 
 | 547 |     } | 
 | 548 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 549 |     if (!allocator) | 
 | 550 |         allocator = GetAllocator(device); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 551 |     swapchain->~Swapchain(); | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 552 |     allocator->pfnFree(allocator->pUserData, swapchain); | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 553 | } | 
 | 554 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 555 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 556 | VkResult GetSwapchainImagesKHR_Bottom(VkDevice, | 
 | 557 |                                       VkSwapchainKHR swapchain_handle, | 
 | 558 |                                       uint32_t* count, | 
 | 559 |                                       VkImage* images) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 560 |     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); | 
 | 561 |     VkResult result = VK_SUCCESS; | 
 | 562 |     if (images) { | 
 | 563 |         uint32_t n = swapchain.num_images; | 
 | 564 |         if (*count < swapchain.num_images) { | 
 | 565 |             n = *count; | 
 | 566 |             result = VK_INCOMPLETE; | 
 | 567 |         } | 
 | 568 |         for (uint32_t i = 0; i < n; i++) | 
 | 569 |             images[i] = swapchain.images[i].image; | 
 | 570 |     } | 
 | 571 |     *count = swapchain.num_images; | 
 | 572 |     return result; | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 573 | } | 
 | 574 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 575 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 576 | VkResult AcquireNextImageKHR_Bottom(VkDevice device, | 
 | 577 |                                     VkSwapchainKHR swapchain_handle, | 
 | 578 |                                     uint64_t timeout, | 
 | 579 |                                     VkSemaphore semaphore, | 
 | 580 |                                     VkFence vk_fence, | 
 | 581 |                                     uint32_t* image_index) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 582 |     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 583 |     ANativeWindow* window = swapchain.surface.window.get(); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 584 |     VkResult result; | 
 | 585 |     int err; | 
 | 586 |  | 
 | 587 |     ALOGW_IF( | 
 | 588 |         timeout != UINT64_MAX, | 
 | 589 |         "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented"); | 
 | 590 |  | 
 | 591 |     ANativeWindowBuffer* buffer; | 
| Jesse Hall | 0619380 | 2015-12-03 16:12:51 -0800 | [diff] [blame] | 592 |     int fence_fd; | 
 | 593 |     err = window->dequeueBuffer(window, &buffer, &fence_fd); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 594 |     if (err != 0) { | 
 | 595 |         // TODO(jessehall): Improve error reporting. Can we enumerate possible | 
 | 596 |         // errors and translate them to valid Vulkan result codes? | 
 | 597 |         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err); | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 598 |         return VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 599 |     } | 
 | 600 |  | 
 | 601 |     uint32_t idx; | 
 | 602 |     for (idx = 0; idx < swapchain.num_images; idx++) { | 
 | 603 |         if (swapchain.images[idx].buffer.get() == buffer) { | 
 | 604 |             swapchain.images[idx].dequeued = true; | 
| Jesse Hall | 0619380 | 2015-12-03 16:12:51 -0800 | [diff] [blame] | 605 |             swapchain.images[idx].dequeue_fence = fence_fd; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 606 |             break; | 
 | 607 |         } | 
 | 608 |     } | 
 | 609 |     if (idx == swapchain.num_images) { | 
 | 610 |         ALOGE("dequeueBuffer returned unrecognized buffer"); | 
| Jesse Hall | 0619380 | 2015-12-03 16:12:51 -0800 | [diff] [blame] | 611 |         window->cancelBuffer(window, buffer, fence_fd); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 612 |         return VK_ERROR_OUT_OF_DATE_KHR; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 613 |     } | 
 | 614 |  | 
 | 615 |     int fence_clone = -1; | 
| Jesse Hall | 0619380 | 2015-12-03 16:12:51 -0800 | [diff] [blame] | 616 |     if (fence_fd != -1) { | 
 | 617 |         fence_clone = dup(fence_fd); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 618 |         if (fence_clone == -1) { | 
 | 619 |             ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", | 
 | 620 |                   strerror(errno), errno); | 
| Jesse Hall | 0619380 | 2015-12-03 16:12:51 -0800 | [diff] [blame] | 621 |             sync_wait(fence_fd, -1 /* forever */); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 622 |         } | 
 | 623 |     } | 
 | 624 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 625 |     result = GetDriverDispatch(device).AcquireImageANDROID( | 
 | 626 |         device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 627 |     if (result != VK_SUCCESS) { | 
| Jesse Hall | ab9aeef | 2015-11-04 10:56:20 -0800 | [diff] [blame] | 628 |         // NOTE: we're relying on AcquireImageANDROID to close fence_clone, | 
 | 629 |         // even if the call fails. We could close it ourselves on failure, but | 
 | 630 |         // that would create a race condition if the driver closes it on a | 
 | 631 |         // failure path: some other thread might create an fd with the same | 
 | 632 |         // number between the time the driver closes it and the time we close | 
 | 633 |         // it. We must assume one of: the driver *always* closes it even on | 
 | 634 |         // failure, or *never* closes it on failure. | 
| Jesse Hall | 0619380 | 2015-12-03 16:12:51 -0800 | [diff] [blame] | 635 |         window->cancelBuffer(window, buffer, fence_fd); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 636 |         swapchain.images[idx].dequeued = false; | 
 | 637 |         swapchain.images[idx].dequeue_fence = -1; | 
 | 638 |         return result; | 
 | 639 |     } | 
 | 640 |  | 
 | 641 |     *image_index = idx; | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 642 |     return VK_SUCCESS; | 
 | 643 | } | 
 | 644 |  | 
| Jesse Hall | e1b1278 | 2015-11-30 11:27:32 -0800 | [diff] [blame] | 645 | VKAPI_ATTR | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 646 | VkResult QueuePresentKHR_Bottom(VkQueue queue, | 
 | 647 |                                 const VkPresentInfoKHR* present_info) { | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 648 |     ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, | 
 | 649 |              "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d", | 
 | 650 |              present_info->sType); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 651 |     ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL"); | 
 | 652 |  | 
| Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 653 |     const DriverDispatchTable& dispatch = GetDriverDispatch(queue); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 654 |     VkResult final_result = VK_SUCCESS; | 
 | 655 |     for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) { | 
 | 656 |         Swapchain& swapchain = | 
| Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 657 |             *SwapchainFromHandle(present_info->pSwapchains[sc]); | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 658 |         ANativeWindow* window = swapchain.surface.window.get(); | 
| Jesse Hall | f4ab2b1 | 2015-11-30 16:04:55 -0800 | [diff] [blame] | 659 |         uint32_t image_idx = present_info->pImageIndices[sc]; | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 660 |         Swapchain::Image& img = swapchain.images[image_idx]; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 661 |         VkResult result; | 
 | 662 |         int err; | 
 | 663 |  | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 664 |         int fence = -1; | 
| Jesse Hall | 275d76c | 2016-01-08 22:39:16 -0800 | [diff] [blame] | 665 |         result = dispatch.QueueSignalReleaseImageANDROID( | 
 | 666 |             queue, present_info->waitSemaphoreCount, | 
 | 667 |             present_info->pWaitSemaphores, img.image, &fence); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 668 |         if (result != VK_SUCCESS) { | 
| Jesse Hall | ab9aeef | 2015-11-04 10:56:20 -0800 | [diff] [blame] | 669 |             ALOGE("QueueSignalReleaseImageANDROID failed: %d", result); | 
| Jesse Hall | a9e5703 | 2015-11-30 01:03:10 -0800 | [diff] [blame] | 670 |             if (present_info->pResults) | 
 | 671 |                 present_info->pResults[sc] = result; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 672 |             if (final_result == VK_SUCCESS) | 
 | 673 |                 final_result = result; | 
 | 674 |             // TODO(jessehall): What happens to the buffer here? Does the app | 
 | 675 |             // still own it or not, i.e. should we cancel the buffer? Hard to | 
 | 676 |             // do correctly without synchronizing, though I guess we could wait | 
 | 677 |             // for the queue to idle. | 
 | 678 |             continue; | 
 | 679 |         } | 
 | 680 |  | 
| Jesse Hall | 1356b0d | 2015-11-23 17:24:58 -0800 | [diff] [blame] | 681 |         err = window->queueBuffer(window, img.buffer.get(), fence); | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 682 |         if (err != 0) { | 
 | 683 |             // TODO(jessehall): What now? We should probably cancel the buffer, | 
 | 684 |             // I guess? | 
 | 685 |             ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err); | 
| Jesse Hall | a9e5703 | 2015-11-30 01:03:10 -0800 | [diff] [blame] | 686 |             if (present_info->pResults) | 
 | 687 |                 present_info->pResults[sc] = result; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 688 |             if (final_result == VK_SUCCESS) | 
| Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 689 |                 final_result = VK_ERROR_INITIALIZATION_FAILED; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 690 |             continue; | 
 | 691 |         } | 
 | 692 |  | 
 | 693 |         if (img.dequeue_fence != -1) { | 
 | 694 |             close(img.dequeue_fence); | 
 | 695 |             img.dequeue_fence = -1; | 
 | 696 |         } | 
 | 697 |         img.dequeued = false; | 
| Jesse Hall | a9e5703 | 2015-11-30 01:03:10 -0800 | [diff] [blame] | 698 |  | 
 | 699 |         if (present_info->pResults) | 
 | 700 |             present_info->pResults[sc] = VK_SUCCESS; | 
| Jesse Hall | d7b994a | 2015-09-07 14:17:37 -0700 | [diff] [blame] | 701 |     } | 
 | 702 |  | 
 | 703 |     return final_result; | 
 | 704 | } | 
| Jesse Hall | b1352bc | 2015-09-04 16:12:33 -0700 | [diff] [blame] | 705 |  | 
 | 706 | }  // namespace vulkan |