vulkan: Add acquire fence fix to sdk-0.10 patch stack
Change-Id: I1cd113fd9f534ead89cc68ae35615d260c43df9c
(cherry picked from commit ed10d8ff02ae068d39ebde2b47b030790b0f3ffa)
diff --git a/vulkan/patches/frameworks_native-sdk_0.10/0032-libvulkan-Implement-new-VkFence-parameter-in-vkAcqui.patch b/vulkan/patches/frameworks_native-sdk_0.10/0032-libvulkan-Implement-new-VkFence-parameter-in-vkAcqui.patch
new file mode 100644
index 0000000..74dadaf
--- /dev/null
+++ b/vulkan/patches/frameworks_native-sdk_0.10/0032-libvulkan-Implement-new-VkFence-parameter-in-vkAcqui.patch
@@ -0,0 +1,478 @@
+From a7d7f27007e1e251b889b80c162e88507925fdff Mon Sep 17 00:00:00 2001
+From: Jesse Hall <jessehall@google.com>
+Date: Thu, 3 Dec 2015 16:12:51 -0800
+Subject: [PATCH] libvulkan: Implement new VkFence parameter in
+ vkAcquireNextImageKHR
+
+This parameter was added recently but wasn't hooked up. This adds a
+new parameter to the vkAcquireImageANDROID extension function, and
+plumbs the fence through from vkAcquireNextImageKHR to it.
+
+This change also fixes some function signatures for API functions that
+are implemented in the loader bottom rather than the driver. These
+functions are only ever called through function pointers returned by
+vkGet*ProcAddr, and therefore pass through a cast to
+PFN_vkVoidFunction. So the compiler had no way to know they were
+supposed to match a particular prototype, and couldn't issue an error
+when they didn't. This change adds explicit static casts to the
+expected function pointer type before reinterpret casting to the
+generic function pointer type to enable compile errors.
+
+Change-Id: I8a7e065502f783d5f2381b43c880644868234f8f
+---
+ .../doc/implementors_guide/implementors_guide.adoc | 29 +++++++++++---
+ .../doc/implementors_guide/implementors_guide.html | 39 ++++++++++++++++---
+ vulkan/include/vulkan/vk_android_native_buffer.h | 24 ++++++------
+ vulkan/libvulkan/loader.cpp | 45 ++++++++++++++--------
+ vulkan/libvulkan/loader.h | 29 +++++++-------
+ vulkan/libvulkan/swapchain.cpp | 30 +++++++--------
+ 6 files changed, 132 insertions(+), 64 deletions(-)
+
+diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc
+index 60a6f61..97eff48 100644
+--- a/vulkan/doc/implementors_guide/implementors_guide.adoc
++++ b/vulkan/doc/implementors_guide/implementors_guide.adoc
+@@ -2,7 +2,7 @@
+ = Vulkan on Android Implementor's Guide =
+ :toc: right
+ :numbered:
+-:revnumber: 3
++:revnumber: 4
+
+ This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.
+
+@@ -99,7 +99,9 @@ When creating a gralloc-backed image, the +VkImageCreateInfo+ will have:
+ .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices
+ ----
+
+-+vkAcquireImageANDROID+ acquires ownership of a swapchain image and imports an externally-signalled native fence into an existing +VkSemaphore+ object:
+++vkAcquireImageANDROID+ acquires ownership of a swapchain image and imports an
++externally-signalled native fence into both an existing VkSemaphore object
++and an existing VkFence object:
+
+ [source,c]
+ ----
+@@ -107,12 +109,26 @@ VkResult VKAPI vkAcquireImageANDROID(
+ VkDevice device,
+ VkImage image,
+ int nativeFenceFd,
+- VkSemaphore semaphore
+-);
++ VkSemaphore semaphore,
++ VkFence fence
+ );
+ ----
+
+-This function is called during +vkAcquireNextImageWSI+ to import a native fence into the +VkSemaphore+ object provided by the application. The driver may also use this opportunity to recognize and handle any external changes to the gralloc buffer state; many drivers won't need to do anything here. This call puts the +VkSemaphore+ into the same "pending" state as +vkQueueSignalSemaphore+, so queues can wait on the semaphore. The +VkSemaphore+ signals when the underlying native fence signals; if the fence has already signalled, then the semaphore will be in the signalled state when this function returns. The driver takes ownership of the fence fd and is responsible for closing it when the +VkSemaphore+ is destroyed, when a different native fence is imported, or any other condition that replaces the +VkSemaphore+'s underlying synchronization object. If +fenceFd+ is -1, the +VkSemaphore+ will be considered signalled immediately, but it can still be passed to +vkQueueWaitSemaphore+.
++This function is called during +vkAcquireNextImageWSI+ to import a native
++fence into the +VkSemaphore+ and +VkFence+ objects provided by the
++application. Both semaphore and fence objects are optional in this call. The
++driver may also use this opportunity to recognize and handle any external
++changes to the gralloc buffer state; many drivers won't need to do anything
++here. This call puts the +VkSemaphore+ and +VkFence+ into the same "pending"
++state as +vkQueueSignalSemaphore+ and +vkQueueSubmit+ respectively, so queues
++can wait on the semaphore and the application can wait on the fence. Both
++objects become signalled when the underlying native fence signals; if the
++native fence has already signalled, then the semaphore will be in the signalled
++state when this function returns. The driver takes ownership of the fence fd
++and is responsible for closing it when no longer needed. It must do so even if
++neither a semaphore or fence object is provided, or even if
+++vkAcquireImageANDROID+ fails and returns an error. If +fenceFd+ is -1, it
++is as if the native fence was already signalled.
+
+ +vkQueueSignalReleaseImageANDROID+ prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.
+
+@@ -140,3 +156,6 @@ This will be called during +vkQueuePresentWSI+ on the provided queue. Effects ar
+ * Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
+ with vkAcquireImageANDROID and vkQueueSignalReleaseImageANDROID, to allow
+ drivers to known the ownership state of swapchain images.
++. *2015-12-03*
++ * Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
++ parameter added to vkAcquireNextImageKHR.
+diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html
+index 8d6297a..00efca8 100644
+--- a/vulkan/doc/implementors_guide/implementors_guide.html
++++ b/vulkan/doc/implementors_guide/implementors_guide.html
+@@ -843,7 +843,9 @@ http://www.gnu.org/software/src-highlite -->
+ .queueFamilyCount = VkSwapChainCreateInfoWSI::queueFamilyCount
+ .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</pre>
+ </div></div>
+-<div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an externally-signalled native fence into an existing <span class="monospaced">VkSemaphore</span> object:</p></div>
++<div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an
++externally-signalled native fence into both an existing VkSemaphore object
++and an existing VkFence object:</p></div>
+ <div class="listingblock">
+ <div class="content"><!-- Generator: GNU source-highlight 3.1.6
+ by Lorenzo Bettini
+@@ -853,10 +855,24 @@ http://www.gnu.org/software/src-highlite -->
+ <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span>
+ <span style="color: #008080">VkImage</span> image<span style="color: #990000">,</span>
+ <span style="color: #009900">int</span> nativeFenceFd<span style="color: #990000">,</span>
+- VkSemaphore semaphore
+-<span style="color: #990000">);</span>
++ <span style="color: #008080">VkSemaphore</span> semaphore<span style="color: #990000">,</span>
++ VkFence fence
+ <span style="color: #990000">);</span></tt></pre></div></div>
+-<div class="paragraph"><p>This function is called during <span class="monospaced">vkAcquireNextImageWSI</span> to import a native fence into the <span class="monospaced">VkSemaphore</span> object provided by the application. The driver may also use this opportunity to recognize and handle any external changes to the gralloc buffer state; many drivers won’t need to do anything here. This call puts the <span class="monospaced">VkSemaphore</span> into the same "pending" state as <span class="monospaced">vkQueueSignalSemaphore</span>, so queues can wait on the semaphore. The <span class="monospaced">VkSemaphore</span> signals when the underlying native fence signals; if the fence has already signalled, then the semaphore will be in the signalled state when this function returns. The driver takes ownership of the fence fd and is responsible for closing it when the <span class="monospaced">VkSemaphore</span> is destroyed, when a different native fence is imported, or any other condition that replaces the <span class="monospaced">VkSemaphore</span>'s underlying synchronization object. If <span class="monospaced">fenceFd</span> is -1, the <span class="monospaced">VkSemaphore</span> will be considered signalled immediately, but it can still be passed to <span class="monospaced">vkQueueWaitSemaphore</span>.</p></div>
++<div class="paragraph"><p>This function is called during <span class="monospaced">vkAcquireNextImageWSI</span> to import a native
++fence into the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> objects provided by the
++application. Both semaphore and fence objects are optional in this call. The
++driver may also use this opportunity to recognize and handle any external
++changes to the gralloc buffer state; many drivers won’t need to do anything
++here. This call puts the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> into the same "pending"
++state as <span class="monospaced">vkQueueSignalSemaphore</span> and <span class="monospaced">vkQueueSubmit</span> respectively, so queues
++can wait on the semaphore and the application can wait on the fence. Both
++objects become signalled when the underlying native fence signals; if the
++native fence has already signalled, then the semaphore will be in the signalled
++state when this function returns. The driver takes ownership of the fence fd
++and is responsible for closing it when no longer needed. It must do so even if
++neither a semaphore or fence object is provided, or even if
++<span class="monospaced">vkAcquireImageANDROID</span> fails and returns an error. If <span class="monospaced">fenceFd</span> is -1, it
++is as if the native fence was already signalled.</p></div>
+ <div class="paragraph"><p><span class="monospaced">vkQueueSignalReleaseImageANDROID</span> prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
+ <div class="listingblock">
+ <div class="content"><!-- Generator: GNU source-highlight 3.1.6
+@@ -926,6 +942,19 @@ Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
+ </li>
+ </ul></div>
+ </li>
++<li>
++<p>
++<strong>2015-12-03</strong>
++</p>
++<div class="ulist"><ul>
++<li>
++<p>
++Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
++ parameter added to vkAcquireNextImageKHR.
++</p>
++</li>
++</ul></div>
++</li>
+ </ol></div>
+ </div>
+ </div>
+@@ -934,7 +963,7 @@ Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
+ <div id="footer">
+ <div id="footer-text">
+ Version 3<br>
+-Last updated 2015-11-04 10:58:22 PST
++Last updated 2015-12-03 15:47:36 PST
+ </div>
+ </div>
+ </body>
+diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
+index bf4641e..2fb8c14 100644
+--- a/vulkan/include/vulkan/vk_android_native_buffer.h
++++ b/vulkan/include/vulkan/vk_android_native_buffer.h
+@@ -17,21 +17,22 @@
+ #ifndef __VK_ANDROID_NATIVE_BUFFER_H__
+ #define __VK_ANDROID_NATIVE_BUFFER_H__
+
+-#include <vulkan/vulkan.h>
+ #include <system/window.h>
+-
+-// TODO(jessehall): Get a real extension number officially assigned.
+-#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 1024
+-#define VK_ANDROID_NATIVE_BUFFER_REVISION 1
+-#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME "VK_ANDROID_native_buffer"
++#include <vulkan/vulkan.h>
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+-// See https://gitlab.khronos.org/vulkan/vulkan/blob/master/doc/proposals/proposed/NVIDIA/VulkanRegistryProposal.txt
+-// and Khronos bug 14154 for explanation of these magic numbers.
+-#define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id) ((type)((int)0xc0000000 - VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER * -1024 + (id)))
++#define VK_ANDROID_native_buffer 1
++
++// Extension number not yet official, reservation request at:
++// https://gitlab.khronos.org/vulkan/vulkan/merge_requests/872
++#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 11
++#define VK_ANDROID_NATIVE_BUFFER_REVISION 4
++#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME "VK_ANDROID_native_buffer"
++
++#define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id) ((type)(1000000000 + (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
+ #define VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 0)
+
+ typedef struct {
+@@ -48,7 +49,7 @@ typedef struct {
+ } VkNativeBufferANDROID;
+
+ typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+-typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore);
++typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+ typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(VkQueue queue, VkImage image, int* pNativeFenceFd);
+ // -- DEPRECATED --
+ typedef VkResult (VKAPI_PTR *PFN_vkImportNativeFenceANDROID)(VkDevice device, VkSemaphore semaphore, int nativeFenceFd);
+@@ -66,7 +67,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID(
+ VkDevice device,
+ VkImage image,
+ int nativeFenceFd,
+- VkSemaphore semaphore
++ VkSemaphore semaphore,
++ VkFence fence
+ );
+ VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(
+ VkQueue queue,
+diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
+index defd691..ee9af85 100644
+--- a/vulkan/libvulkan/loader.cpp
++++ b/vulkan/libvulkan/loader.cpp
+@@ -539,33 +539,44 @@ VkBool32 LogDebugMessageCallback(VkFlags message_flags,
+ return false;
+ }
+
+-VkResult Noop(...) {
++VkResult Noop() {
+ return VK_SUCCESS;
+ }
+
+ VKAPI_ATTR PFN_vkVoidFunction
+ GetLayerDeviceProcAddr(VkDevice device, const char* name) {
++ // The static_casts are used to ensure that our function actually
++ // matches the API function prototype. Otherwise, if the API function
++ // prototype changes (only a problem during API development), the compiler
++ // has no way of knowing that the function is supposed to match the
++ // prototype, so won't warn us if they don't.
+ if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(GetLayerDeviceProcAddr);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkGetDeviceProcAddr>(GetLayerDeviceProcAddr));
+ }
+ if (strcmp(name, "vkCreateDevice") == 0) {
+ return reinterpret_cast<PFN_vkVoidFunction>(Noop);
+ }
+ // WSI extensions are not in the driver so return the loader functions
+ if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR));
+ }
+ if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR));
+ }
+ if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR));
+ }
+ if (strcmp(name, "vkAcquireNextImageKHR") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR));
+ }
+ if (strcmp(name, "vkQueuePresentKHR") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR));
+ }
+ if (!device)
+ return GetGlobalDeviceProcAddr(name);
+@@ -927,7 +938,8 @@ PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
+ return reinterpret_cast<PFN_vkVoidFunction>(Noop);
+ }
+ if (strcmp(name, "vkCreateInstance") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkCreateInstance>(CreateInstanceBottom));
+ }
+ return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
+ }
+@@ -1116,16 +1128,20 @@ PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
+ if (!device)
+ return GetGlobalDeviceProcAddr(name);
+ if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr));
+ }
+ if (strcmp(name, "vkGetDeviceQueue") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue));
+ }
+ if (strcmp(name, "vkAllocateCommandBuffers") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers));
+ }
+ if (strcmp(name, "vkDestroyDevice") == 0) {
+- return reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice);
++ return reinterpret_cast<PFN_vkVoidFunction>(
++ static_cast<PFN_vkDestroyDevice>(DestroyDevice));
+ }
+ return GetSpecificDeviceProcAddr(GetVtbl(device), name);
+ }
+@@ -1164,8 +1180,8 @@ VkResult AllocateCommandBuffers(VkDevice device,
+ return VK_SUCCESS;
+ }
+
+-VkResult DestroyDevice(VkDevice drv_device,
+- const VkAllocationCallbacks* /*allocator*/) {
++void DestroyDevice(VkDevice drv_device,
++ const VkAllocationCallbacks* /*allocator*/) {
+ const DeviceVtbl* vtbl = GetVtbl(drv_device);
+ Device* device = static_cast<Device*>(vtbl->device);
+ for (auto it = device->active_layers.begin();
+@@ -1174,7 +1190,6 @@ VkResult DestroyDevice(VkDevice drv_device,
+ }
+ vtbl->DestroyDevice(drv_device, device->instance->alloc);
+ DestroyDevice(device);
+- return VK_SUCCESS;
+ }
+
+ void* AllocMem(VkInstance instance,
+diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
+index e007f8d..65f11f4 100644
+--- a/vulkan/libvulkan/loader.h
++++ b/vulkan/libvulkan/loader.h
+@@ -215,16 +215,18 @@ VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance);
+ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name);
+-PFN_vkVoidFunction GetDeviceProcAddr(VkDevice drv_device, const char* name);
+-void GetDeviceQueue(VkDevice drv_device,
+- uint32_t family,
+- uint32_t index,
+- VkQueue* out_queue);
+-VkResult AllocateCommandBuffers(VkDevice device,
+- const VkCommandBufferAllocateInfo* alloc_info,
+- VkCommandBuffer* cmdbufs);
+-VkResult DestroyDevice(VkDevice drv_device,
+- const VkAllocationCallbacks* allocator);
++VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice drv_device,
++ const char* name);
++VKAPI_ATTR void GetDeviceQueue(VkDevice drv_device,
++ uint32_t family,
++ uint32_t index,
++ VkQueue* out_queue);
++VKAPI_ATTR VkResult
++AllocateCommandBuffers(VkDevice device,
++ const VkCommandBufferAllocateInfo* alloc_info,
++ VkCommandBuffer* cmdbufs);
++VKAPI_ATTR void DestroyDevice(VkDevice drv_device,
++ const VkAllocationCallbacks* allocator);
+
+ void* AllocMem(VkInstance instance,
+ size_t size,
+@@ -292,9 +294,9 @@ CreateSwapchainKHR(VkDevice device,
+ const VkSwapchainCreateInfoKHR* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkSwapchainKHR* swapchain_handle);
+-VKAPI_ATTR VkResult DestroySwapchainKHR(VkDevice device,
+- VkSwapchainKHR swapchain_handle,
+- const VkAllocationCallbacks* allocator);
++VKAPI_ATTR void DestroySwapchainKHR(VkDevice device,
++ VkSwapchainKHR swapchain_handle,
++ const VkAllocationCallbacks* allocator);
+ VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ uint32_t* count,
+@@ -303,6 +305,7 @@ VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ uint64_t timeout,
+ VkSemaphore semaphore,
++ VkFence fence,
+ uint32_t* image_index);
+ VKAPI_ATTR VkResult
+ QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
+index 39a581c..88e4d6f 100644
+--- a/vulkan/libvulkan/swapchain.cpp
++++ b/vulkan/libvulkan/swapchain.cpp
+@@ -487,9 +487,9 @@ VkResult CreateSwapchainKHR(VkDevice device,
+ }
+
+ VKAPI_ATTR
+-VkResult DestroySwapchainKHR(VkDevice device,
+- VkSwapchainKHR swapchain_handle,
+- const VkAllocationCallbacks* /*allocator*/) {
++void DestroySwapchainKHR(VkDevice device,
++ VkSwapchainKHR swapchain_handle,
++ const VkAllocationCallbacks* /*allocator*/) {
+ const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
+ Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
+ const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window;
+@@ -509,8 +509,6 @@ VkResult DestroySwapchainKHR(VkDevice device,
+
+ swapchain->~Swapchain();
+ FreeMem(device, swapchain);
+-
+- return VK_SUCCESS;
+ }
+
+ VKAPI_ATTR
+@@ -538,6 +536,7 @@ VkResult AcquireNextImageKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ uint64_t timeout,
+ VkSemaphore semaphore,
++ VkFence vk_fence,
+ uint32_t* image_index) {
+ Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+ ANativeWindow* window = swapchain.surface.window.get();
+@@ -549,8 +548,8 @@ VkResult AcquireNextImageKHR(VkDevice device,
+ "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
+
+ ANativeWindowBuffer* buffer;
+- int fence;
+- err = window->dequeueBuffer(window, &buffer, &fence);
++ int fence_fd;
++ err = window->dequeueBuffer(window, &buffer, &fence_fd);
+ if (err != 0) {
+ // TODO(jessehall): Improve error reporting. Can we enumerate possible
+ // errors and translate them to valid Vulkan result codes?
+@@ -562,30 +561,31 @@ VkResult AcquireNextImageKHR(VkDevice device,
+ for (idx = 0; idx < swapchain.num_images; idx++) {
+ if (swapchain.images[idx].buffer.get() == buffer) {
+ swapchain.images[idx].dequeued = true;
+- swapchain.images[idx].dequeue_fence = fence;
++ swapchain.images[idx].dequeue_fence = fence_fd;
+ break;
+ }
+ }
+ if (idx == swapchain.num_images) {
+ ALOGE("dequeueBuffer returned unrecognized buffer");
+- window->cancelBuffer(window, buffer, fence);
++ window->cancelBuffer(window, buffer, fence_fd);
+ return VK_ERROR_OUT_OF_DATE_KHR;
+ }
+
+ int fence_clone = -1;
+- if (fence != -1) {
+- fence_clone = dup(fence);
++ if (fence_fd != -1) {
++ fence_clone = dup(fence_fd);
+ if (fence_clone == -1) {
+ ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
+ strerror(errno), errno);
+- sync_wait(fence, -1 /* forever */);
++ sync_wait(fence_fd, -1 /* forever */);
+ }
+ }
+
+ const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
+ if (driver_vtbl.AcquireImageANDROID) {
+- result = driver_vtbl.AcquireImageANDROID(
+- device, swapchain.images[idx].image, fence_clone, semaphore);
++ result =
++ driver_vtbl.AcquireImageANDROID(device, swapchain.images[idx].image,
++ fence_clone, semaphore, vk_fence);
+ } else {
+ ALOG_ASSERT(driver_vtbl.ImportNativeFenceANDROID,
+ "Have neither vkAcquireImageANDROID nor "
+@@ -601,7 +601,7 @@ VkResult AcquireNextImageKHR(VkDevice device,
+ // number between the time the driver closes it and the time we close
+ // it. We must assume one of: the driver *always* closes it even on
+ // failure, or *never* closes it on failure.
+- window->cancelBuffer(window, buffer, fence);
++ window->cancelBuffer(window, buffer, fence_fd);
+ swapchain.images[idx].dequeued = false;
+ swapchain.images[idx].dequeue_fence = -1;
+ return result;
+--
+2.6.0.rc2.230.g3dd15c0
+