<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">I made some fairly straightforward comments. with that, and the squash you sent, 1-6 and 8-10 are</div><div class="gmail_quote"><br></div><div class="gmail_quote">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>></div><div class="gmail_quote"><br></div><div class="gmail_quote">I'd like to see the respin of patch 7 but I fully expect to give it my R-B almost immediately.</div><div class="gmail_quote"><br></div><div class="gmail_quote">--Jason<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">On Mon, Oct 16, 2017 at 11:55 AM, Chad Versace <span dir="ltr"><<a href="mailto:chadversary@chromium.org" target="_blank">chadversary@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This implementation is correct (afaict), but takes two shortcuts<br>
regarding the import/export of Android sync fds.<br>
<br>
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync<br>
fd into a VkSemaphore or VkFence, the driver instead simply blocks on<br>
the sync fd, then puts the VkSemaphore or VkFence into the signalled<br>
state. Thanks to implicit sync, this produces correct behavior (with<br>
extra latency overhead, perhaps) despite its ugliness.<br>
<br>
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDRO<wbr>ID to export<br>
a collection of wait semaphores as a sync fd, the driver instead<br>
submits the semaphores to the queue, then returns sync fd -1, which<br>
informs the caller that no additional synchronization is needed.<br>
Again, thanks to implicit sync, this produces correct behavior (with<br>
extra batch submission overhead) despite its ugliness.<br>
<br>
I chose to take the shortcuts instead of properly importing/exporting<br>
the sync fds for two reasons:<br>
<br>
Reason 1. I've already tested this patch with dEQP and with demos<br>
apps. It works. I wanted to get the tested patches into the tree now,<br>
and polish the implementation afterwards.<br>
<br>
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915<br>
supports neither Android's sync_fence, nor upstream's sync_file, nor<br>
drm_syncobj. Again, I tested these patches on Android with a 3.18<br>
kernel and they work.<br>
<br>
I plan to quickly follow-up with patches that remove the shortcuts and<br>
properly import/export the sync fds.<br>
<br>
Non-Testing<br>
===========<br>
I did not test at all using the Android.mk buildsystem. I probably<br>
broke it. Please test and review that.<br>
<br>
Testing<br>
=======<br>
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.<br>
The following pass (as of patchset v9):<br>
<br>
- a little spinning cube demo APK<br>
- several Sascha demos<br>
- dEQP-VK.info.*<br>
- dEQP-VK.api.wsi.android.*<br>
(except dEQP-VK.api.wsi.android.swapch<wbr>ain.*.image_usage, because<br>
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)<br>
- dEQP-VK.api.smoke.*<br>
- dEQP-VK.api.info.instance.*<br>
- dEQP-VK.api.info.device.*<br>
<br>
v2:<br>
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for<br>
the VkImage.<br>
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory<br>
during vkCreateImage. Instead, directly import its dma-buf during<br>
vkCreateImage with anv_bo_cache_import(). [for jekstrand]<br>
- Rebase onto Tapani's VK_EXT_debug_report changes.<br>
- Drop `CPPFLAGS += $(top_srcdir)/include/android`<wbr>. The dir does not<br>
exist.<br>
<br>
v3:<br>
- Delete duplicate #include "anv_private.h". [per Tapani]<br>
- Try to fix the Android-IA build in <a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a> by following<br>
Tapani's example.<br>
<br>
v4:<br>
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported<br>
gralloc buffer, just as we do for all other winsys buffers in<br>
anv_wsi.c. [found by Tapani]<br>
<br>
v5:<br>
- Really fix the Android-IA build by ensuring that <a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include<br>
before -Iframeworks/native/vulkan/inc<wbr>lude. [for Tapani]<br>
- In vkAcquireImageANDROID, submit signal operations to the<br>
VkSemaphore and VkFence. [for zhou]<br>
<br>
v6:<br>
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDR<wbr>OID().<br>
[found by zhou]<br>
- Improve comments in vkGetSwapchainGrallocUsageANDR<wbr>OID().<br>
<br>
v7:<br>
- Fix vkGetSwapchainGrallocUsageANDR<wbr>OID() to inspect its<br>
VkImageUsageFlags parameter. [for tfiga]<br>
- This fix regresses dEQP-VK.api.wsi.android.swapch<wbr>ain.*.image_usage<br>
because dEQP wants to create swapchains with<br>
VK_IMAGE_USAGE_STORAGE_BIT.<br>
<br>
v8:<br>
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]<br>
<br>
v8.1: (minor changes)<br>
- Drop errant hunks added by rerere in anv_device.c.<br>
- Drop explicit mention of VK_ANDROID_native_buffer in<br>
anv_entrypoints_gen.py. [for jekstrand]<br>
<br>
v9:<br>
- Isolate as much Android code as possible, moving it from anv_image.c<br>
to anv_android.c. Connect the files with anv_image_from_gralloc().<br>
Remove VkNativeBufferANDROID params from all anv_image.c<br>
funcs. [for krh]<br>
- Replace some intel_loge() with vk_errorf() in anv_android.c.<br>
- Use © in copyright line. [for krh]<br>
<br>
Reviewed-by: Tapani Pälli <<a href="mailto:tapani.palli@intel.com" target="_blank">tapani.palli@intel.com</a>> (v5)<br>
Cc: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>><br>
Cc: zhoucm1 <<a href="mailto:david1.zhou@amd.com" target="_blank">david1.zhou@amd.com</a>><br>
Cc: Tomasz Figa <<a href="mailto:tfiga@chromium.org" target="_blank">tfiga@chromium.org</a>><br>
Cc: Kristian H. Kristensen <<a href="mailto:hoegsberg@google.com" target="_blank">hoegsberg@google.com</a>><br>
---<br>
src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a> | 7 +-<br>
src/intel/Makefile.sources | 3 +<br>
src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a> | 2 +<br>
src/intel/vulkan/anv_android.<wbr>c | 416 ++++++++++++++++++++++++++++++<wbr>++<br>
src/intel/vulkan/anv_entrypoi<wbr>nts_gen.py | 4 +-<br>
src/intel/vulkan/anv_extensio<wbr>ns.py | 1 +<br>
src/intel/vulkan/anv_image.c | 20 +-<br>
src/intel/vulkan/anv_private.<wbr>h | 12 +<br>
8 files changed, 459 insertions(+), 6 deletions(-)<br>
create mode 100644 src/intel/vulkan/anv_android.c<br>
<br>
diff --git a/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a> b/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
index ee98e30c35..b9a0446f72 100644<br>
--- a/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
+++ b/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
@@ -28,6 +28,7 @@ VK_ENTRYPOINTS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_entry<wbr>points_ge<br>
VK_EXTENSIONS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_exten<wbr>sions.py<br>
<br>
VULKAN_COMMON_INCLUDES := \<br>
+ $(MESA_TOP)/include \<br>
$(MESA_TOP)/src/mapi \<br>
$(MESA_TOP)/src/gallium/auxili<wbr>ary \<br>
$(MESA_TOP)/src/gallium/includ<wbr>e \<br>
@@ -36,7 +37,8 @@ VULKAN_COMMON_INCLUDES := \<br>
$(MESA_TOP)/src/vulkan/util \<br>
$(MESA_TOP)/src/intel \<br>
$(MESA_TOP)/include/drm-uapi \<br>
- $(MESA_TOP)/src/intel/vulkan<br>
+ $(MESA_TOP)/src/intel/vulkan \<br>
+ frameworks/native/vulkan/incl<wbr>ude<br>
<br>
# libmesa_anv_entrypoints with header and dummy.c<br>
#<br>
@@ -243,7 +245,8 @@ LOCAL_MODULE_CLASS := SHARED_LIBRARIES<br>
LOCAL_LDFLAGS += -Wl,--build-id=sha1<br>
<br>
LOCAL_SRC_FILES := \<br>
- $(VULKAN_GEM_FILES)<br>
+ $(VULKAN_GEM_FILES) \<br>
+ $(VULKAN_ANDROID_FILES)<br>
<br>
LOCAL_C_INCLUDES := \<br>
$(VULKAN_COMMON_INCLUDES) \<br>
diff --git a/src/intel/Makefile.sources b/src/intel/Makefile.sources<br>
index da018dcc6a..5a09e6d916 100644<br>
--- a/src/intel/Makefile.sources<br>
+++ b/src/intel/Makefile.sources<br>
@@ -231,6 +231,9 @@ VULKAN_FILES := \<br>
vulkan/anv_wsi.c \<br>
vulkan/vk_format_info.h<br>
<br>
+VULKAN_ANDROID_FILES := \<br>
+ vulkan/anv_android.c<br>
+<br>
VULKAN_WSI_WAYLAND_FILES := \<br>
vulkan/anv_wsi_wayland.c<br>
<br>
diff --git a/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a> b/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a><br>
index 0f488fc9f6..811faab556 100644<br>
--- a/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a><br>
+++ b/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a><br>
@@ -147,8 +147,10 @@ VULKAN_LIB_DEPS = \<br>
-lm<br>
<br>
if HAVE_PLATFORM_ANDROID<br>
+VULKAN_CPPFLAGS += $(ANDROID_CPPFLAGS)<br>
VULKAN_CFLAGS += $(ANDROID_CFLAGS)<br>
VULKAN_LIB_DEPS += $(ANDROID_LIBS)<br>
+VULKAN_SOURCES += $(VULKAN_ANDROID_FILES)<br>
endif<br>
<br>
if HAVE_PLATFORM_X11<br>
diff --git a/src/intel/vulkan/anv_android<wbr>.c b/src/intel/vulkan/anv_android<wbr>.c<br>
new file mode 100644<br>
index 0000000000..73baaf1f54<br>
--- /dev/null<br>
+++ b/src/intel/vulkan/anv_android<wbr>.c<br>
@@ -0,0 +1,416 @@<br>
+/*<br>
+ * Copyright © 2017 Google<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include <hardware/gralloc.h><br>
+#include <hardware/hardware.h><br>
+#include <hardware/hwvulkan.h><br>
+#include <vulkan/vk_android_native_buff<wbr>er.h><br>
+#include <vulkan/vk_icd.h><br>
+#include <sync/sync.h><br>
+<br>
+#include "anv_private.h"<br>
+<br>
+static int anv_hal_open(const struct hw_module_t* mod, const char* id, struct hw_device_t** dev);<br>
+static int anv_hal_close(struct hw_device_t *dev);<br>
+<br>
+static void UNUSED<br>
+static_asserts(void)<br>
+{<br>
+ STATIC_ASSERT(HWVULKAN_DISPAT<wbr>CH_MAGIC == ICD_LOADER_MAGIC);<br>
+}<br>
+<br>
+PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {<br>
+ .common = {<br>
+ .tag = HARDWARE_MODULE_TAG,<br>
+ .module_api_version = HWVULKAN_MODULE_API_VERSION_0_<wbr>1,<br>
+ .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),<br>
+ .id = HWVULKAN_HARDWARE_MODULE_ID,<br>
+ .name = "Intel Vulkan HAL",<br>
+ .author = "Intel",<br>
+ .methods = &(hw_module_methods_t) {<br>
+ .open = anv_hal_open,<br>
+ },<br>
+ },<br>
+};<br>
+<br>
+/* If any bits in test_mask are set, then unset them and return true. */<br>
+static inline bool<br>
+unmask32(uint32_t *inout_mask, uint32_t test_mask)<br>
+{<br>
+ uint32_t orig_mask = *inout_mask;<br>
+ *inout_mask &= ~test_mask;<br>
+ return *inout_mask != orig_mask;<br>
+}<br>
+<br>
+static int<br>
+anv_hal_open(const struct hw_module_t* mod, const char* id,<br>
+ struct hw_device_t** dev)<br>
+{<br>
+ assert(mod == &HAL_MODULE_INFO_SYM.common);<br>
+ assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);<br>
+<br>
+ hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));<br>
+ if (!hal_dev)<br>
+ return -1;<br>
+<br>
+ *hal_dev = (hwvulkan_device_t) {<br>
+ .common = {<br>
+ .tag = HARDWARE_DEVICE_TAG,<br>
+ .version = HWVULKAN_DEVICE_API_VERSION_0_<wbr>1,<br>
+ .module = &HAL_MODULE_INFO_SYM.common,<br>
+ .close = anv_hal_close,<br>
+ },<br>
+ .EnumerateInstanceExtensionPr<wbr>operties = anv_EnumerateInstanceExtension<wbr>Properties,<br>
+ .CreateInstance = anv_CreateInstance,<br>
+ .GetInstanceProcAddr = anv_GetInstanceProcAddr,<br>
+ };<br>
+<br>
+ *dev = &hal_dev->common;<br>
+ return 0;<br>
+}<br>
+<br>
+static int<br>
+anv_hal_close(struct hw_device_t *dev)<br>
+{<br>
+ /* hwvulkan.h claims that hw_device_t::close() is never called. */<br>
+ return -1;<br>
+}<br>
+<br>
+VkResult<br>
+anv_image_from_gralloc(VkDevi<wbr>ce device_h,<br>
+ const VkImageCreateInfo *base_info,<br>
+ const VkNativeBufferANDROID *gralloc_info,<br>
+ const VkAllocationCallbacks *alloc,<br>
+ VkImage *out_image_h)<br>
+<br>
+{<br>
+ ANV_FROM_HANDLE(anv_device, device, device_h);<br>
+ VkImage image_h = VK_NULL_HANDLE;<br>
+ struct anv_image *image = NULL;<br>
+ struct anv_bo *bo = NULL;<br>
+ VkResult result;<br>
+<br>
+ struct anv_image_create_info anv_info = {<br>
+ .vk_info = base_info,<br>
+ .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT<wbr>,<br>
+ };<br>
+<br>
+ if (gralloc_info->handle->numFds != 1) {<br>
+ return vk_errorf(device->instance, device,<br>
+ VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+ "VkNativeBufferANDROID::handl<wbr>e::numFds is %d, "<br>
+ "expected 1", gralloc_info->handle->numFds);<br>
+ }<br>
+<br>
+ /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf<br>
+ * must exceed that of the gralloc handle, and we do not own the gralloc<br>
+ * handle.<br>
+ */<br>
+ int dma_buf = gralloc_info->handle->data[0];<br>
+<br>
+ result = anv_bo_cache_import(device, &device->bo_cache, dma_buf, &bo);<br>
+ if (result != VK_SUCCESS) {<br>
+ return vk_errorf(device->instance, device, result,<br>
+ "failed to import dma-buf from VkNativeBufferANDROID");<br>
+ }<br>
+<br>
+ int i915_tiling = anv_gem_get_tiling(device, bo->gem_handle);<br>
+ switch (i915_tiling) {<br>
+ case I915_TILING_NONE:<br>
+ anv_info.isl_tiling_flags = ISL_TILING_LINEAR_BIT;<br>
+ break;<br>
+ case I915_TILING_X:<br>
+ anv_info.isl_tiling_flags = ISL_TILING_X_BIT;<br>
+ break;<br>
+ case I915_TILING_Y:<br>
+ anv_info.isl_tiling_flags = ISL_TILING_Y0_BIT;<br></blockquote><div><br></div><div>We have isl_tiling_for_i915_tiling to do this. You may still want the switch statement for error handling purposes but I'm not a huge fan of repeated code. How about</div><div><br></div><div>if (i915_tiling < 0) {</div><div> /* Do the one error */<br></div><div>} else if (i915_tiling > I915_TILING_Y) {</div><div> /* Do the other error */</div><div>}</div><div>anv_info.isl_tiling_flags = 1u << isl_tiling_from_i915_tiling(<wbr>i915_tiling);</div><div><br></div><div>It's not really less code but it keeps things centralized.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ break;<br>
+ case -1:<br>
+ result = vk_errorf(device->instance, device,<br>
+ VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+ "DRM_IOCTL_I915_GEM_GET_<wbr>TILING failed for "<br>
+ "VkNativeBufferANDROID");<br>
+ goto fail_tiling;<br>
+ default:<br>
+ result = vk_errorf(device->instance, device,<br>
+ VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+ "DRM_IOCTL_I915_GEM_GET_<wbr>TILING returned unknown "<br>
+ "tiling %d for VkNativeBufferANDROID", i915_tiling);<br>
+ goto fail_tiling;<br>
+ }<br>
+<br>
+ enum isl_format format = anv_get_isl_format(&device->in<wbr>fo,<br>
+ base_info->format,<br>
+ VK_IMAGE_ASPECT_COLOR_BIT,<br>
+ base_info->tiling);<br></blockquote><div><br></div><div>Is base_info->tiling allowed to be anything other than OPTIMAL? Not that it really matters...<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ assert(format != ISL_FORMAT_UNSUPPORTED);<br>
+<br>
+ anv_info.stride = gralloc_info->stride *<br>
+ (isl_format_get_layout(<wbr>format)->bpb / 8);<br>
+<br>
+ result = anv_image_create(device_h, &anv_info, alloc, &image_h);<br>
+ image = anv_image_from_handle(image_h)<wbr>;<br>
+ if (result != VK_SUCCESS)<br>
+ goto fail_create;<br>
+<br>
+ if (bo->size < image->size) {<br>
+ result = vk_errorf(device, device->instance,<br>
+ VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+ "dma-buf from VkNativeBufferANDROID is too small for "<br>
+ "VkImage: %"PRIu64" < %"PRIu64,<br>
+ bo->size, image->size);<br>
+ goto fail_size;<br>
+ }<br>
+<br>
+ assert(image->n_planes == 1);<br>
+ assert(image->planes[0].bo_of<wbr>fset == 0);<br>
+<br>
+ image->planes[0].bo = bo;<br>
+ image->planes[0].bo_is_owned = true;<br>
+<br>
+ /* We need to set the WRITE flag on window system buffers so that GEM will<br>
+ * know we're writing to them and synchronize uses on other rings (for<br>
+ * example, if the display server uses the blitter ring).<br>
+ *<br>
+ * If this function fails and if the imported bo was resident in the cache,<br>
+ * we should avoid updating the bo's flags. Therefore, we defer updating<br>
+ * the flags until success is certain.<br>
+ *<br>
+ */<br>
+ bo->flags &= ~EXEC_OBJECT_ASYNC;<br>
+ bo->flags |= EXEC_OBJECT_WRITE;<br></blockquote><div><br></div><div>If Android is using sync_file, we shouldn't need this? Maybe we need it now and can delete it later? I just read the semaphore code below and answered my own question.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+ /* Don't clobber the out-parameter until success is certain. */<br>
+ *out_image_h = image_h;<br>
+<br>
+ return VK_SUCCESS;<br>
+<br>
+ fail_size:<br>
+ anv_DestroyImage(device_h, image_h, alloc);<br>
+ fail_create:<br>
+ fail_tiling:<br>
+ anv_bo_cache_release(device, &device->bo_cache, bo);<br>
+<br>
+ return result;<br>
+}<br>
+<br>
+VkResult anv_GetSwapchainGrallocUsageAN<wbr>DROID(<br>
+ VkDevice device_h,<br>
+ VkFormat format,<br>
+ VkImageUsageFlags imageUsage,<br>
+ int* grallocUsage)<br>
+{<br>
+ ANV_FROM_HANDLE(anv_device, device, device_h);<br>
+ struct anv_physical_device *phys_dev = &device->instance->physicalDev<wbr>ice;<br>
+ VkPhysicalDevice phys_dev_h = anv_physical_device_to_handle(<wbr>phys_dev);<br>
+ VkResult result;<br>
+<br>
+ *grallocUsage = 0;<br>
+ intel_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);<br>
+<br>
+ /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags<br>
+ * returned to applications via VkSurfaceCapabilitiesKHR::supp<wbr>ortedUsageFlags.<br>
+ * The relevant code in libvulkan/swapchain.cpp contains this fun comment:<br>
+ *<br>
+ * TODO(jessehall): I think these are right, but haven't thought hard<br>
+ * about it. Do we need to query the driver for support of any of<br>
+ * these?<br>
+ *<br>
+ * Any disagreement between this function and the hardcoded<br>
+ * VkSurfaceCapabilitiesKHR:suppo<wbr>rtedUsageFlags causes tests<br>
+ * dEQP-VK.wsi.android.swapchain.<wbr>*.image_usage to fail.<br>
+ */<br>
+<br>
+ const VkPhysicalDeviceImageFormatInf<wbr>o2KHR image_format_info = {<br>
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEV<wbr>ICE_IMAGE_FORMAT_INFO_2_KHR,<br>
+ .format = format,<br>
+ .type = VK_IMAGE_TYPE_2D,<br>
+ .tiling = VK_IMAGE_TILING_OPTIMAL,<br>
+ .usage = imageUsage,<br>
+ };<br>
+<br>
+ VkImageFormatProperties2KHR image_format_props = {<br>
+ .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT<wbr>_PROPERTIES_2_KHR,<br>
+ };<br>
+<br>
+ /* Check that requested format and usage are supported. */<br>
+ result = anv_GetPhysicalDeviceImageForm<wbr>atProperties2KHR(phys_dev_h,<br>
+ &image_format_info, &image_format_props);<br>
+ if (result != VK_SUCCESS) {<br>
+ return vk_errorf(device->instance, device, result,<br>
+ "anv_GetPhysicalDeviceImageFo<wbr>rmatProperties2KHR failed "<br>
+ "inside %s", __func__);<br>
+ }<br>
+<br>
+ /* Reject STORAGE here to avoid complexity elsewhere. */<br>
+ if (imageUsage & VK_IMAGE_USAGE_STORAGE_BIT) {<br>
+ return vk_errorf(device->instance, device, VK_ERROR_FORMAT_NOT_SUPPORTED,<br>
+ "VK_IMAGE_USAGE_STORAGE_BIT unsupported for gralloc "<br>
+ "swapchain");<br>
+ }<br>
+<br>
+ if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BI<wbr>T |<br>
+ VK_IMAGE_USAGE_COLOR_ATTACHME<wbr>NT_BIT))<br>
+ *grallocUsage |= GRALLOC_USAGE_HW_RENDER;<br>
+<br>
+ if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BI<wbr>T |<br>
+ VK_IMAGE_USAGE_SAMPLED_BIT |<br>
+ VK_IMAGE_USAGE_INPUT_ATTACHME<wbr>NT_BIT))<br>
+ *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;<br>
+<br>
+ /* All VkImageUsageFlags not explicitly checked here are unsupported for<br>
+ * gralloc swapchains.<br>
+ */<br>
+ if (imageUsage != 0) {<br>
+ return vk_errorf(device->instance, device, VK_ERROR_FORMAT_NOT_SUPPORTED,<br>
+ "unsupported VkImageUsageFlags(0x%x) for gralloc "<br>
+ "swapchain", imageUsage);<br>
+ }<br>
+<br>
+ /* The below formats support GRALLOC_USAGE_HW_FB (that is, display<br>
+ * scanout). This short list of formats is univserally supported on Intel<br>
+ * but is incomplete. The full set of supported formats is dependent on<br>
+ * kernel and hardware.<br>
+ *<br>
+ * FINISHME: Advertise all display-supported formats.<br>
+ */<br>
+ if (format == VK_FORMAT_B8G8R8A8_UNORM ||<br>
+ format == VK_FORMAT_B5G6R5_UNORM_PACK16) {<br>
+ *grallocUsage |= GRALLOC_USAGE_HW_FB |<br>
+ GRALLOC_USAGE_HW_COMPOSER |<br>
+ GRALLOC_USAGE_EXTERNAL_DISP;<br>
+ }<br>
+<br>
+ if (*grallocUsage == 0)<br>
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;<br>
+<br>
+ return VK_SUCCESS;<br>
+}<br>
+<br>
+VkResult<br>
+anv_AcquireImageANDROID(<br>
+ VkDevice device_h,<br>
+ VkImage image_h,<br>
+ int nativeFenceFd,<br>
+ VkSemaphore semaphore_h,<br>
+ VkFence fence_h)<br>
+{<br>
+ ANV_FROM_HANDLE(anv_device, device, device_h);<br>
+ VkResult result = VK_SUCCESS;<br>
+<br>
+ if (nativeFenceFd != -1) {<br>
+ /* As a simple, firstpass implementation of VK_ANDROID_native_buffer, we<br>
+ * block on the nativeFenceFd. This may introduce latency and is<br>
+ * definitiely inefficient, yet it's correct.<br>
+ *<br>
+ * FINISHME(chadv): Import the nativeFenceFd into the VkSemaphore and<br>
+ * VkFence.<br>
+ */<br>
+ if (sync_wait(nativeFenceFd, /*timeout*/ -1) < 0) {<br>
+ result = vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,<br>
+ "%s: failed to wait on nativeFenceFd=%d",<br>
+ __func__, nativeFenceFd);<br>
+ }<br>
+<br>
+ /* From VK_ANDROID_native_buffer's pseudo spec<br>
+ * (<a href="https://source.android.com/devices/graphics/implement-vulkan" rel="noreferrer" target="_blank">https://source.android.com/de<wbr>vices/graphics/implement-vulka<wbr>n</a>):<br>
+ *<br>
+ * The driver takes ownership of the fence fd and is responsible for<br>
+ * closing it [...] even if vkAcquireImageANDROID fails and returns<br>
+ * an error.<br>
+ */<br>
+ close(nativeFenceFd);<br>
+<br>
+ if (result != VK_SUCCESS)<br>
+ return result;<br>
+ }<br>
+<br>
+ if (semaphore_h || fence_h) {<br>
+ /* Thanks to implicit sync, the image is ready for GPU access. But we<br>
+ * must still put the semaphore into the "submit" state; otherwise the<br>
+ * client may get unexpected behavior if the client later uses it as<br>
+ * a wait semaphore.<br>
+ *<br>
+ * Because we blocked above on the nativeFenceFd, the image is also<br>
+ * ready for foreign-device access (including CPU access). But we must<br>
+ * still signal the fence; otherwise the client may get unexpected<br>
+ * behavior if the client later waits on it.<br>
+ *<br>
+ * For some values of anv_semaphore_type, we must submit the semaphore<br>
+ * to execbuf in order to signal it. Likewise for anv_fence_type.<br>
+ * Instead of open-coding here the signal operation for each<br>
+ * anv_semaphore_type and anv_fence_type, we piggy-back on<br>
+ * vkQueueSubmit.<br>
+ */<br></blockquote><div><br></div><div>This makes me sad.... Also, it works.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ const VkSubmitInfo submit = {<br>
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,<br>
+ .waitSemaphoreCount = 0,<br>
+ .commandBufferCount = 0,<br>
+ .signalSemaphoreCount = (semaphore_h ? 1 : 0),<br>
+ .pSignalSemaphores = &semaphore_h,<br>
+ };<br>
+<br>
+ result = anv_QueueSubmit(anv_queue_to_h<wbr>andle(&device->queue), 1,<br>
+ &submit, fence_h);<br>
+ if (result != VK_SUCCESS) {<br>
+ return vk_errorf(device->instance, device, result,<br>
+ "anv_QueueSubmit failed inside %s", __func__);<br>
+ }<br>
+ }<br>
+<br>
+ return VK_SUCCESS;<br>
+}<br>
+<br>
+VkResult<br>
+anv_QueueSignalReleaseImageAN<wbr>DROID(<br>
+ VkQueue queue,<br>
+ uint32_t waitSemaphoreCount,<br>
+ const VkSemaphore* pWaitSemaphores,<br>
+ VkImage image,<br>
+ int* pNativeFenceFd)<br>
+{<br>
+ VkResult result;<br>
+<br>
+ if (waitSemaphoreCount == 0)<br>
+ goto done;<br>
+<br>
+ result = anv_QueueSubmit(queue, 1,<br>
+ &(VkSubmitInfo) {<br>
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,<br>
+ .waitSemaphoreCount = 1,<br>
+ .pWaitSemaphores = pWaitSemaphores,<br>
+ },<br>
+ (VkFence) VK_NULL_HANDLE);<br>
+ if (result != VK_SUCCESS)<br>
+ return result;<br>
+<br>
+ done:<br>
+ if (pNativeFenceFd) {<br>
+ /* We can rely implicit on sync because above we submitted all<br>
+ * semaphores to the queue.<br>
+ */<br>
+ *pNativeFenceFd = -1;<br>
+ }<br>
+<br>
+ return VK_SUCCESS;<br>
+}<br>
diff --git a/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py b/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py<br>
index bf376a881f..334b6de54b 100644<br>
--- a/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py<br>
+++ b/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py<br>
@@ -270,7 +270,9 @@ def get_entrypoints(doc, entrypoints_to_defines, start_index):<br>
if extension.attrib['name'] not in supported:<br>
continue<br>
<br>
- assert extension.attrib['supported'] == 'vulkan'<br>
+ if extension.attrib['supported'] != 'vulkan':<br>
+ continue<br>
+<br>
for command in extension.findall('./require/c<wbr>ommand'):<br>
enabled_commands.add(command.<wbr>attrib['name'])<br>
<br>
diff --git a/src/intel/vulkan/anv_extensi<wbr>ons.py b/src/intel/vulkan/anv_extensi<wbr>ons.py<br>
index a828a668d6..b1e984b8cd 100644<br>
--- a/src/intel/vulkan/anv_extensi<wbr>ons.py<br>
+++ b/src/intel/vulkan/anv_extensi<wbr>ons.py<br>
@@ -50,6 +50,7 @@ class Extension:<br>
# the those extension strings, then tests dEQP-VK.api.info.instance.exte<wbr>nsions<br>
# and dEQP-VK.api.info.device fail due to the duplicated strings.<br>
EXTENSIONS = [<br>
+ Extension('VK_ANDROID_native_b<wbr>uffer', 5, 'ANDROID'),<br>
Extension('VK_KHR_bind_memory<wbr>2', 1, True),<br>
Extension('VK_KHR_dedicated_a<wbr>llocation', 1, True),<br>
Extension('VK_KHR_descriptor_<wbr>update_template', 1, True),<br>
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c<br>
index b80011e222..cd96bfd0d6 100644<br>
--- a/src/intel/vulkan/anv_image.c<br>
+++ b/src/intel/vulkan/anv_image.c<br>
@@ -40,9 +40,10 @@<br>
static isl_surf_usage_flags_t<br>
choose_isl_surf_usage(VkImage<wbr>CreateFlags vk_create_flags,<br>
VkImageUsageFlags vk_usage,<br>
+ isl_surf_usage_flags_t isl_extra_usage,<br>
VkImageAspectFlags aspect)<br>
{<br>
- isl_surf_usage_flags_t isl_usage = 0;<br>
+ isl_surf_usage_flags_t isl_usage = isl_extra_usage;<br>
<br>
if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)<br>
isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;<br>
@@ -290,6 +291,10 @@ make_surface(const struct anv_device *dev,<br>
anv_get_format_plane(&dev->in<wbr>fo, image->vk_format, aspect, image->tiling);<br>
struct anv_surface *anv_surf = &image->planes[plane].surface;<br>
<br>
+ const isl_surf_usage_flags_t usage =<br>
+ choose_isl_surf_usage(vk_info-<wbr>>flags, image->usage,<br>
+ anv_info->isl_extra_usage_flag<wbr>s, aspect);<br>
+<br>
/* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to<br>
* fall back to linear on Broadwell and earlier because we aren't<br>
* guaranteed that we can handle offsets correctly. On Sky Lake, the<br>
@@ -316,7 +321,7 @@ make_surface(const struct anv_device *dev,<br>
.samples = vk_info->samples,<br>
.min_alignment = 0,<br>
.row_pitch = anv_info->stride,<br>
- .usage = choose_isl_surf_usage(vk_info-<wbr>>flags, image->usage, aspect),<br>
+ .usage = usage,<br>
.tiling_flags = tiling_flags);<br>
<br>
/* isl_surf_init() will fail only if provided invalid input. Invalid input<br>
@@ -347,7 +352,7 @@ make_surface(const struct anv_device *dev,<br>
.samples = vk_info->samples,<br>
.min_alignment = 0,<br>
.row_pitch = anv_info->stride,<br>
- .usage = choose_isl_surf_usage(image->u<wbr>sage, image->usage, aspect),<br>
+ .usage = usage,<br>
.tiling_flags = ISL_TILING_ANY_MASK);<br>
<br>
/* isl_surf_init() will fail only if provided invalid input. Invalid input<br>
@@ -547,6 +552,15 @@ anv_CreateImage(VkDevice device,<br>
const VkAllocationCallbacks *pAllocator,<br>
VkImage *pImage)<br>
{<br>
+#ifdef ANDROID<br>
+ const VkNativeBufferANDROID *gralloc_info =<br>
+ vk_find_struct_const(pCreateIn<wbr>fo->pNext, NATIVE_BUFFER_ANDROID);<br>
+<br>
+ if (gralloc_info)<br>
+ return anv_image_from_gralloc(device, pCreateInfo, gralloc_info,<br>
+ pAllocator, pImage);<br>
+#endif<br>
+<br>
return anv_image_create(device,<br>
&(struct anv_image_create_info) {<br>
.vk_info = pCreateInfo,<br>
diff --git a/src/intel/vulkan/anv_private<wbr>.h b/src/intel/vulkan/anv_private<wbr>.h<br>
index b51d110514..36c7220679 100644<br>
--- a/src/intel/vulkan/anv_private<wbr>.h<br>
+++ b/src/intel/vulkan/anv_private<wbr>.h<br>
@@ -69,6 +69,7 @@ struct gen_l3_config;<br>
#include <vulkan/vulkan.h><br>
#include <vulkan/vulkan_intel.h><br>
#include <vulkan/vk_icd.h><br>
+#include <vulkan/vk_android_native_buff<wbr>er.h><br>
<br>
#include "anv_entrypoints.h"<br>
#include "isl/isl.h"<br>
@@ -2632,6 +2633,9 @@ struct anv_image_create_info {<br>
/** An opt-in bitmask which filters an ISL-mapping of the Vulkan tiling. */<br>
isl_tiling_flags_t isl_tiling_flags;<br>
<br>
+ /** These flags will be added to any derived from VkImageCreateInfo. */<br>
+ isl_surf_usage_flags_t isl_extra_usage_flags;<br>
+<br>
uint32_t stride;<br>
};<br>
<br>
@@ -2640,6 +2644,14 @@ VkResult anv_image_create(VkDevice _device,<br>
const VkAllocationCallbacks* alloc,<br>
VkImage *pImage);<br>
<br>
+#ifdef ANDROID<br>
+VkResult anv_image_from_gralloc(VkDevic<wbr>e device_h,<br>
+ const VkImageCreateInfo *base_info,<br>
+ const VkNativeBufferANDROID *gralloc_info,<br>
+ const VkAllocationCallbacks *alloc,<br>
+ VkImage *pImage);<br>
+#endif<br>
+<br>
const struct anv_surface *<br>
anv_image_get_surface_for_asp<wbr>ect_mask(const struct anv_image *image,<br>
VkImageAspectFlags aspect_mask);<br>
<span class="m_-8188284107046820196HOEnZb"><font color="#888888">--<br>
2.13.0<br>
<br>
</font></span></blockquote></div><br></div></div>