2021-04-03 20:14:00 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2021 Google LLC
|
|
|
|
* SPDX-License-Identifier: MIT
|
2021-04-12 02:33:05 +01:00
|
|
|
*
|
|
|
|
* based in part on anv and radv which are:
|
|
|
|
* Copyright © 2015 Intel Corporation
|
|
|
|
* Copyright © 2016 Red Hat
|
|
|
|
* Copyright © 2016 Bas Nieuwenhuizen
|
2021-04-03 20:14:00 +01:00
|
|
|
*/
|
|
|
|
|
2021-04-12 02:33:05 +01:00
|
|
|
#include "vn_android.h"
|
2021-04-03 20:14:00 +01:00
|
|
|
|
2021-04-30 18:20:54 +01:00
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <hardware/gralloc.h>
|
2021-04-03 20:14:00 +01:00
|
|
|
#include <hardware/hwvulkan.h>
|
2021-04-12 02:33:05 +01:00
|
|
|
#include <vndk/hardware_buffer.h>
|
2021-04-03 20:14:00 +01:00
|
|
|
#include <vulkan/vk_icd.h>
|
|
|
|
|
2021-06-17 23:03:02 +01:00
|
|
|
#include "drm-uapi/drm_fourcc.h"
|
2021-04-12 02:33:05 +01:00
|
|
|
#include "util/os_file.h"
|
|
|
|
|
2021-06-30 18:28:47 +01:00
|
|
|
#include "vn_buffer.h"
|
2021-04-12 02:33:05 +01:00
|
|
|
#include "vn_device.h"
|
2021-05-19 05:42:57 +01:00
|
|
|
#include "vn_device_memory.h"
|
2021-04-12 02:33:05 +01:00
|
|
|
#include "vn_image.h"
|
2021-07-30 19:07:55 +01:00
|
|
|
#include "vn_instance.h"
|
|
|
|
#include "vn_physical_device.h"
|
2021-04-12 02:33:05 +01:00
|
|
|
#include "vn_queue.h"
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
/* perform options supported by CrOS Gralloc */
|
|
|
|
#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4
|
2022-04-09 01:21:53 +01:00
|
|
|
#define CROS_GRALLOC_DRM_GET_USAGE 5
|
|
|
|
#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1
|
2022-04-09 00:13:35 +01:00
|
|
|
|
|
|
|
struct vn_android_gralloc {
|
|
|
|
const gralloc_module_t *module;
|
2022-04-09 01:21:53 +01:00
|
|
|
uint32_t front_rendering_usage;
|
2022-04-09 00:13:35 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct vn_android_gralloc _vn_android_gralloc;
|
|
|
|
|
|
|
|
static int
|
|
|
|
vn_android_gralloc_init()
|
|
|
|
{
|
|
|
|
static const char CROS_GRALLOC_MODULE_NAME[] = "CrOS Gralloc";
|
|
|
|
const gralloc_module_t *gralloc = NULL;
|
2022-04-09 01:21:53 +01:00
|
|
|
uint32_t front_rendering_usage = 0;
|
2022-04-09 00:13:35 +01:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* get gralloc module for gralloc buffer info query */
|
|
|
|
ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
|
|
|
|
(const hw_module_t **)&gralloc);
|
|
|
|
if (ret) {
|
|
|
|
vn_log(NULL, "failed to open gralloc module(ret=%d)", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(gralloc->common.name, CROS_GRALLOC_MODULE_NAME) != 0) {
|
|
|
|
dlclose(gralloc->common.dso);
|
|
|
|
vn_log(NULL, "unexpected gralloc (name: %s)", gralloc->common.name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gralloc->perform) {
|
|
|
|
dlclose(gralloc->common.dso);
|
|
|
|
vn_log(NULL, "missing required gralloc helper: perform");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-04-09 01:21:53 +01:00
|
|
|
if (gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_USAGE,
|
|
|
|
CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT,
|
|
|
|
&front_rendering_usage) == 0) {
|
|
|
|
assert(front_rendering_usage);
|
|
|
|
_vn_android_gralloc.front_rendering_usage = front_rendering_usage;
|
|
|
|
}
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
_vn_android_gralloc.module = gralloc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
vn_android_gralloc_fini()
|
|
|
|
{
|
|
|
|
dlclose(_vn_android_gralloc.module->common.dso);
|
|
|
|
}
|
|
|
|
|
2022-04-09 03:46:00 +01:00
|
|
|
uint32_t
|
|
|
|
vn_android_gralloc_get_shared_present_usage()
|
|
|
|
{
|
|
|
|
return _vn_android_gralloc.front_rendering_usage;
|
|
|
|
}
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
struct cros_gralloc0_buffer_info {
|
|
|
|
uint32_t drm_fourcc;
|
|
|
|
int num_fds; /* ignored */
|
|
|
|
int fds[4]; /* ignored */
|
|
|
|
uint64_t modifier;
|
|
|
|
uint32_t offset[4];
|
|
|
|
uint32_t stride[4];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct vn_android_gralloc_buffer_properties {
|
|
|
|
uint32_t drm_fourcc;
|
|
|
|
uint64_t modifier;
|
2022-06-30 23:06:05 +01:00
|
|
|
|
|
|
|
/* plane order matches VkImageDrmFormatModifierExplicitCreateInfoEXT */
|
2022-04-09 00:13:35 +01:00
|
|
|
uint32_t offset[4];
|
|
|
|
uint32_t stride[4];
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
vn_android_gralloc_get_buffer_properties(
|
|
|
|
buffer_handle_t handle,
|
|
|
|
struct vn_android_gralloc_buffer_properties *out_props)
|
|
|
|
{
|
|
|
|
const gralloc_module_t *gralloc = _vn_android_gralloc.module;
|
|
|
|
struct cros_gralloc0_buffer_info info;
|
|
|
|
if (gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO, handle,
|
|
|
|
&info) != 0) {
|
|
|
|
vn_log(NULL, "CROS_GRALLOC_DRM_GET_BUFFER_INFO failed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.modifier == DRM_FORMAT_MOD_INVALID) {
|
|
|
|
vn_log(NULL, "Unexpected DRM_FORMAT_MOD_INVALID");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
out_props->drm_fourcc = info.drm_fourcc;
|
|
|
|
for (uint32_t i = 0; i < 4; i++) {
|
|
|
|
out_props->stride[i] = info.stride[i];
|
|
|
|
out_props->offset[i] = info.offset[i];
|
|
|
|
}
|
2022-06-30 23:06:05 +01:00
|
|
|
|
|
|
|
/* YVU420 has a chroma order of CrCb. So we must swap the planes for CrCb
|
|
|
|
* to align with VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM. This is to serve
|
|
|
|
* VkImageDrmFormatModifierExplicitCreateInfoEXT explicit plane layouts.
|
|
|
|
*/
|
|
|
|
if (info.drm_fourcc == DRM_FORMAT_YVU420) {
|
|
|
|
out_props->stride[1] = info.stride[2];
|
|
|
|
out_props->offset[1] = info.offset[2];
|
|
|
|
out_props->stride[2] = info.stride[1];
|
|
|
|
out_props->offset[2] = info.offset[1];
|
|
|
|
}
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
out_props->modifier = info.modifier;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
vn_android_gralloc_get_dma_buf_fd(const native_handle_t *handle)
|
|
|
|
{
|
|
|
|
/* There can be multiple fds wrapped inside a native_handle_t, but we
|
|
|
|
* expect the 1st one pointing to the dma_buf. For multi-planar format,
|
|
|
|
* there should only exist one undelying dma_buf. The other fd(s) could be
|
|
|
|
* dups to the same dma_buf or point to the shared memory used to store
|
|
|
|
* gralloc buffer metadata.
|
|
|
|
*/
|
|
|
|
assert(handle);
|
|
|
|
|
|
|
|
if (handle->numFds < 1) {
|
|
|
|
vn_log(NULL, "handle->numFds is %d, expected >= 1", handle->numFds);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle->data[0] < 0) {
|
|
|
|
vn_log(NULL, "handle->data[0] < 0");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return handle->data[0];
|
|
|
|
}
|
|
|
|
|
2021-04-03 20:14:00 +01:00
|
|
|
static int
|
|
|
|
vn_hal_open(const struct hw_module_t *mod,
|
|
|
|
const char *id,
|
|
|
|
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_HAL_API_VERSION,
|
|
|
|
.id = HWVULKAN_HARDWARE_MODULE_ID,
|
|
|
|
.name = "Venus Vulkan HAL",
|
|
|
|
.author = "Google LLC",
|
|
|
|
.methods = &(hw_module_methods_t) {
|
|
|
|
.open = vn_hal_open,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
vn_hal_close(UNUSED struct hw_device_t *dev)
|
|
|
|
{
|
2022-04-09 00:13:35 +01:00
|
|
|
vn_android_gralloc_fini();
|
2021-04-03 20:14:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static hwvulkan_device_t vn_hal_dev = {
|
|
|
|
.common = {
|
|
|
|
.tag = HARDWARE_DEVICE_TAG,
|
|
|
|
.version = HWVULKAN_DEVICE_API_VERSION_0_1,
|
|
|
|
.module = &HAL_MODULE_INFO_SYM.common,
|
|
|
|
.close = vn_hal_close,
|
|
|
|
},
|
|
|
|
.EnumerateInstanceExtensionProperties = vn_EnumerateInstanceExtensionProperties,
|
|
|
|
.CreateInstance = vn_CreateInstance,
|
|
|
|
.GetInstanceProcAddr = vn_GetInstanceProcAddr,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
vn_hal_open(const struct hw_module_t *mod,
|
|
|
|
const char *id,
|
|
|
|
struct hw_device_t **dev)
|
|
|
|
{
|
2022-04-09 00:13:35 +01:00
|
|
|
int ret;
|
2021-04-30 18:20:54 +01:00
|
|
|
|
2021-04-03 20:14:00 +01:00
|
|
|
assert(mod == &HAL_MODULE_INFO_SYM.common);
|
|
|
|
assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
ret = vn_android_gralloc_init();
|
|
|
|
if (ret)
|
2021-04-30 18:20:54 +01:00
|
|
|
return ret;
|
|
|
|
|
2021-04-03 20:14:00 +01:00
|
|
|
*dev = &vn_hal_dev.common;
|
2021-04-30 18:20:54 +01:00
|
|
|
|
2021-04-03 20:14:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2021-05-05 23:11:23 +01:00
|
|
|
static uint32_t
|
|
|
|
vn_android_ahb_format_from_vk_format(VkFormat format)
|
|
|
|
{
|
2022-06-07 07:59:32 +01:00
|
|
|
/* Only non-external AHB compatible formats are expected at:
|
|
|
|
* - image format query
|
|
|
|
* - memory export allocation
|
|
|
|
*/
|
2021-05-05 23:11:23 +01:00
|
|
|
switch (format) {
|
|
|
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
|
|
|
return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
case VK_FORMAT_R8G8B8_UNORM:
|
|
|
|
return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
|
|
|
|
case VK_FORMAT_R5G6B5_UNORM_PACK16:
|
|
|
|
return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
|
|
|
|
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
|
|
|
return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
|
|
|
|
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
|
|
|
return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-14 23:18:32 +00:00
|
|
|
const VkFormat *
|
|
|
|
vn_android_format_to_view_formats(VkFormat format, uint32_t *out_count)
|
|
|
|
{
|
|
|
|
/* For AHB image prop query and creation, venus overrides the tiling to
|
|
|
|
* VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, which requires to chain
|
|
|
|
* VkImageFormatListCreateInfo struct in the corresponding pNext when the
|
|
|
|
* VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is set. Those AHB images are assumed
|
|
|
|
* to be mutable no more than sRGB-ness, and the implementations can fail
|
|
|
|
* whenever going beyond.
|
|
|
|
*
|
|
|
|
* This helper provides the view formats that have sRGB variants for the
|
|
|
|
* image format that venus supports.
|
|
|
|
*/
|
|
|
|
static const VkFormat view_formats_r8g8b8a8[] = {
|
|
|
|
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB
|
|
|
|
};
|
|
|
|
static const VkFormat view_formats_r8g8b8[] = { VK_FORMAT_R8G8B8_UNORM,
|
|
|
|
VK_FORMAT_R8G8B8_SRGB };
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
|
|
|
*out_count = ARRAY_SIZE(view_formats_r8g8b8a8);
|
|
|
|
return view_formats_r8g8b8a8;
|
|
|
|
break;
|
|
|
|
case VK_FORMAT_R8G8B8_UNORM:
|
|
|
|
*out_count = ARRAY_SIZE(view_formats_r8g8b8);
|
|
|
|
return view_formats_r8g8b8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* let the caller handle the fallback case */
|
|
|
|
*out_count = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-24 19:25:02 +01:00
|
|
|
VkFormat
|
2021-06-18 22:45:28 +01:00
|
|
|
vn_android_drm_format_to_vk_format(uint32_t format)
|
2021-05-05 23:11:23 +01:00
|
|
|
{
|
|
|
|
switch (format) {
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
2021-05-05 23:11:23 +01:00
|
|
|
return VK_FORMAT_R8G8B8A8_UNORM;
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_BGR888:
|
2021-05-05 23:11:23 +01:00
|
|
|
return VK_FORMAT_R8G8B8_UNORM;
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_RGB565:
|
2021-05-05 23:11:23 +01:00
|
|
|
return VK_FORMAT_R5G6B5_UNORM_PACK16;
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_ABGR16161616F:
|
2021-05-05 23:11:23 +01:00
|
|
|
return VK_FORMAT_R16G16B16A16_SFLOAT;
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_ABGR2101010:
|
2021-05-05 23:11:23 +01:00
|
|
|
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_YVU420:
|
2022-06-07 07:59:32 +01:00
|
|
|
return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
|
2021-06-18 22:45:28 +01:00
|
|
|
case DRM_FORMAT_NV12:
|
2021-05-05 23:11:23 +01:00
|
|
|
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
|
|
|
|
default:
|
|
|
|
return VK_FORMAT_UNDEFINED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-02 08:17:37 +01:00
|
|
|
static bool
|
|
|
|
vn_android_drm_format_is_yuv(uint32_t format)
|
|
|
|
{
|
|
|
|
assert(vn_android_drm_format_to_vk_format(format) != VK_FORMAT_UNDEFINED);
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case DRM_FORMAT_YVU420:
|
|
|
|
case DRM_FORMAT_NV12:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-05 00:18:22 +01:00
|
|
|
uint64_t
|
|
|
|
vn_android_get_ahb_usage(const VkImageUsageFlags usage,
|
|
|
|
const VkImageCreateFlags flags)
|
|
|
|
{
|
|
|
|
uint64_t ahb_usage = 0;
|
|
|
|
if (usage &
|
|
|
|
(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
|
|
|
|
ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
|
|
|
|
|
|
|
|
if (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
|
|
|
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
|
|
|
ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
|
|
|
|
|
|
|
|
if (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
|
|
|
|
ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
|
|
|
|
|
|
|
|
if (flags & VK_IMAGE_CREATE_PROTECTED_BIT)
|
|
|
|
ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
|
|
|
|
|
|
|
|
/* must include at least one GPU usage flag */
|
|
|
|
if (ahb_usage == 0)
|
|
|
|
ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
|
|
|
|
|
|
|
|
return ahb_usage;
|
|
|
|
}
|
|
|
|
|
2021-04-12 02:33:05 +01:00
|
|
|
VkResult
|
|
|
|
vn_GetSwapchainGrallocUsage2ANDROID(
|
|
|
|
VkDevice device,
|
|
|
|
VkFormat format,
|
|
|
|
VkImageUsageFlags imageUsage,
|
|
|
|
VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
|
|
|
|
uint64_t *grallocConsumerUsage,
|
|
|
|
uint64_t *grallocProducerUsage)
|
|
|
|
{
|
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
|
2022-04-09 03:46:00 +01:00
|
|
|
if (VN_DEBUG(WSI)) {
|
|
|
|
vn_log(dev->instance,
|
|
|
|
"format=%d, imageUsage=0x%x, swapchainImageUsage=0x%x", format,
|
|
|
|
imageUsage, swapchainImageUsage);
|
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2022-04-09 03:46:00 +01:00
|
|
|
*grallocConsumerUsage = 0;
|
|
|
|
*grallocProducerUsage = 0;
|
2021-04-12 02:33:05 +01:00
|
|
|
if (imageUsage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
|
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
|
|
|
|
*grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
|
|
|
|
|
|
|
|
if (imageUsage &
|
|
|
|
(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
|
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
|
2022-04-09 03:46:00 +01:00
|
|
|
*grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
|
|
|
|
|
|
|
|
if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
|
|
|
|
*grallocProducerUsage |= vn_android_gralloc_get_shared_present_usage();
|
2021-04-12 02:33:05 +01:00
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-05-05 00:35:06 +01:00
|
|
|
static VkResult
|
2021-06-04 19:43:49 +01:00
|
|
|
vn_android_get_modifier_properties(struct vn_device *dev,
|
2021-05-17 05:34:06 +01:00
|
|
|
VkFormat format,
|
|
|
|
uint64_t modifier,
|
|
|
|
const VkAllocationCallbacks *alloc,
|
|
|
|
VkDrmFormatModifierPropertiesEXT *out_props)
|
2021-04-30 18:20:54 +01:00
|
|
|
{
|
2021-06-04 19:43:49 +01:00
|
|
|
VkPhysicalDevice physical_device =
|
|
|
|
vn_physical_device_to_handle(dev->physical_device);
|
2021-04-30 18:20:54 +01:00
|
|
|
VkDrmFormatModifierPropertiesListEXT mod_prop_list = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
|
|
|
|
.pNext = NULL,
|
|
|
|
.drmFormatModifierCount = 0,
|
|
|
|
.pDrmFormatModifierProperties = NULL,
|
|
|
|
};
|
|
|
|
VkFormatProperties2 format_prop = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
|
|
|
|
.pNext = &mod_prop_list,
|
|
|
|
};
|
2021-06-04 19:43:49 +01:00
|
|
|
VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
|
|
|
|
bool modifier_found = false;
|
|
|
|
|
2021-04-30 18:20:54 +01:00
|
|
|
vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
|
|
|
|
&format_prop);
|
|
|
|
|
2021-06-02 23:32:29 +01:00
|
|
|
if (!mod_prop_list.drmFormatModifierCount) {
|
2021-06-10 00:05:50 +01:00
|
|
|
vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",
|
|
|
|
format);
|
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-06-02 23:32:29 +01:00
|
|
|
}
|
2021-04-30 18:20:54 +01:00
|
|
|
|
2021-06-04 19:43:49 +01:00
|
|
|
mod_props = vk_zalloc(
|
|
|
|
alloc, sizeof(*mod_props) * mod_prop_list.drmFormatModifierCount,
|
|
|
|
VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
2021-04-30 18:20:54 +01:00
|
|
|
if (!mod_props)
|
2021-05-05 00:35:06 +01:00
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
2021-04-30 18:20:54 +01:00
|
|
|
|
|
|
|
mod_prop_list.pDrmFormatModifierProperties = mod_props;
|
|
|
|
vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
|
|
|
|
&format_prop);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {
|
|
|
|
if (mod_props[i].drmFormatModifier == modifier) {
|
2021-05-17 05:34:06 +01:00
|
|
|
*out_props = mod_props[i];
|
2021-06-04 19:43:49 +01:00
|
|
|
modifier_found = true;
|
2021-04-30 18:20:54 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vk_free(alloc, mod_props);
|
2021-06-04 19:43:49 +01:00
|
|
|
|
|
|
|
if (!modifier_found) {
|
|
|
|
vn_log(dev->instance,
|
|
|
|
"No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",
|
|
|
|
modifier, format);
|
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
}
|
|
|
|
|
2021-05-05 00:35:06 +01:00
|
|
|
return VK_SUCCESS;
|
2021-04-30 18:20:54 +01:00
|
|
|
}
|
|
|
|
|
2021-06-04 23:43:25 +01:00
|
|
|
struct vn_android_image_builder {
|
|
|
|
VkImageCreateInfo create;
|
|
|
|
VkSubresourceLayout layouts[4];
|
|
|
|
VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;
|
|
|
|
VkExternalMemoryImageCreateInfo external;
|
2022-02-14 22:42:29 +00:00
|
|
|
VkImageFormatListCreateInfo list;
|
2021-06-04 23:43:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
vn_android_get_image_builder(struct vn_device *dev,
|
|
|
|
const VkImageCreateInfo *create_info,
|
|
|
|
const native_handle_t *handle,
|
|
|
|
const VkAllocationCallbacks *alloc,
|
|
|
|
struct vn_android_image_builder *out_builder)
|
|
|
|
{
|
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
struct vn_android_gralloc_buffer_properties buf_props;
|
|
|
|
VkDrmFormatModifierPropertiesEXT mod_props;
|
2022-02-14 22:42:29 +00:00
|
|
|
uint32_t vcount = 0;
|
|
|
|
const VkFormat *vformats = NULL;
|
2021-06-04 23:43:25 +01:00
|
|
|
|
2022-02-14 19:46:39 +00:00
|
|
|
/* Android image builder is only used by ANB or AHB. For ANB, Android
|
|
|
|
* Vulkan loader will never pass the below structs. For AHB, struct
|
|
|
|
* vn_image_create_deferred_info will never carry below either.
|
|
|
|
*/
|
|
|
|
assert(!vk_find_struct_const(
|
|
|
|
create_info->pNext,
|
|
|
|
IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT));
|
|
|
|
assert(!vk_find_struct_const(create_info->pNext,
|
|
|
|
EXTERNAL_MEMORY_IMAGE_CREATE_INFO));
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
if (!vn_android_gralloc_get_buffer_properties(handle, &buf_props))
|
2021-06-04 23:43:25 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
|
|
|
|
result = vn_android_get_modifier_properties(
|
|
|
|
dev, create_info->format, buf_props.modifier, alloc, &mod_props);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
2022-02-14 19:46:39 +00:00
|
|
|
/* fill VkImageCreateInfo */
|
|
|
|
memset(out_builder, 0, sizeof(*out_builder));
|
|
|
|
out_builder->create = *create_info;
|
|
|
|
out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
|
|
|
|
|
|
|
/* fill VkImageDrmFormatModifierExplicitCreateInfoEXT */
|
2021-06-04 23:43:25 +01:00
|
|
|
for (uint32_t i = 0; i < mod_props.drmFormatModifierPlaneCount; i++) {
|
|
|
|
out_builder->layouts[i].offset = buf_props.offset[i];
|
|
|
|
out_builder->layouts[i].rowPitch = buf_props.stride[i];
|
|
|
|
}
|
|
|
|
out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){
|
|
|
|
.sType =
|
|
|
|
VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
|
2022-02-14 19:46:39 +00:00
|
|
|
.pNext = out_builder->create.pNext,
|
2021-06-04 23:43:25 +01:00
|
|
|
.drmFormatModifier = buf_props.modifier,
|
|
|
|
.drmFormatModifierPlaneCount = mod_props.drmFormatModifierPlaneCount,
|
|
|
|
.pPlaneLayouts = out_builder->layouts,
|
|
|
|
};
|
2022-02-14 19:46:39 +00:00
|
|
|
out_builder->create.pNext = &out_builder->modifier;
|
|
|
|
|
|
|
|
/* fill VkExternalMemoryImageCreateInfo */
|
2021-06-04 23:43:25 +01:00
|
|
|
out_builder->external = (VkExternalMemoryImageCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
2022-02-14 19:46:39 +00:00
|
|
|
.pNext = out_builder->create.pNext,
|
2021-06-04 23:43:25 +01:00
|
|
|
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
|
|
|
};
|
|
|
|
out_builder->create.pNext = &out_builder->external;
|
|
|
|
|
2022-02-14 22:42:29 +00:00
|
|
|
/* fill VkImageFormatListCreateInfo if needed
|
|
|
|
*
|
|
|
|
* vn_image::deferred_info only stores VkImageFormatListCreateInfo with a
|
|
|
|
* non-zero viewFormatCount, and that stored struct will be respected.
|
|
|
|
*/
|
|
|
|
if ((create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
|
|
|
|
!vk_find_struct_const(create_info->pNext,
|
|
|
|
IMAGE_FORMAT_LIST_CREATE_INFO)) {
|
|
|
|
/* 12.3. Images
|
|
|
|
*
|
|
|
|
* If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags
|
|
|
|
* contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain
|
|
|
|
* must include a VkImageFormatListCreateInfo structure with non-zero
|
|
|
|
* viewFormatCount.
|
|
|
|
*/
|
|
|
|
vformats =
|
|
|
|
vn_android_format_to_view_formats(create_info->format, &vcount);
|
|
|
|
if (!vformats) {
|
|
|
|
/* image builder struct persists through the image creation call */
|
|
|
|
vformats = &out_builder->create.format;
|
|
|
|
vcount = 1;
|
|
|
|
}
|
|
|
|
out_builder->list = (VkImageFormatListCreateInfo){
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
|
|
|
|
.pNext = out_builder->create.pNext,
|
|
|
|
.viewFormatCount = vcount,
|
|
|
|
.pViewFormats = vformats,
|
|
|
|
};
|
|
|
|
out_builder->create.pNext = &out_builder->list;
|
|
|
|
}
|
|
|
|
|
2021-06-04 23:43:25 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-04-12 02:33:05 +01:00
|
|
|
VkResult
|
2021-05-14 23:58:34 +01:00
|
|
|
vn_android_image_from_anb(struct vn_device *dev,
|
2021-06-04 23:43:25 +01:00
|
|
|
const VkImageCreateInfo *create_info,
|
2021-05-14 23:58:34 +01:00
|
|
|
const VkNativeBufferANDROID *anb_info,
|
|
|
|
const VkAllocationCallbacks *alloc,
|
|
|
|
struct vn_image **out_img)
|
2021-04-12 02:33:05 +01:00
|
|
|
{
|
|
|
|
/* If anb_info->handle points to a classic resouce created from
|
|
|
|
* virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the
|
|
|
|
* guest shadow storage other than the host gpu storage.
|
|
|
|
*
|
|
|
|
* We also need to pass the correct stride to vn_CreateImage, which will be
|
|
|
|
* done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require
|
|
|
|
* VK_EXT_image_drm_format_modifier support in the host driver. The struct
|
2021-04-30 18:20:54 +01:00
|
|
|
* needs host storage info which can be queried from cros gralloc.
|
2021-04-12 02:33:05 +01:00
|
|
|
*/
|
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
VkDevice device = vn_device_to_handle(dev);
|
|
|
|
VkDeviceMemory memory = VK_NULL_HANDLE;
|
|
|
|
VkImage image = VK_NULL_HANDLE;
|
|
|
|
struct vn_image *img = NULL;
|
2021-05-27 20:47:53 +01:00
|
|
|
uint64_t alloc_size = 0;
|
2021-04-12 02:33:05 +01:00
|
|
|
uint32_t mem_type_bits = 0;
|
|
|
|
int dma_buf_fd = -1;
|
|
|
|
int dup_fd = -1;
|
2022-02-14 19:46:39 +00:00
|
|
|
VkImageCreateInfo local_create_info;
|
2021-06-04 23:43:25 +01:00
|
|
|
struct vn_android_image_builder builder;
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(anb_info->handle);
|
|
|
|
if (dma_buf_fd < 0) {
|
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-04-12 02:33:05 +01:00
|
|
|
goto fail;
|
2022-04-09 00:13:35 +01:00
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2022-02-14 22:42:29 +00:00
|
|
|
assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT));
|
2022-02-14 19:46:39 +00:00
|
|
|
assert(!vk_find_struct_const(create_info->pNext,
|
|
|
|
IMAGE_FORMAT_LIST_CREATE_INFO));
|
|
|
|
assert(!vk_find_struct_const(create_info->pNext,
|
|
|
|
IMAGE_STENCIL_USAGE_CREATE_INFO));
|
|
|
|
|
|
|
|
/* strip VkNativeBufferANDROID and VkSwapchainImageCreateInfoANDROID */
|
|
|
|
local_create_info = *create_info;
|
|
|
|
local_create_info.pNext = NULL;
|
|
|
|
result = vn_android_get_image_builder(dev, &local_create_info,
|
|
|
|
anb_info->handle, alloc, &builder);
|
2021-05-05 00:35:06 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto fail;
|
2021-04-30 18:20:54 +01:00
|
|
|
|
2021-04-22 22:01:44 +01:00
|
|
|
/* encoder will strip the Android specific pNext structs */
|
2021-06-04 23:43:25 +01:00
|
|
|
result = vn_image_create(dev, &builder.create, alloc, &img);
|
2021-06-30 07:02:17 +01:00
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
if (VN_DEBUG(WSI))
|
|
|
|
vn_log(dev->instance, "vn_image_create failed");
|
2021-04-22 22:01:44 +01:00
|
|
|
goto fail;
|
2021-06-30 07:02:17 +01:00
|
|
|
}
|
2021-04-22 22:01:44 +01:00
|
|
|
|
|
|
|
image = vn_image_to_handle(img);
|
2022-03-28 21:35:08 +01:00
|
|
|
|
|
|
|
const VkMemoryRequirements *mem_req =
|
|
|
|
&img->requirements[0].memory.memoryRequirements;
|
|
|
|
if (!mem_req->memoryTypeBits) {
|
2021-06-30 07:02:17 +01:00
|
|
|
if (VN_DEBUG(WSI))
|
2022-03-28 21:35:08 +01:00
|
|
|
vn_log(dev->instance, "mem_req->memoryTypeBits cannot be zero");
|
2021-04-22 22:01:44 +01:00
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2021-05-27 20:47:53 +01:00
|
|
|
result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
|
|
|
|
&mem_type_bits);
|
2021-04-12 02:33:05 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto fail;
|
|
|
|
|
2021-05-27 20:47:53 +01:00
|
|
|
if (VN_DEBUG(WSI)) {
|
|
|
|
vn_log(dev->instance,
|
|
|
|
"size = img(%" PRIu64 ") fd(%" PRIu64 "), "
|
|
|
|
"memoryTypeBits = img(0x%X) & fd(0x%X)",
|
2022-03-28 21:35:08 +01:00
|
|
|
mem_req->size, alloc_size, mem_req->memoryTypeBits,
|
|
|
|
mem_type_bits);
|
2021-05-27 20:47:53 +01:00
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
if (alloc_size < mem_req->size) {
|
2021-06-30 07:02:17 +01:00
|
|
|
if (VN_DEBUG(WSI)) {
|
|
|
|
vn_log(dev->instance,
|
2022-03-28 21:35:08 +01:00
|
|
|
"alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
|
|
|
|
alloc_size, mem_req->size);
|
2021-06-30 07:02:17 +01:00
|
|
|
}
|
2021-06-01 23:23:53 +01:00
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
mem_type_bits &= mem_req->memoryTypeBits;
|
2021-04-12 02:33:05 +01:00
|
|
|
if (!mem_type_bits) {
|
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
dup_fd = os_dupfd_cloexec(dma_buf_fd);
|
|
|
|
if (dup_fd < 0) {
|
|
|
|
result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
|
|
|
|
: VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
const VkImportMemoryFdInfoKHR import_fd_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
|
|
|
|
.pNext = NULL,
|
|
|
|
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
|
|
|
.fd = dup_fd,
|
|
|
|
};
|
|
|
|
const VkMemoryAllocateInfo memory_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
.pNext = &import_fd_info,
|
2022-03-28 21:35:08 +01:00
|
|
|
.allocationSize = mem_req->size,
|
2021-04-12 02:33:05 +01:00
|
|
|
.memoryTypeIndex = ffs(mem_type_bits) - 1,
|
|
|
|
};
|
|
|
|
result = vn_AllocateMemory(device, &memory_info, alloc, &memory);
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
/* only need to close the dup_fd on import failure */
|
|
|
|
close(dup_fd);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
const VkBindImageMemoryInfo bind_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
|
|
|
|
.pNext = NULL,
|
|
|
|
.image = image,
|
|
|
|
.memory = memory,
|
|
|
|
.memoryOffset = 0,
|
|
|
|
};
|
|
|
|
result = vn_BindImageMemory2(device, 1, &bind_info);
|
2021-04-12 02:33:05 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto fail;
|
|
|
|
|
2022-01-13 20:02:46 +00:00
|
|
|
img->wsi.is_wsi = true;
|
2022-01-13 20:03:29 +00:00
|
|
|
img->wsi.tiling_override = builder.create.tiling;
|
|
|
|
img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier;
|
2021-04-12 02:33:05 +01:00
|
|
|
/* Android WSI image owns the memory */
|
2022-01-13 20:02:46 +00:00
|
|
|
img->wsi.memory = vn_device_memory_from_handle(memory);
|
|
|
|
img->wsi.memory_owned = true;
|
2021-04-12 02:33:05 +01:00
|
|
|
*out_img = img;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (image != VK_NULL_HANDLE)
|
|
|
|
vn_DestroyImage(device, image, alloc);
|
|
|
|
if (memory != VK_NULL_HANDLE)
|
|
|
|
vn_FreeMemory(device, memory, alloc);
|
|
|
|
return vn_error(dev->instance, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_AcquireImageANDROID(VkDevice device,
|
2021-05-06 18:17:30 +01:00
|
|
|
UNUSED VkImage image,
|
2021-04-12 02:33:05 +01:00
|
|
|
int nativeFenceFd,
|
|
|
|
VkSemaphore semaphore,
|
|
|
|
VkFence fence)
|
|
|
|
{
|
2021-05-17 18:25:52 +01:00
|
|
|
VN_TRACE_FUNC();
|
2021-04-12 02:33:05 +01:00
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
2021-06-13 00:17:44 +01:00
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
|
|
|
|
if (dev->instance->experimental.globalFencing == VK_FALSE) {
|
|
|
|
/* Fallback when VkVenusExperimentalFeatures100000MESA::globalFencing is
|
|
|
|
* VK_FALSE, out semaphore and fence are filled with already signaled
|
|
|
|
* payloads, and the native fence fd is waited inside until signaled.
|
|
|
|
*/
|
|
|
|
if (nativeFenceFd >= 0) {
|
|
|
|
int ret = sync_wait(nativeFenceFd, -1);
|
|
|
|
/* Android loader expects the ICD to always close the fd */
|
|
|
|
close(nativeFenceFd);
|
|
|
|
if (ret)
|
|
|
|
return vn_error(dev->instance, VK_ERROR_SURFACE_LOST_KHR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (semaphore != VK_NULL_HANDLE)
|
|
|
|
vn_semaphore_signal_wsi(dev, vn_semaphore_from_handle(semaphore));
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2021-06-13 00:17:44 +01:00
|
|
|
if (fence != VK_NULL_HANDLE)
|
|
|
|
vn_fence_signal_wsi(dev, vn_fence_from_handle(fence));
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int semaphore_fd = -1;
|
|
|
|
int fence_fd = -1;
|
2021-04-12 02:33:05 +01:00
|
|
|
if (nativeFenceFd >= 0) {
|
2021-06-13 00:17:44 +01:00
|
|
|
if (semaphore != VK_NULL_HANDLE && fence != VK_NULL_HANDLE) {
|
|
|
|
semaphore_fd = nativeFenceFd;
|
|
|
|
fence_fd = os_dupfd_cloexec(nativeFenceFd);
|
|
|
|
if (fence_fd < 0) {
|
|
|
|
result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
|
|
|
|
: VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
close(nativeFenceFd);
|
|
|
|
return vn_error(dev->instance, result);
|
|
|
|
}
|
|
|
|
} else if (semaphore != VK_NULL_HANDLE) {
|
|
|
|
semaphore_fd = nativeFenceFd;
|
|
|
|
} else if (fence != VK_NULL_HANDLE) {
|
|
|
|
fence_fd = nativeFenceFd;
|
|
|
|
} else {
|
|
|
|
close(nativeFenceFd);
|
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
}
|
|
|
|
|
2021-06-13 00:17:44 +01:00
|
|
|
if (semaphore != VK_NULL_HANDLE) {
|
|
|
|
const VkImportSemaphoreFdInfoKHR info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
|
|
|
|
.pNext = NULL,
|
|
|
|
.semaphore = semaphore,
|
|
|
|
.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
|
|
|
|
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
|
|
|
.fd = semaphore_fd,
|
|
|
|
};
|
|
|
|
result = vn_ImportSemaphoreFdKHR(device, &info);
|
|
|
|
if (result == VK_SUCCESS)
|
|
|
|
semaphore_fd = -1;
|
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2021-06-13 00:17:44 +01:00
|
|
|
if (result == VK_SUCCESS && fence != VK_NULL_HANDLE) {
|
|
|
|
const VkImportFenceFdInfoKHR info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
|
|
|
|
.pNext = NULL,
|
|
|
|
.fence = fence,
|
|
|
|
.flags = VK_FENCE_IMPORT_TEMPORARY_BIT,
|
|
|
|
.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
|
|
|
|
.fd = fence_fd,
|
|
|
|
};
|
|
|
|
result = vn_ImportFenceFdKHR(device, &info);
|
|
|
|
if (result == VK_SUCCESS)
|
|
|
|
fence_fd = -1;
|
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2021-06-13 00:17:44 +01:00
|
|
|
if (semaphore_fd >= 0)
|
|
|
|
close(semaphore_fd);
|
|
|
|
if (fence_fd >= 0)
|
|
|
|
close(fence_fd);
|
|
|
|
|
|
|
|
return vn_result(dev->instance, result);
|
2021-04-12 02:33:05 +01:00
|
|
|
}
|
|
|
|
|
2022-08-11 23:08:43 +01:00
|
|
|
static VkResult
|
2022-08-12 19:31:13 +01:00
|
|
|
vn_android_sync_fence_create(struct vn_queue *queue, bool external)
|
2022-08-11 23:08:43 +01:00
|
|
|
{
|
|
|
|
struct vn_device *dev = queue->device;
|
|
|
|
|
|
|
|
const VkExportFenceCreateInfo export_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
|
|
|
|
.pNext = NULL,
|
|
|
|
.handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
|
|
|
|
};
|
|
|
|
const VkFenceCreateInfo create_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
2022-08-12 19:31:13 +01:00
|
|
|
.pNext = external ? &export_info : NULL,
|
2022-08-11 23:08:43 +01:00
|
|
|
.flags = 0,
|
|
|
|
};
|
|
|
|
return vn_CreateFence(vn_device_to_handle(dev), &create_info, NULL,
|
|
|
|
&queue->sync_fence);
|
|
|
|
}
|
|
|
|
|
2021-04-12 02:33:05 +01:00
|
|
|
VkResult
|
2022-08-11 23:08:43 +01:00
|
|
|
vn_QueueSignalReleaseImageANDROID(VkQueue _queue,
|
2021-04-12 02:33:05 +01:00
|
|
|
uint32_t waitSemaphoreCount,
|
|
|
|
const VkSemaphore *pWaitSemaphores,
|
|
|
|
VkImage image,
|
|
|
|
int *pNativeFenceFd)
|
|
|
|
{
|
2021-05-17 18:25:52 +01:00
|
|
|
VN_TRACE_FUNC();
|
2022-08-11 23:08:43 +01:00
|
|
|
struct vn_queue *queue = vn_queue_from_handle(_queue);
|
|
|
|
struct vn_device *dev = queue->device;
|
2021-06-15 08:00:09 +01:00
|
|
|
const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
|
2022-08-12 19:31:13 +01:00
|
|
|
const bool has_sync_fd_fence_export =
|
|
|
|
dev->physical_device->renderer_sync_fd_fence_features &
|
|
|
|
VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT;
|
2021-06-15 08:00:09 +01:00
|
|
|
VkDevice device = vn_device_to_handle(dev);
|
2021-04-12 02:33:05 +01:00
|
|
|
VkPipelineStageFlags local_stage_masks[8];
|
|
|
|
VkPipelineStageFlags *stage_masks = local_stage_masks;
|
2021-06-15 08:00:09 +01:00
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
int fd = -1;
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2021-06-15 08:00:09 +01:00
|
|
|
if (waitSemaphoreCount == 0) {
|
|
|
|
*pNativeFenceFd = -1;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2022-08-11 23:08:43 +01:00
|
|
|
/* lazily create sync fence for Android wsi */
|
|
|
|
if (queue->sync_fence == VK_NULL_HANDLE) {
|
2022-08-12 19:31:13 +01:00
|
|
|
result = vn_android_sync_fence_create(queue, has_sync_fd_fence_export);
|
2022-08-11 23:08:43 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-04-12 02:33:05 +01:00
|
|
|
if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) {
|
|
|
|
stage_masks =
|
2021-06-15 08:00:09 +01:00
|
|
|
vk_alloc(alloc, sizeof(*stage_masks) * waitSemaphoreCount,
|
2021-04-12 02:33:05 +01:00
|
|
|
VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
2021-06-15 08:00:09 +01:00
|
|
|
if (!stage_masks)
|
|
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2021-04-12 02:33:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < waitSemaphoreCount; i++)
|
|
|
|
stage_masks[i] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
|
|
|
|
|
|
|
const VkSubmitInfo submit_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
|
|
.pNext = NULL,
|
|
|
|
.waitSemaphoreCount = waitSemaphoreCount,
|
|
|
|
.pWaitSemaphores = pWaitSemaphores,
|
|
|
|
.pWaitDstStageMask = stage_masks,
|
2021-05-06 18:17:30 +01:00
|
|
|
.commandBufferCount = 0,
|
|
|
|
.pCommandBuffers = NULL,
|
2021-04-12 02:33:05 +01:00
|
|
|
.signalSemaphoreCount = 0,
|
|
|
|
.pSignalSemaphores = NULL,
|
|
|
|
};
|
2022-08-12 19:31:13 +01:00
|
|
|
result = vn_QueueSubmit(_queue, 1, &submit_info, queue->sync_fence);
|
2021-06-15 08:00:09 +01:00
|
|
|
|
|
|
|
if (stage_masks != local_stage_masks)
|
|
|
|
vk_free(alloc, stage_masks);
|
|
|
|
|
2021-04-12 02:33:05 +01:00
|
|
|
if (result != VK_SUCCESS)
|
2021-06-15 08:00:09 +01:00
|
|
|
return vn_error(dev->instance, result);
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2022-08-12 19:31:13 +01:00
|
|
|
if (has_sync_fd_fence_export) {
|
2021-06-15 08:00:09 +01:00
|
|
|
const VkFenceGetFdInfoKHR fd_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
|
|
|
|
.pNext = NULL,
|
2022-08-11 23:08:43 +01:00
|
|
|
.fence = queue->sync_fence,
|
2021-06-15 08:00:09 +01:00
|
|
|
.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
|
|
|
|
};
|
|
|
|
result = vn_GetFenceFdKHR(device, &fd_info, &fd);
|
|
|
|
} else {
|
|
|
|
result =
|
2022-08-11 23:08:43 +01:00
|
|
|
vn_WaitForFences(device, 1, &queue->sync_fence, VK_TRUE, UINT64_MAX);
|
2021-06-15 08:00:09 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return vn_error(dev->instance, result);
|
|
|
|
|
2022-08-11 23:08:43 +01:00
|
|
|
result = vn_ResetFences(device, 1, &queue->sync_fence);
|
2021-06-15 08:00:09 +01:00
|
|
|
}
|
2021-04-12 02:33:05 +01:00
|
|
|
|
2021-06-15 08:00:09 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return vn_error(dev->instance, result);
|
|
|
|
|
|
|
|
*pNativeFenceFd = fd;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
2021-04-12 02:33:05 +01:00
|
|
|
}
|
2021-04-29 00:03:10 +01:00
|
|
|
|
2021-05-17 05:34:06 +01:00
|
|
|
static VkResult
|
|
|
|
vn_android_get_ahb_format_properties(
|
|
|
|
struct vn_device *dev,
|
|
|
|
const struct AHardwareBuffer *ahb,
|
|
|
|
VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
|
|
|
|
{
|
|
|
|
AHardwareBuffer_Desc desc;
|
2021-06-04 19:43:49 +01:00
|
|
|
VkFormat format;
|
|
|
|
struct vn_android_gralloc_buffer_properties buf_props;
|
|
|
|
VkDrmFormatModifierPropertiesEXT mod_props;
|
2021-05-17 05:34:06 +01:00
|
|
|
|
2021-06-04 19:43:49 +01:00
|
|
|
AHardwareBuffer_describe(ahb, &desc);
|
2021-05-17 05:34:06 +01:00
|
|
|
if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
|
|
|
|
AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
|
2021-06-04 19:43:49 +01:00
|
|
|
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
|
|
|
|
vn_log(dev->instance,
|
|
|
|
"AHB usage(%" PRIu64 ") must include at least one GPU bit",
|
|
|
|
desc.usage);
|
2021-05-17 05:34:06 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-06-04 19:43:49 +01:00
|
|
|
}
|
2021-05-17 05:34:06 +01:00
|
|
|
|
2021-06-18 22:45:28 +01:00
|
|
|
/* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
|
|
|
|
if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
|
|
|
|
out_props->format = VK_FORMAT_UNDEFINED;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
if (!vn_android_gralloc_get_buffer_properties(
|
2021-06-18 22:45:28 +01:00
|
|
|
AHardwareBuffer_getNativeHandle(ahb), &buf_props))
|
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
|
2021-05-17 05:34:06 +01:00
|
|
|
/* We implement AHB extension support with EXT_image_drm_format_modifier.
|
|
|
|
* It requires us to have a compatible VkFormat but not DRM formats. So if
|
|
|
|
* the ahb is not intended for backing a VkBuffer, error out early if the
|
|
|
|
* format is VK_FORMAT_UNDEFINED.
|
|
|
|
*/
|
2021-06-18 22:45:28 +01:00
|
|
|
format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
|
2021-05-17 05:34:06 +01:00
|
|
|
if (format == VK_FORMAT_UNDEFINED) {
|
2021-06-18 22:45:28 +01:00
|
|
|
vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
|
|
|
|
buf_props.drm_fourcc, desc.format);
|
2021-05-17 05:34:06 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-06-18 22:45:28 +01:00
|
|
|
}
|
2021-05-17 05:34:06 +01:00
|
|
|
|
|
|
|
VkResult result = vn_android_get_modifier_properties(
|
2021-06-04 19:43:49 +01:00
|
|
|
dev, format, buf_props.modifier, &dev->base.base.alloc, &mod_props);
|
2021-05-17 05:34:06 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
2021-05-23 01:11:18 +01:00
|
|
|
/* The spec requires that formatFeatures must include at least one of
|
|
|
|
* VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
|
|
|
|
* VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
|
|
|
|
*/
|
|
|
|
const VkFormatFeatureFlags format_features =
|
|
|
|
mod_props.drmFormatModifierTilingFeatures |
|
|
|
|
VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
|
2021-09-02 08:17:37 +01:00
|
|
|
|
|
|
|
/* 11.2.7. Android Hardware Buffer External Memory
|
|
|
|
*
|
|
|
|
* Implementations may not always be able to determine the color model,
|
|
|
|
* numerical range, or chroma offsets of the image contents, so the values
|
|
|
|
* in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
|
|
|
|
* Applications should treat these values as sensible defaults to use in the
|
|
|
|
* absence of more reliable information obtained through some other means.
|
|
|
|
*/
|
2022-06-07 07:59:32 +01:00
|
|
|
const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
|
2021-09-02 08:17:37 +01:00
|
|
|
const VkSamplerYcbcrModelConversion model =
|
2022-06-07 07:59:32 +01:00
|
|
|
is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
|
|
|
|
: VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
|
2022-04-02 07:10:14 +01:00
|
|
|
|
|
|
|
/* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
|
2022-05-28 00:02:49 +01:00
|
|
|
* AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
|
2022-06-07 07:59:32 +01:00
|
|
|
* AHB formats. Venus supports below explicit ones:
|
|
|
|
* - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
|
|
|
|
* - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
|
2022-04-02 07:10:14 +01:00
|
|
|
*/
|
2022-06-07 07:59:32 +01:00
|
|
|
if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
|
2022-04-02 07:10:14 +01:00
|
|
|
format = VK_FORMAT_UNDEFINED;
|
|
|
|
|
2021-05-17 05:34:06 +01:00
|
|
|
*out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
|
|
|
|
.sType = out_props->sType,
|
|
|
|
.pNext = out_props->pNext,
|
|
|
|
.format = format,
|
2021-06-18 22:45:28 +01:00
|
|
|
.externalFormat = buf_props.drm_fourcc,
|
2021-05-23 01:11:18 +01:00
|
|
|
.formatFeatures = format_features,
|
2021-05-17 05:34:06 +01:00
|
|
|
.samplerYcbcrConversionComponents = {
|
|
|
|
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
},
|
2021-09-02 08:17:37 +01:00
|
|
|
.suggestedYcbcrModel = model,
|
2022-06-30 00:25:54 +01:00
|
|
|
/* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
|
|
|
|
.suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
|
2021-05-17 05:34:06 +01:00
|
|
|
.suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
|
|
|
.suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
|
|
|
};
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-05-17 00:59:02 +01:00
|
|
|
VkResult
|
|
|
|
vn_GetAndroidHardwareBufferPropertiesANDROID(
|
|
|
|
VkDevice device,
|
|
|
|
const struct AHardwareBuffer *buffer,
|
|
|
|
VkAndroidHardwareBufferPropertiesANDROID *pProperties)
|
|
|
|
{
|
2022-07-12 07:31:37 +01:00
|
|
|
VN_TRACE_FUNC();
|
2021-05-17 00:59:02 +01:00
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
int dma_buf_fd = -1;
|
2021-05-27 20:47:53 +01:00
|
|
|
uint64_t alloc_size = 0;
|
2021-05-17 00:59:02 +01:00
|
|
|
uint32_t mem_type_bits = 0;
|
|
|
|
|
2021-05-17 05:34:06 +01:00
|
|
|
VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
|
|
|
|
vk_find_struct(pProperties->pNext,
|
|
|
|
ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
|
|
|
|
if (format_props) {
|
|
|
|
result =
|
|
|
|
vn_android_get_ahb_format_properties(dev, buffer, format_props);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return vn_error(dev->instance, result);
|
|
|
|
}
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
|
|
|
|
AHardwareBuffer_getNativeHandle(buffer));
|
|
|
|
if (dma_buf_fd < 0)
|
|
|
|
return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
|
2021-05-17 00:59:02 +01:00
|
|
|
|
2021-05-27 20:47:53 +01:00
|
|
|
result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
|
|
|
|
&mem_type_bits);
|
2021-05-17 00:59:02 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return vn_error(dev->instance, result);
|
|
|
|
|
2021-05-27 20:47:53 +01:00
|
|
|
pProperties->allocationSize = alloc_size;
|
2021-05-17 00:59:02 +01:00
|
|
|
pProperties->memoryTypeBits = mem_type_bits;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2021-05-23 22:05:15 +01:00
|
|
|
|
|
|
|
static AHardwareBuffer *
|
|
|
|
vn_android_ahb_allocate(uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
uint32_t layers,
|
|
|
|
uint32_t format,
|
|
|
|
uint64_t usage)
|
|
|
|
{
|
|
|
|
AHardwareBuffer *ahb = NULL;
|
|
|
|
AHardwareBuffer_Desc desc;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
memset(&desc, 0, sizeof(desc));
|
|
|
|
desc.width = width;
|
|
|
|
desc.height = height;
|
|
|
|
desc.layers = layers;
|
|
|
|
desc.format = format;
|
|
|
|
desc.usage = usage;
|
|
|
|
|
|
|
|
ret = AHardwareBuffer_allocate(&desc, &ahb);
|
|
|
|
if (ret) {
|
|
|
|
/* We just log the error code here for now since the platform falsely
|
|
|
|
* maps all gralloc allocation failures to oom.
|
|
|
|
*/
|
|
|
|
vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
|
|
|
|
width, height, layers, format, usage, ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ahb;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
vn_android_get_drm_format_modifier_info(
|
|
|
|
const VkPhysicalDeviceImageFormatInfo2 *format_info,
|
|
|
|
VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
|
|
|
|
{
|
|
|
|
/* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
|
|
|
|
* to allocate an ahb to retrieve the drm format modifier. For the image
|
|
|
|
* sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
|
|
|
|
*/
|
|
|
|
AHardwareBuffer *ahb = NULL;
|
|
|
|
uint32_t format = 0;
|
|
|
|
uint64_t usage = 0;
|
2021-06-04 19:43:49 +01:00
|
|
|
struct vn_android_gralloc_buffer_properties buf_props;
|
2021-05-23 22:05:15 +01:00
|
|
|
|
|
|
|
assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
|
|
|
|
|
|
|
|
format = vn_android_ahb_format_from_vk_format(format_info->format);
|
|
|
|
if (!format)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
usage = vn_android_get_ahb_usage(format_info->usage, format_info->flags);
|
|
|
|
ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
|
|
|
|
if (!ahb)
|
|
|
|
return false;
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
if (!vn_android_gralloc_get_buffer_properties(
|
2021-06-04 19:43:49 +01:00
|
|
|
AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
|
2021-05-23 22:05:15 +01:00
|
|
|
AHardwareBuffer_release(ahb);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
|
|
|
|
.sType =
|
|
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
|
|
|
|
.pNext = NULL,
|
2021-06-04 19:43:49 +01:00
|
|
|
.drmFormatModifier = buf_props.modifier,
|
2021-05-23 22:05:15 +01:00
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
.queueFamilyIndexCount = 0,
|
|
|
|
.pQueueFamilyIndices = NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
AHardwareBuffer_release(ahb);
|
|
|
|
return true;
|
|
|
|
}
|
2021-05-18 21:55:10 +01:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_android_image_from_ahb(struct vn_device *dev,
|
|
|
|
const VkImageCreateInfo *create_info,
|
|
|
|
const VkAllocationCallbacks *alloc,
|
|
|
|
struct vn_image **out_img)
|
|
|
|
{
|
|
|
|
const VkExternalFormatANDROID *ext_info =
|
|
|
|
vk_find_struct_const(create_info->pNext, EXTERNAL_FORMAT_ANDROID);
|
|
|
|
|
|
|
|
VkImageCreateInfo local_info;
|
|
|
|
if (ext_info && ext_info->externalFormat) {
|
|
|
|
assert(create_info->format == VK_FORMAT_UNDEFINED);
|
|
|
|
assert(create_info->imageType == VK_IMAGE_TYPE_2D);
|
|
|
|
assert(create_info->usage == VK_IMAGE_USAGE_SAMPLED_BIT);
|
|
|
|
assert(create_info->tiling == VK_IMAGE_TILING_OPTIMAL);
|
2022-02-14 22:42:29 +00:00
|
|
|
assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT));
|
2021-05-18 21:55:10 +01:00
|
|
|
|
|
|
|
local_info = *create_info;
|
|
|
|
local_info.format =
|
2021-06-18 22:45:28 +01:00
|
|
|
vn_android_drm_format_to_vk_format(ext_info->externalFormat);
|
2021-05-18 21:55:10 +01:00
|
|
|
create_info = &local_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vn_image_create_deferred(dev, create_info, alloc, out_img);
|
|
|
|
}
|
2021-05-18 23:37:50 +01:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_android_device_import_ahb(struct vn_device *dev,
|
|
|
|
struct vn_device_memory *mem,
|
|
|
|
const VkMemoryAllocateInfo *alloc_info,
|
2021-06-04 19:43:49 +01:00
|
|
|
const VkAllocationCallbacks *alloc,
|
2021-10-26 07:59:47 +01:00
|
|
|
struct AHardwareBuffer *ahb,
|
|
|
|
bool internal_ahb)
|
2021-05-18 23:37:50 +01:00
|
|
|
{
|
2021-05-19 05:42:57 +01:00
|
|
|
const VkMemoryDedicatedAllocateInfo *dedicated_info =
|
|
|
|
vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
|
|
|
|
const native_handle_t *handle = NULL;
|
|
|
|
int dma_buf_fd = -1;
|
|
|
|
int dup_fd = -1;
|
2021-05-28 06:00:24 +01:00
|
|
|
uint64_t alloc_size = 0;
|
|
|
|
uint32_t mem_type_bits = 0;
|
2021-10-26 07:59:47 +01:00
|
|
|
uint32_t mem_type_index = alloc_info->memoryTypeIndex;
|
2021-09-01 22:30:36 +01:00
|
|
|
bool force_unmappable = false;
|
2021-05-19 05:42:57 +01:00
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
|
|
|
|
handle = AHardwareBuffer_getNativeHandle(ahb);
|
2022-04-09 00:13:35 +01:00
|
|
|
dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
|
|
|
|
if (dma_buf_fd < 0)
|
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-05-19 05:42:57 +01:00
|
|
|
|
2021-05-28 06:00:24 +01:00
|
|
|
result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
|
|
|
|
&mem_type_bits);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
2021-05-19 05:42:57 +01:00
|
|
|
/* If ahb is for an image, finish the deferred image creation first */
|
|
|
|
if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
|
|
|
|
struct vn_image *img = vn_image_from_handle(dedicated_info->image);
|
2021-06-04 23:43:25 +01:00
|
|
|
struct vn_android_image_builder builder;
|
2021-05-19 05:42:57 +01:00
|
|
|
|
2021-06-04 23:43:25 +01:00
|
|
|
result = vn_android_get_image_builder(dev, &img->deferred_info->create,
|
|
|
|
handle, alloc, &builder);
|
2021-05-19 05:42:57 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
2021-06-04 23:43:25 +01:00
|
|
|
result = vn_image_init_deferred(dev, &builder.create, img);
|
2021-05-19 05:42:57 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
const VkMemoryRequirements *mem_req =
|
|
|
|
&img->requirements[0].memory.memoryRequirements;
|
|
|
|
if (alloc_size < mem_req->size) {
|
2021-06-10 00:05:50 +01:00
|
|
|
vn_log(dev->instance,
|
2022-03-28 21:35:08 +01:00
|
|
|
"alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
|
|
|
|
alloc_size, mem_req->size);
|
2021-06-01 23:23:53 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-06-10 00:05:50 +01:00
|
|
|
}
|
2021-06-01 23:23:53 +01:00
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
alloc_size = mem_req->size;
|
2021-09-01 22:30:36 +01:00
|
|
|
|
2021-10-26 07:59:47 +01:00
|
|
|
/* XXX Workaround before spec issue #2762 gets resolved. If importing an
|
|
|
|
* internally allocated AHB from the exportable path, memoryTypeIndex is
|
|
|
|
* undefined while defaulting to zero, which can be incompatible with
|
|
|
|
* the queried memoryTypeBits from the combined memory requirement and
|
|
|
|
* dma_buf fd properties. Thus we override the requested memoryTypeIndex
|
|
|
|
* to an applicable one if existed.
|
|
|
|
*/
|
|
|
|
if (internal_ahb) {
|
2022-03-28 21:35:08 +01:00
|
|
|
if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
|
2021-10-26 07:59:47 +01:00
|
|
|
vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
|
2022-03-28 21:35:08 +01:00
|
|
|
mem_req->memoryTypeBits, mem_type_bits);
|
2021-10-26 07:59:47 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
}
|
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
|
2021-10-26 07:59:47 +01:00
|
|
|
}
|
|
|
|
|
2021-09-01 22:30:36 +01:00
|
|
|
/* XXX Workaround before we use cross-domain backend in minigbm. The
|
2022-01-13 20:07:30 +00:00
|
|
|
* blob_mem allocated from virgl backend can have a queried guest
|
|
|
|
* mappable size smaller than the size returned from image memory
|
|
|
|
* requirement.
|
2021-09-01 22:30:36 +01:00
|
|
|
*/
|
|
|
|
force_unmappable = true;
|
2021-05-28 06:00:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
|
2022-03-28 21:35:08 +01:00
|
|
|
struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
|
|
|
|
const VkMemoryRequirements *mem_req =
|
|
|
|
&buf->requirements.memory.memoryRequirements;
|
|
|
|
if (alloc_size < mem_req->size) {
|
2021-06-10 00:05:50 +01:00
|
|
|
vn_log(dev->instance,
|
2022-03-28 21:35:08 +01:00
|
|
|
"alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
|
|
|
|
alloc_size, mem_req->size);
|
2021-06-01 23:23:53 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-06-10 00:05:50 +01:00
|
|
|
}
|
2021-06-01 23:23:53 +01:00
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
alloc_size = mem_req->size;
|
2021-10-26 07:59:47 +01:00
|
|
|
|
2022-03-28 21:35:08 +01:00
|
|
|
assert((1 << mem_type_index) & mem_req->memoryTypeBits);
|
2021-05-19 05:42:57 +01:00
|
|
|
}
|
|
|
|
|
2021-10-26 07:59:47 +01:00
|
|
|
assert((1 << mem_type_index) & mem_type_bits);
|
|
|
|
|
2021-05-19 05:42:57 +01:00
|
|
|
errno = 0;
|
|
|
|
dup_fd = os_dupfd_cloexec(dma_buf_fd);
|
|
|
|
if (dup_fd < 0)
|
|
|
|
return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
|
|
|
|
: VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
|
|
|
/* Spec requires AHB export info to be present, so we must strip it. In
|
|
|
|
* practice, the AHB import path here only needs the main allocation info
|
|
|
|
* and the dedicated_info.
|
|
|
|
*/
|
|
|
|
VkMemoryDedicatedAllocateInfo local_dedicated_info;
|
|
|
|
/* Override when dedicated_info exists and is not the tail struct. */
|
|
|
|
if (dedicated_info && dedicated_info->pNext) {
|
|
|
|
local_dedicated_info = *dedicated_info;
|
|
|
|
local_dedicated_info.pNext = NULL;
|
|
|
|
dedicated_info = &local_dedicated_info;
|
|
|
|
}
|
|
|
|
const VkMemoryAllocateInfo local_alloc_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
.pNext = dedicated_info,
|
|
|
|
.allocationSize = alloc_size,
|
2021-10-26 07:59:47 +01:00
|
|
|
.memoryTypeIndex = mem_type_index,
|
2021-05-19 05:42:57 +01:00
|
|
|
};
|
2021-09-01 22:30:36 +01:00
|
|
|
result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
|
|
|
|
force_unmappable, dup_fd);
|
2021-05-19 05:42:57 +01:00
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
close(dup_fd);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
AHardwareBuffer_acquire(ahb);
|
|
|
|
mem->ahb = ahb;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
2021-05-18 23:37:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_android_device_allocate_ahb(struct vn_device *dev,
|
|
|
|
struct vn_device_memory *mem,
|
2021-06-04 19:43:49 +01:00
|
|
|
const VkMemoryAllocateInfo *alloc_info,
|
|
|
|
const VkAllocationCallbacks *alloc)
|
2021-05-18 23:37:50 +01:00
|
|
|
{
|
2021-05-19 05:42:57 +01:00
|
|
|
const VkMemoryDedicatedAllocateInfo *dedicated_info =
|
|
|
|
vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
|
|
|
|
uint32_t width = 0;
|
|
|
|
uint32_t height = 1;
|
|
|
|
uint32_t layers = 1;
|
|
|
|
uint32_t format = 0;
|
|
|
|
uint64_t usage = 0;
|
|
|
|
struct AHardwareBuffer *ahb = NULL;
|
|
|
|
|
|
|
|
if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
|
|
|
|
const VkImageCreateInfo *image_info =
|
|
|
|
&vn_image_from_handle(dedicated_info->image)->deferred_info->create;
|
|
|
|
assert(image_info);
|
|
|
|
width = image_info->extent.width;
|
|
|
|
height = image_info->extent.height;
|
|
|
|
layers = image_info->arrayLayers;
|
|
|
|
format = vn_android_ahb_format_from_vk_format(image_info->format);
|
|
|
|
usage = vn_android_get_ahb_usage(image_info->usage, image_info->flags);
|
|
|
|
} else {
|
2021-06-20 18:05:41 +01:00
|
|
|
const VkPhysicalDeviceMemoryProperties *mem_props =
|
|
|
|
&dev->physical_device->memory_properties.memoryProperties;
|
|
|
|
|
|
|
|
assert(alloc_info->memoryTypeIndex < mem_props->memoryTypeCount);
|
|
|
|
|
2021-05-19 05:42:57 +01:00
|
|
|
width = alloc_info->allocationSize;
|
|
|
|
format = AHARDWAREBUFFER_FORMAT_BLOB;
|
2021-06-20 18:05:41 +01:00
|
|
|
usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
|
|
|
|
if (mem_props->memoryTypes[alloc_info->memoryTypeIndex].propertyFlags &
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
|
|
|
|
usage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
|
|
|
|
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
|
|
|
|
}
|
2021-05-19 05:42:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ahb = vn_android_ahb_allocate(width, height, layers, format, usage);
|
|
|
|
if (!ahb)
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
2021-06-04 19:43:49 +01:00
|
|
|
VkResult result =
|
2021-10-26 07:59:47 +01:00
|
|
|
vn_android_device_import_ahb(dev, mem, alloc_info, alloc, ahb, true);
|
2021-05-19 05:42:57 +01:00
|
|
|
|
|
|
|
/* ahb alloc has already acquired a ref and import will acquire another,
|
|
|
|
* must release one here to avoid leak.
|
|
|
|
*/
|
|
|
|
AHardwareBuffer_release(ahb);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vn_android_release_ahb(struct AHardwareBuffer *ahb)
|
|
|
|
{
|
|
|
|
AHardwareBuffer_release(ahb);
|
2021-05-18 23:37:50 +01:00
|
|
|
}
|
2021-05-20 23:26:27 +01:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_GetMemoryAndroidHardwareBufferANDROID(
|
|
|
|
VkDevice device,
|
|
|
|
const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
|
|
|
|
struct AHardwareBuffer **pBuffer)
|
|
|
|
{
|
|
|
|
struct vn_device_memory *mem = vn_device_memory_from_handle(pInfo->memory);
|
|
|
|
|
|
|
|
AHardwareBuffer_acquire(mem->ahb);
|
|
|
|
*pBuffer = mem->ahb;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2021-06-30 18:28:47 +01:00
|
|
|
|
|
|
|
struct vn_android_buffer_create_info {
|
|
|
|
VkBufferCreateInfo create;
|
|
|
|
VkExternalMemoryBufferCreateInfo external;
|
|
|
|
VkBufferOpaqueCaptureAddressCreateInfo address;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const VkBufferCreateInfo *
|
|
|
|
vn_android_fix_buffer_create_info(
|
|
|
|
const VkBufferCreateInfo *create_info,
|
|
|
|
struct vn_android_buffer_create_info *local_info)
|
|
|
|
{
|
|
|
|
local_info->create = *create_info;
|
|
|
|
VkBaseOutStructure *dst = (void *)&local_info->create;
|
|
|
|
|
|
|
|
vk_foreach_struct_const(src, create_info->pNext) {
|
|
|
|
void *pnext = NULL;
|
|
|
|
switch (src->sType) {
|
|
|
|
case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO:
|
|
|
|
memcpy(&local_info->external, src, sizeof(local_info->external));
|
|
|
|
local_info->external.handleTypes =
|
|
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
|
|
|
pnext = &local_info->external;
|
|
|
|
break;
|
|
|
|
case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO:
|
|
|
|
memcpy(&local_info->address, src, sizeof(local_info->address));
|
|
|
|
pnext = &local_info->address;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pnext) {
|
|
|
|
dst->pNext = pnext;
|
|
|
|
dst = pnext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dst->pNext = NULL;
|
|
|
|
|
|
|
|
return &local_info->create;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
2021-10-18 22:22:57 +01:00
|
|
|
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev,
|
|
|
|
uint32_t *out_mem_type_bits)
|
2021-06-30 18:28:47 +01:00
|
|
|
{
|
2021-06-30 19:39:00 +01:00
|
|
|
const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
|
|
|
|
/* ensure dma_buf_memory_type_bits covers host visible usage */
|
|
|
|
const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
|
|
|
|
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
|
|
|
|
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
|
|
|
|
AHardwareBuffer *ahb = NULL;
|
|
|
|
int dma_buf_fd = -1;
|
|
|
|
uint64_t alloc_size = 0;
|
|
|
|
uint32_t mem_type_bits = 0;
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
|
|
|
|
if (!ahb)
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
|
2022-04-09 00:13:35 +01:00
|
|
|
dma_buf_fd =
|
|
|
|
vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
|
|
|
|
if (dma_buf_fd < 0) {
|
2021-06-30 19:39:00 +01:00
|
|
|
AHardwareBuffer_release(ahb);
|
2022-04-09 00:13:35 +01:00
|
|
|
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
2021-06-30 19:39:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
|
|
|
|
&mem_type_bits);
|
|
|
|
|
|
|
|
AHardwareBuffer_release(ahb);
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
2021-06-30 18:28:47 +01:00
|
|
|
|
2021-10-18 22:22:57 +01:00
|
|
|
*out_mem_type_bits = mem_type_bits;
|
2021-08-02 16:49:55 +01:00
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_android_buffer_from_ahb(struct vn_device *dev,
|
|
|
|
const VkBufferCreateInfo *create_info,
|
|
|
|
const VkAllocationCallbacks *alloc,
|
|
|
|
struct vn_buffer **out_buf)
|
|
|
|
{
|
|
|
|
struct vn_android_buffer_create_info local_info;
|
|
|
|
VkResult result;
|
|
|
|
|
2021-06-30 18:28:47 +01:00
|
|
|
create_info = vn_android_fix_buffer_create_info(create_info, &local_info);
|
2021-06-30 19:39:00 +01:00
|
|
|
result = vn_buffer_create(dev, create_info, alloc, out_buf);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
/* AHB backed buffer layers on top of dma_buf, so here we must comine the
|
|
|
|
* queried type bits from both buffer memory requirement and dma_buf fd
|
|
|
|
* properties.
|
|
|
|
*/
|
2021-10-21 06:56:30 +01:00
|
|
|
(*out_buf)->requirements.memory.memoryRequirements.memoryTypeBits &=
|
2021-10-15 19:37:23 +01:00
|
|
|
dev->buffer_cache.ahb_mem_type_bits;
|
2021-06-30 19:39:00 +01:00
|
|
|
|
2021-10-21 06:56:30 +01:00
|
|
|
assert((*out_buf)->requirements.memory.memoryRequirements.memoryTypeBits);
|
2021-06-30 19:39:00 +01:00
|
|
|
|
|
|
|
return VK_SUCCESS;
|
2021-06-30 18:28:47 +01:00
|
|
|
}
|