On 5 January 2018 at 03:38, Bas Nieuwenhuizen <ba...@chromium.org> wrote: > Passes > dEQP-VK.api.smoke.* > dEQP-VK.wsi.android.* > > with android-cts-7.1_r12 . > > Unlike the initial anv implementation this does > use syncobjs instead of waiting on the CPU. > > This is missing meson build coverage for now. > > One possible todo is that linux 4.15 now has a > sycall that allows us to export amdgpu fence to > a sync_file, which allows us not to force all > fences and semaphores to use syncobjs. However, > I had trouble with my kernel crashing regularly > with NULL pointers, and I'm not sure how beneficial > it is in the first place given that intel uses > syncobjs for all fences if available.
Happy to have these merged as-is, but I do wonder if we could refactor out most of radv_android.c into a wsi_android or some such to share with anv. The current WSI already has some magic flags to pass things like the no space for cmask flag. For all 3: Reviewed-by: Dave Airlie <airl...@redhat.com> Dave. > --- > src/amd/vulkan/Makefile.am | 7 + > src/amd/vulkan/Makefile.sources | 3 + > src/amd/vulkan/meson.build | 4 +- > src/amd/vulkan/radv_android.c | 366 > ++++++++++++++++++++++++++++++++++++++++ > src/amd/vulkan/radv_device.c | 7 +- > src/amd/vulkan/radv_image.c | 12 ++ > src/amd/vulkan/radv_private.h | 12 ++ > 7 files changed, 407 insertions(+), 4 deletions(-) > create mode 100644 src/amd/vulkan/radv_android.c > > diff --git a/src/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am > index e1a04e8c7f..a4e23cd28e 100644 > --- a/src/amd/vulkan/Makefile.am > +++ b/src/amd/vulkan/Makefile.am > @@ -99,6 +99,13 @@ VULKAN_LIB_DEPS += \ > $(WAYLAND_CLIENT_LIBS) > endif > > +if HAVE_PLATFORM_ANDROID > +AM_CPPFLAGS += $(ANDROID_CPPFLAGS) > +AM_CFLAGS += $(ANDROID_CFLAGS) > +VULKAN_LIB_DEPS += $(ANDROID_LIBS) > +VULKAN_SOURCES += $(VULKAN_ANDROID_FILES) > +endif > + > noinst_LTLIBRARIES = libvulkan_common.la > libvulkan_common_la_SOURCES = $(VULKAN_SOURCES) > > diff --git a/src/amd/vulkan/Makefile.sources b/src/amd/vulkan/Makefile.sources > index c9d172c3b1..a510d88d96 100644 > --- a/src/amd/vulkan/Makefile.sources > +++ b/src/amd/vulkan/Makefile.sources > @@ -69,6 +69,9 @@ VULKAN_FILES := \ > vk_format.h \ > $(RADV_WS_AMDGPU_FILES) > > +VULKAN_ANDROID_FILES := \ > + radv_android.c > + > VULKAN_WSI_WAYLAND_FILES := \ > radv_wsi_wayland.c > > diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build > index 93997350a2..fa23d28fbb 100644 > --- a/src/amd/vulkan/meson.build > +++ b/src/amd/vulkan/meson.build > @@ -29,10 +29,10 @@ radv_entrypoints = custom_target( > > radv_extensions_c = custom_target( > 'radv_extensions.c', > - input : ['radv_extensions.py', vk_api_xml], > + input : ['radv_extensions.py', vk_api_xml, vk_android_native_buffer_xml], > output : ['radv_extensions.c'], > command : [prog_python2, '@INPUT0@', '--xml', '@INPUT1@', > - '--out', '@OUTPUT@'], > + '--xml', '@INPUT2@', '--out', '@OUTPUT@'], > ) > > vk_format_table_c = custom_target( > diff --git a/src/amd/vulkan/radv_android.c b/src/amd/vulkan/radv_android.c > new file mode 100644 > index 0000000000..09da601dac > --- /dev/null > +++ b/src/amd/vulkan/radv_android.c > @@ -0,0 +1,366 @@ > +/* > + * Copyright © 2017, Google Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > DEALINGS > + * IN THE SOFTWARE. > + */ > + > +#include <hardware/gralloc.h> > +#include <hardware/hardware.h> > +#include <hardware/hwvulkan.h> > +#include <vulkan/vk_android_native_buffer.h> > +#include <vulkan/vk_icd.h> > +#include <libsync.h> > + > +#include "radv_private.h" > + > +static int radv_hal_open(const struct hw_module_t* mod, const char* id, > struct hw_device_t** dev); > +static int radv_hal_close(struct hw_device_t *dev); > + > +static void UNUSED > +static_asserts(void) > +{ > + STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC); > +} > + > +PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = { > + .common = { > + .tag = HARDWARE_MODULE_TAG, > + .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1, > + .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0), > + .id = HWVULKAN_HARDWARE_MODULE_ID, > + .name = "AMD Vulkan HAL", > + .author = "Google", > + .methods = &(hw_module_methods_t) { > + .open = radv_hal_open, > + }, > + }, > +}; > + > +/* If any bits in test_mask are set, then unset them and return true. */ > +static inline bool > +unmask32(uint32_t *inout_mask, uint32_t test_mask) > +{ > + uint32_t orig_mask = *inout_mask; > + *inout_mask &= ~test_mask; > + return *inout_mask != orig_mask; > +} > + > +static int > +radv_hal_open(const struct hw_module_t* mod, const char* id, > + struct hw_device_t** dev) > +{ > + assert(mod == &HAL_MODULE_INFO_SYM.common); > + assert(strcmp(id, HWVULKAN_DEVICE_0) == 0); > + > + hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev)); > + if (!hal_dev) > + return -1; > + > + *hal_dev = (hwvulkan_device_t) { > + .common = { > + .tag = HARDWARE_DEVICE_TAG, > + .version = HWVULKAN_DEVICE_API_VERSION_0_1, > + .module = &HAL_MODULE_INFO_SYM.common, > + .close = radv_hal_close, > + }, > + .EnumerateInstanceExtensionProperties = > radv_EnumerateInstanceExtensionProperties, > + .CreateInstance = radv_CreateInstance, > + .GetInstanceProcAddr = radv_GetInstanceProcAddr, > + }; > + > + *dev = &hal_dev->common; > + return 0; > +} > + > +static int > +radv_hal_close(struct hw_device_t *dev) > +{ > + /* hwvulkan.h claims that hw_device_t::close() is never called. */ > + return -1; > +} > + > +VkResult > +radv_image_from_gralloc(VkDevice device_h, > + const VkImageCreateInfo *base_info, > + const VkNativeBufferANDROID *gralloc_info, > + const VkAllocationCallbacks *alloc, > + VkImage *out_image_h) > + > +{ > + RADV_FROM_HANDLE(radv_device, device, device_h); > + VkImage image_h = VK_NULL_HANDLE; > + struct radv_image *image = NULL; > + struct radv_bo *bo = NULL; > + VkResult result; > + > + result = radv_image_create(device_h, > + &(struct radv_image_create_info) { > + .vk_info = base_info, > + .scanout = true, > + .no_metadata_planes = true}, > + alloc, > + &image_h); > + > + if (result != VK_SUCCESS) > + return result; > + > + if (gralloc_info->handle->numFds != 1) { > + return vk_errorf(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR, > + "VkNativeBufferANDROID::handle::numFds is > %d, " > + "expected 1", gralloc_info->handle->numFds); > + } > + > + /* Do not close the gralloc handle's dma_buf. The lifetime of the > dma_buf > + * must exceed that of the gralloc handle, and we do not own the > gralloc > + * handle. > + */ > + int dma_buf = gralloc_info->handle->data[0]; > + > + image = radv_image_from_handle(image_h); > + > + VkDeviceMemory memory_h; > + > + const VkMemoryDedicatedAllocateInfoKHR ded_alloc = { > + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, > + .pNext = NULL, > + .buffer = VK_NULL_HANDLE, > + .image = image_h > + }; > + > + const VkImportMemoryFdInfoKHR import_info = { > + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, > + .pNext = &ded_alloc, > + .handleType = > VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, > + .fd = dup(dma_buf), > + }; > + /* Find the first VRAM memory type, or GART for PRIME images. */ > + int memory_type_index = -1; > + for (int i = 0; i < > device->physical_device->memory_properties.memoryTypeCount; ++i) { > + bool is_local = > !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags & > VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); > + if (is_local) { > + memory_type_index = i; > + break; > + } > + } > + > + /* fallback */ > + if (memory_type_index == -1) > + memory_type_index = 0; > + > + result = radv_AllocateMemory(device_h, > + &(VkMemoryAllocateInfo) { > + .sType = > VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, > + .pNext = &import_info, > + .allocationSize = image->size, > + .memoryTypeIndex = > memory_type_index, > + }, > + alloc, > + &memory_h); > + if (result != VK_SUCCESS) > + goto fail_create_image; > + > + radv_BindImageMemory(device_h, image_h, memory_h, 0); > + > + image->owned_memory = memory_h; > + /* Don't clobber the out-parameter until success is certain. */ > + *out_image_h = image_h; > + > + return VK_SUCCESS; > + > +fail_create_image: > +fail_size: > + radv_DestroyImage(device_h, image_h, alloc); > + > + return result; > +} > + > +VkResult radv_GetSwapchainGrallocUsageANDROID( > + VkDevice device_h, > + VkFormat format, > + VkImageUsageFlags imageUsage, > + int* grallocUsage) > +{ > + RADV_FROM_HANDLE(radv_device, device, device_h); > + struct radv_physical_device *phys_dev = device->physical_device; > + VkPhysicalDevice phys_dev_h = > radv_physical_device_to_handle(phys_dev); > + VkResult result; > + > + *grallocUsage = 0; > + > + /* WARNING: Android Nougat's libvulkan.so hardcodes the > VkImageUsageFlags > + * returned to applications via > VkSurfaceCapabilitiesKHR::supportedUsageFlags. > + * The relevant code in libvulkan/swapchain.cpp contains this fun > comment: > + * > + * TODO(jessehall): I think these are right, but haven't thought > hard > + * about it. Do we need to query the driver for support of any of > + * these? > + * > + * Any disagreement between this function and the hardcoded > + * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests > + * dEQP-VK.wsi.android.swapchain.*.image_usage to fail. > + */ > + > + const VkPhysicalDeviceImageFormatInfo2KHR image_format_info = { > + .sType = > VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR, > + .format = format, > + .type = VK_IMAGE_TYPE_2D, > + .tiling = VK_IMAGE_TILING_OPTIMAL, > + .usage = imageUsage, > + }; > + > + VkImageFormatProperties2KHR image_format_props = { > + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, > + }; > + > + /* Check that requested format and usage are supported. */ > + result = radv_GetPhysicalDeviceImageFormatProperties2KHR(phys_dev_h, > + > &image_format_info, &image_format_props); > + if (result != VK_SUCCESS) { > + return vk_errorf(result, > + > "radv_GetPhysicalDeviceImageFormatProperties2KHR failed " > + "inside %s", __func__); > + } > + > + if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | > + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) > + *grallocUsage |= GRALLOC_USAGE_HW_RENDER; > + > + if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | > + VK_IMAGE_USAGE_SAMPLED_BIT | > + VK_IMAGE_USAGE_STORAGE_BIT | > + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) > + *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE; > + > + /* All VkImageUsageFlags not explicitly checked here are unsupported > for > + * gralloc swapchains. > + */ > + if (imageUsage != 0) { > + return vk_errorf(VK_ERROR_FORMAT_NOT_SUPPORTED, > + "unsupported VkImageUsageFlags(0x%x) for gralloc " > + "swapchain", imageUsage); > + } > + > + /* > + * FINISHME: Advertise all display-supported formats. Mostly > + * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check > + * what we need for 30-bit colors. > + */ > + if (format == VK_FORMAT_B8G8R8A8_UNORM || > + format == VK_FORMAT_B5G6R5_UNORM_PACK16) { > + *grallocUsage |= GRALLOC_USAGE_HW_FB | > + GRALLOC_USAGE_HW_COMPOSER | > + GRALLOC_USAGE_EXTERNAL_DISP; > + } > + > + if (*grallocUsage == 0) > + return VK_ERROR_FORMAT_NOT_SUPPORTED; > + > + return VK_SUCCESS; > +} > + > +VkResult > +radv_AcquireImageANDROID( > + VkDevice device, > + VkImage image_h, > + int nativeFenceFd, > + VkSemaphore semaphore, > + VkFence fence) > +{ > + VkResult semaphore_result = VK_SUCCESS, fence_result = VK_SUCCESS; > + > + if (semaphore != VK_NULL_HANDLE) { > + int semaphore_fd = nativeFenceFd >= 0 ? dup(nativeFenceFd) : > nativeFenceFd; > + semaphore_result = radv_ImportSemaphoreFdKHR(device, > + > &(VkImportSemaphoreFdInfoKHR) { > + .sType = > VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, > + .flags = > VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR, > + .fd = > semaphore_fd, > + .semaphore = > semaphore, > + }); > + } > + > + if (fence != VK_NULL_HANDLE) { > + int fence_fd = nativeFenceFd >= 0 ? dup(nativeFenceFd) : > nativeFenceFd; > + fence_result = radv_ImportFenceFdKHR(device, > + > &(VkImportFenceFdInfoKHR) { > + .sType = > VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, > + .flags = > VK_FENCE_IMPORT_TEMPORARY_BIT_KHR, > + .fd = fence_fd, > + .fence = fence, > + }); > + } > + > + close(nativeFenceFd); > + > + if (semaphore_result != VK_SUCCESS) > + return semaphore_result; > + return fence_result; > +} > + > +VkResult > +radv_QueueSignalReleaseImageANDROID( > + VkQueue _queue, > + uint32_t waitSemaphoreCount, > + const VkSemaphore* pWaitSemaphores, > + VkImage image, > + int* pNativeFenceFd) > +{ > + RADV_FROM_HANDLE(radv_queue, queue, _queue); > + VkResult result = VK_SUCCESS; > + > + if (waitSemaphoreCount == 0) { > + if (pNativeFenceFd) > + *pNativeFenceFd = -1; > + return VK_SUCCESS; > + } > + > + int fd = -1; > + > + for (uint32_t i = 0; i < waitSemaphoreCount; ++i) { > + int tmp_fd; > + result = > radv_GetSemaphoreFdKHR(radv_device_to_handle(queue->device), > + &(VkSemaphoreGetFdInfoKHR) { > + .sType = > VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, > + .handleType = > VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR, > + .semaphore = > pWaitSemaphores[i], > + }, &tmp_fd); > + if (result != VK_SUCCESS) { > + if (fd >= 0) > + close (fd); > + return result; > + } > + > + if (fd < 0) > + fd = tmp_fd; > + else if (tmp_fd >= 0) { > + sync_accumulate("radv", &fd, tmp_fd); > + close(tmp_fd); > + } > + } > + > + if (pNativeFenceFd) { > + *pNativeFenceFd = fd; > + } else if (fd >= 0) { > + close(fd); > + /* We still need to do the exports, to reset the semaphores, > but > + * otherwise we don't wait on them. */ > + } > + return VK_SUCCESS; > +} > diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c > index cbf8f5cf49..4751b7ab6c 100644 > --- a/src/amd/vulkan/radv_device.c > +++ b/src/amd/vulkan/radv_device.c > @@ -1087,6 +1087,9 @@ VkResult radv_CreateDevice( > /* Disabled and not implemented for now. */ > device->dfsm_allowed = device->pbb_allowed && false; > > +#ifdef ANDROID > + device->always_use_syncobj = > device->physical_device->rad_info.has_syncobj_wait_for_submit; > +#endif > > #if HAVE_LLVM < 0x0400 > device->llvm_supports_spill = false; > @@ -2656,7 +2659,7 @@ VkResult radv_CreateFence( > fence->submitted = false; > fence->signalled = !!(pCreateInfo->flags & > VK_FENCE_CREATE_SIGNALED_BIT); > fence->temp_syncobj = 0; > - if (handleTypes) { > + if (device->always_use_syncobj || handleTypes) { > int ret = device->ws->create_syncobj(device->ws, > &fence->syncobj); > if (ret) { > vk_free2(&device->alloc, pAllocator, fence); > @@ -2832,7 +2835,7 @@ VkResult radv_CreateSemaphore( > > sem->temp_syncobj = 0; > /* create a syncobject if we are going to export this semaphore */ > - if (handleTypes) { > + if (device->always_use_syncobj || handleTypes) { > assert (device->physical_device->rad_info.has_syncobj); > int ret = device->ws->create_syncobj(device->ws, > &sem->syncobj); > if (ret) { > diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c > index d69ae8af48..54b2b5247d 100644 > --- a/src/amd/vulkan/radv_image.c > +++ b/src/amd/vulkan/radv_image.c > @@ -1147,6 +1147,15 @@ radv_CreateImage(VkDevice device, > const VkAllocationCallbacks *pAllocator, > VkImage *pImage) > { > +#ifdef ANDROID > + const VkNativeBufferANDROID *gralloc_info = > + vk_find_struct_const(pCreateInfo->pNext, > NATIVE_BUFFER_ANDROID); > + > + if (gralloc_info) > + return radv_image_from_gralloc(device, pCreateInfo, > gralloc_info, > + pAllocator, pImage); > +#endif > + > const struct wsi_image_create_info *wsi_info = > vk_find_struct_const(pCreateInfo->pNext, > WSI_IMAGE_CREATE_INFO_MESA); > bool scanout = wsi_info && wsi_info->scanout; > @@ -1173,6 +1182,9 @@ radv_DestroyImage(VkDevice _device, VkImage _image, > if (image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) > device->ws->buffer_destroy(image->bo); > > + if (image->owned_memory != VK_NULL_HANDLE) > + radv_FreeMemory(_device, image->owned_memory, pAllocator); > + > vk_free2(&device->alloc, pAllocator, image); > } > > diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h > index c15b044d00..e8cd7fe9b7 100644 > --- a/src/amd/vulkan/radv_private.h > +++ b/src/amd/vulkan/radv_private.h > @@ -69,6 +69,7 @@ typedef uint32_t xcb_window_t; > #include <vulkan/vulkan.h> > #include <vulkan/vulkan_intel.h> > #include <vulkan/vk_icd.h> > +#include <vulkan/vk_android_native_buffer.h> > > #include "radv_entrypoints.h" > > @@ -581,6 +582,7 @@ struct radv_device { > int queue_count[RADV_MAX_QUEUE_FAMILIES]; > struct radeon_winsys_cs *empty_cs[RADV_MAX_QUEUE_FAMILIES]; > > + bool always_use_syncobj; > bool llvm_supports_spill; > bool has_distributed_tess; > bool pbb_allowed; > @@ -1340,6 +1342,9 @@ struct radv_image { > struct radv_cmask_info cmask; > uint64_t clear_value_offset; > uint64_t dcc_pred_offset; > + > + /* For VK_ANDROID_native_buffer, the WSI image owns the memory, */ > + VkDeviceMemory owned_memory; > }; > > /* Whether the image has a htile that is known consistent with the contents > of > @@ -1434,6 +1439,13 @@ VkResult radv_image_create(VkDevice _device, > const VkAllocationCallbacks* alloc, > VkImage *pImage); > > +VkResult > +radv_image_from_gralloc(VkDevice device_h, > + const VkImageCreateInfo *base_info, > + const VkNativeBufferANDROID *gralloc_info, > + const VkAllocationCallbacks *alloc, > + VkImage *out_image_h); > + > void radv_image_view_init(struct radv_image_view *view, > struct radv_device *device, > const VkImageViewCreateInfo* pCreateInfo); > -- > 2.16.0.rc0.223.g4a4ac83678-goog > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev