summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/amd/vulkan/Makefile.am7
-rw-r--r--src/amd/vulkan/Makefile.sources3
-rw-r--r--src/amd/vulkan/meson.build7
-rw-r--r--src/amd/vulkan/radv_android.c366
-rw-r--r--src/amd/vulkan/radv_device.c8
-rw-r--r--src/amd/vulkan/radv_image.c12
-rw-r--r--src/amd/vulkan/radv_private.h12
7 files changed, 410 insertions, 5 deletions
diff --git a/src/amd/vulkan/Makefile.am b/src/amd/vulkan/Makefile.am
index e1a04e8c7f1..a4e23cd28e0 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 c9d172c3b1b..a510d88d965 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 305a2f66f58..0cf2072404e 100644
--- a/src/amd/vulkan/meson.build
+++ b/src/amd/vulkan/meson.build
@@ -29,10 +29,11 @@ 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@'],
+ command : [
+ prog_python2, '@INPUT0@', '--xml', '@INPUT1@', '--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 00000000000..09da601dac9
--- /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 a9de6a58fd3..44581586873 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -1038,6 +1038,10 @@ VkResult radv_CreateDevice(
}
}
+#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;
#else
@@ -2581,7 +2585,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);
@@ -2757,7 +2761,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 72e62b39fbc..38c5da45fe7 100644
--- a/src/amd/vulkan/radv_image.c
+++ b/src/amd/vulkan/radv_image.c
@@ -1119,6 +1119,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
+
return radv_image_create(device,
&(struct radv_image_create_info) {
.vk_info = pCreateInfo,
@@ -1141,6 +1150,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 5c8f8e5176e..388f26b44bd 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"
@@ -532,6 +533,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;
uint32_t tess_offchip_block_dw_size;
@@ -1249,6 +1251,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
@@ -1341,6 +1346,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);