779 lines
25 KiB
C
779 lines
25 KiB
C
/*
|
|
* Copyright 2019 Google LLC
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* based in part on anv and radv which are:
|
|
* Copyright © 2015 Intel Corporation
|
|
* Copyright © 2016 Red Hat.
|
|
* Copyright © 2016 Bas Nieuwenhuizen
|
|
*/
|
|
|
|
#include "vn_image.h"
|
|
|
|
#include "venus-protocol/vn_protocol_driver_image.h"
|
|
#include "venus-protocol/vn_protocol_driver_image_view.h"
|
|
#include "venus-protocol/vn_protocol_driver_sampler.h"
|
|
#include "venus-protocol/vn_protocol_driver_sampler_ycbcr_conversion.h"
|
|
|
|
#include "vn_android.h"
|
|
#include "vn_device.h"
|
|
#include "vn_device_memory.h"
|
|
#include "vn_wsi.h"
|
|
|
|
static void
|
|
vn_image_init_memory_requirements(struct vn_image *img,
|
|
struct vn_device *dev,
|
|
const VkImageCreateInfo *create_info)
|
|
{
|
|
uint32_t plane_count = 1;
|
|
if (create_info->flags & VK_IMAGE_CREATE_DISJOINT_BIT) {
|
|
/* TODO VkDrmFormatModifierPropertiesEXT::drmFormatModifierPlaneCount */
|
|
assert(create_info->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
|
|
|
|
switch (create_info->format) {
|
|
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
|
|
case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
|
|
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
|
|
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
|
|
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
|
|
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
|
|
case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
|
|
case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
|
|
plane_count = 2;
|
|
break;
|
|
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
|
|
case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
|
|
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
|
|
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
|
|
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
|
|
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
|
|
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
|
|
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
|
|
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
|
|
case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
|
|
case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
|
|
case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
|
|
plane_count = 3;
|
|
break;
|
|
default:
|
|
plane_count = 1;
|
|
break;
|
|
}
|
|
}
|
|
assert(plane_count <= ARRAY_SIZE(img->requirements));
|
|
|
|
/* TODO add a per-device cache for the requirements */
|
|
for (uint32_t i = 0; i < plane_count; i++) {
|
|
img->requirements[i].memory.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
|
img->requirements[i].memory.pNext = &img->requirements[i].dedicated;
|
|
img->requirements[i].dedicated.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
|
|
img->requirements[i].dedicated.pNext = NULL;
|
|
}
|
|
|
|
VkDevice dev_handle = vn_device_to_handle(dev);
|
|
VkImage img_handle = vn_image_to_handle(img);
|
|
if (plane_count == 1) {
|
|
vn_call_vkGetImageMemoryRequirements2(
|
|
dev->instance, dev_handle,
|
|
&(VkImageMemoryRequirementsInfo2){
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
|
.image = img_handle,
|
|
},
|
|
&img->requirements[0].memory);
|
|
|
|
/* AHB backed image requires dedicated allocation */
|
|
if (img->deferred_info) {
|
|
img->requirements[0].dedicated.prefersDedicatedAllocation = VK_TRUE;
|
|
img->requirements[0].dedicated.requiresDedicatedAllocation = VK_TRUE;
|
|
}
|
|
} else {
|
|
for (uint32_t i = 0; i < plane_count; i++) {
|
|
vn_call_vkGetImageMemoryRequirements2(
|
|
dev->instance, dev_handle,
|
|
&(VkImageMemoryRequirementsInfo2){
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
|
.pNext =
|
|
&(VkImagePlaneMemoryRequirementsInfo){
|
|
.sType =
|
|
VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,
|
|
.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT << i,
|
|
},
|
|
.image = img_handle,
|
|
},
|
|
&img->requirements[i].memory);
|
|
}
|
|
}
|
|
}
|
|
|
|
static VkResult
|
|
vn_image_deferred_info_init(struct vn_image *img,
|
|
const VkImageCreateInfo *create_info,
|
|
const VkAllocationCallbacks *alloc)
|
|
{
|
|
struct vn_image_create_deferred_info *info = NULL;
|
|
VkBaseOutStructure *dst = NULL;
|
|
|
|
info = vk_zalloc(alloc, sizeof(*info), VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!info)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
info->create = *create_info;
|
|
dst = (void *)&info->create;
|
|
|
|
vk_foreach_struct_const(src, create_info->pNext) {
|
|
void *pnext = NULL;
|
|
switch (src->sType) {
|
|
case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO: {
|
|
/* 12.3. Images
|
|
*
|
|
* If viewFormatCount is zero, pViewFormats is ignored and the image
|
|
* is created as if the VkImageFormatListCreateInfo structure were
|
|
* not included in the pNext chain of VkImageCreateInfo.
|
|
*/
|
|
if (!((const VkImageFormatListCreateInfo *)src)->viewFormatCount)
|
|
break;
|
|
|
|
memcpy(&info->list, src, sizeof(info->list));
|
|
pnext = &info->list;
|
|
|
|
/* need a deep copy for view formats array */
|
|
const size_t size = sizeof(VkFormat) * info->list.viewFormatCount;
|
|
VkFormat *view_formats = vk_zalloc(
|
|
alloc, size, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!view_formats) {
|
|
vk_free(alloc, info);
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
memcpy(view_formats,
|
|
((const VkImageFormatListCreateInfo *)src)->pViewFormats,
|
|
size);
|
|
info->list.pViewFormats = view_formats;
|
|
} break;
|
|
case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
|
|
memcpy(&info->stencil, src, sizeof(info->stencil));
|
|
pnext = &info->stencil;
|
|
break;
|
|
case VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID:
|
|
/* we should have translated the external format */
|
|
assert(create_info->format != VK_FORMAT_UNDEFINED);
|
|
info->from_external_format =
|
|
((const VkExternalFormatANDROID *)src)->externalFormat;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (pnext) {
|
|
dst->pNext = pnext;
|
|
dst = pnext;
|
|
}
|
|
}
|
|
dst->pNext = NULL;
|
|
|
|
img->deferred_info = info;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
vn_image_deferred_info_fini(struct vn_image *img,
|
|
const VkAllocationCallbacks *alloc)
|
|
{
|
|
if (!img->deferred_info)
|
|
return;
|
|
|
|
if (img->deferred_info->list.pViewFormats)
|
|
vk_free(alloc, (void *)img->deferred_info->list.pViewFormats);
|
|
|
|
vk_free(alloc, img->deferred_info);
|
|
}
|
|
|
|
static VkResult
|
|
vn_image_init(struct vn_device *dev,
|
|
const VkImageCreateInfo *create_info,
|
|
struct vn_image *img)
|
|
{
|
|
VkDevice device = vn_device_to_handle(dev);
|
|
VkImage image = vn_image_to_handle(img);
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
img->sharing_mode = create_info->sharingMode;
|
|
|
|
/* TODO async */
|
|
result =
|
|
vn_call_vkCreateImage(dev->instance, device, create_info, NULL, &image);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
vn_image_init_memory_requirements(img, dev, create_info);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
vn_image_create(struct vn_device *dev,
|
|
const VkImageCreateInfo *create_info,
|
|
const VkAllocationCallbacks *alloc,
|
|
struct vn_image **out_img)
|
|
{
|
|
struct vn_image *img = NULL;
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!img)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);
|
|
|
|
result = vn_image_init(dev, create_info, img);
|
|
if (result != VK_SUCCESS) {
|
|
vn_object_base_fini(&img->base);
|
|
vk_free(alloc, img);
|
|
return result;
|
|
}
|
|
|
|
*out_img = img;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
vn_image_init_deferred(struct vn_device *dev,
|
|
const VkImageCreateInfo *create_info,
|
|
struct vn_image *img)
|
|
{
|
|
VkResult result = vn_image_init(dev, create_info, img);
|
|
img->deferred_info->initialized = result == VK_SUCCESS;
|
|
return result;
|
|
}
|
|
|
|
VkResult
|
|
vn_image_create_deferred(struct vn_device *dev,
|
|
const VkImageCreateInfo *create_info,
|
|
const VkAllocationCallbacks *alloc,
|
|
struct vn_image **out_img)
|
|
{
|
|
struct vn_image *img = NULL;
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!img)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);
|
|
|
|
result = vn_image_deferred_info_init(img, create_info, alloc);
|
|
if (result != VK_SUCCESS) {
|
|
vn_object_base_fini(&img->base);
|
|
vk_free(alloc, img);
|
|
return result;
|
|
}
|
|
|
|
*out_img = img;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
/* image commands */
|
|
|
|
VkResult
|
|
vn_CreateImage(VkDevice device,
|
|
const VkImageCreateInfo *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkImage *pImage)
|
|
{
|
|
VN_TRACE_FUNC();
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
struct vn_image *img;
|
|
VkResult result;
|
|
|
|
const struct wsi_image_create_info *wsi_info =
|
|
vn_wsi_find_wsi_image_create_info(pCreateInfo);
|
|
const VkNativeBufferANDROID *anb_info =
|
|
vn_android_find_native_buffer(pCreateInfo);
|
|
const VkExternalMemoryImageCreateInfo *external_info =
|
|
vk_find_struct_const(pCreateInfo->pNext,
|
|
EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
|
|
const bool ahb_info =
|
|
external_info &&
|
|
external_info->handleTypes ==
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
|
|
|
|
#ifdef ANDROID
|
|
/* VkImageSwapchainCreateInfoKHR is not useful at all */
|
|
const VkImageSwapchainCreateInfoKHR *swapchain_info = NULL;
|
|
#else
|
|
const VkImageSwapchainCreateInfoKHR *swapchain_info = vk_find_struct_const(
|
|
pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
|
|
if (swapchain_info && !swapchain_info->swapchain)
|
|
swapchain_info = NULL;
|
|
#endif
|
|
|
|
if (wsi_info) {
|
|
result = vn_wsi_create_image(dev, pCreateInfo, wsi_info, alloc, &img);
|
|
} else if (anb_info) {
|
|
result =
|
|
vn_android_image_from_anb(dev, pCreateInfo, anb_info, alloc, &img);
|
|
} else if (ahb_info) {
|
|
result = vn_android_image_from_ahb(dev, pCreateInfo, alloc, &img);
|
|
} else if (swapchain_info) {
|
|
result = vn_wsi_create_image_from_swapchain(
|
|
dev, pCreateInfo, swapchain_info, alloc, &img);
|
|
} else {
|
|
result = vn_image_create(dev, pCreateInfo, alloc, &img);
|
|
}
|
|
|
|
if (result != VK_SUCCESS)
|
|
return vn_error(dev->instance, result);
|
|
|
|
*pImage = vn_image_to_handle(img);
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_DestroyImage(VkDevice device,
|
|
VkImage image,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
VN_TRACE_FUNC();
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_image *img = vn_image_from_handle(image);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
if (!img)
|
|
return;
|
|
|
|
if (img->wsi.memory && img->wsi.memory_owned) {
|
|
VkDeviceMemory mem_handle = vn_device_memory_to_handle(img->wsi.memory);
|
|
vn_FreeMemory(device, mem_handle, pAllocator);
|
|
}
|
|
|
|
/* must not ask renderer to destroy uninitialized deferred image */
|
|
if (!img->deferred_info || img->deferred_info->initialized)
|
|
vn_async_vkDestroyImage(dev->instance, device, image, NULL);
|
|
|
|
vn_image_deferred_info_fini(img, alloc);
|
|
|
|
vn_object_base_fini(&img->base);
|
|
vk_free(alloc, img);
|
|
}
|
|
|
|
void
|
|
vn_GetImageMemoryRequirements2(VkDevice device,
|
|
const VkImageMemoryRequirementsInfo2 *pInfo,
|
|
VkMemoryRequirements2 *pMemoryRequirements)
|
|
{
|
|
const struct vn_image *img = vn_image_from_handle(pInfo->image);
|
|
union {
|
|
VkBaseOutStructure *pnext;
|
|
VkMemoryRequirements2 *two;
|
|
VkMemoryDedicatedRequirements *dedicated;
|
|
} u = { .two = pMemoryRequirements };
|
|
|
|
uint32_t plane = 0;
|
|
const VkImagePlaneMemoryRequirementsInfo *plane_info =
|
|
vk_find_struct_const(pInfo->pNext,
|
|
IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);
|
|
if (plane_info) {
|
|
switch (plane_info->planeAspect) {
|
|
case VK_IMAGE_ASPECT_PLANE_1_BIT:
|
|
plane = 1;
|
|
break;
|
|
case VK_IMAGE_ASPECT_PLANE_2_BIT:
|
|
plane = 2;
|
|
break;
|
|
default:
|
|
plane = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (u.pnext) {
|
|
switch (u.pnext->sType) {
|
|
case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:
|
|
u.two->memoryRequirements =
|
|
img->requirements[plane].memory.memoryRequirements;
|
|
break;
|
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
|
|
u.dedicated->prefersDedicatedAllocation =
|
|
img->requirements[plane].dedicated.prefersDedicatedAllocation;
|
|
u.dedicated->requiresDedicatedAllocation =
|
|
img->requirements[plane].dedicated.requiresDedicatedAllocation;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
u.pnext = u.pnext->pNext;
|
|
}
|
|
}
|
|
|
|
void
|
|
vn_GetImageSparseMemoryRequirements2(
|
|
VkDevice device,
|
|
const VkImageSparseMemoryRequirementsInfo2 *pInfo,
|
|
uint32_t *pSparseMemoryRequirementCount,
|
|
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
/* TODO per-device cache */
|
|
vn_call_vkGetImageSparseMemoryRequirements2(dev->instance, device, pInfo,
|
|
pSparseMemoryRequirementCount,
|
|
pSparseMemoryRequirements);
|
|
}
|
|
|
|
static void
|
|
vn_image_bind_wsi_memory(struct vn_image *img, struct vn_device_memory *mem)
|
|
{
|
|
assert(img->wsi.is_wsi && !img->wsi.memory);
|
|
img->wsi.memory = mem;
|
|
}
|
|
|
|
VkResult
|
|
vn_BindImageMemory2(VkDevice device,
|
|
uint32_t bindInfoCount,
|
|
const VkBindImageMemoryInfo *pBindInfos)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
|
|
|
|
VkBindImageMemoryInfo *local_infos = NULL;
|
|
for (uint32_t i = 0; i < bindInfoCount; i++) {
|
|
const VkBindImageMemoryInfo *info = &pBindInfos[i];
|
|
struct vn_image *img = vn_image_from_handle(info->image);
|
|
struct vn_device_memory *mem =
|
|
vn_device_memory_from_handle(info->memory);
|
|
|
|
/* no bind info fixup needed */
|
|
if (mem && !mem->base_memory) {
|
|
if (img->wsi.is_wsi)
|
|
vn_image_bind_wsi_memory(img, mem);
|
|
continue;
|
|
}
|
|
|
|
if (!mem) {
|
|
#ifdef ANDROID
|
|
/* TODO handle VkNativeBufferANDROID when we bump up
|
|
* VN_ANDROID_NATIVE_BUFFER_SPEC_VERSION
|
|
*/
|
|
unreachable("VkBindImageMemoryInfo with no memory");
|
|
#else
|
|
const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
|
|
vk_find_struct_const(info->pNext,
|
|
BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
|
|
assert(img->wsi.is_wsi && swapchain_info);
|
|
|
|
struct vn_image *swapchain_img =
|
|
vn_image_from_handle(wsi_common_get_image(
|
|
swapchain_info->swapchain, swapchain_info->imageIndex));
|
|
mem = swapchain_img->wsi.memory;
|
|
#endif
|
|
}
|
|
|
|
if (img->wsi.is_wsi)
|
|
vn_image_bind_wsi_memory(img, mem);
|
|
|
|
if (!local_infos) {
|
|
const size_t size = sizeof(*local_infos) * bindInfoCount;
|
|
local_infos = vk_alloc(alloc, size, VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
if (!local_infos)
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
memcpy(local_infos, pBindInfos, size);
|
|
}
|
|
|
|
/* If mem is suballocated, mem->base_memory is non-NULL and we must
|
|
* patch it in. If VkBindImageMemorySwapchainInfoKHR is given, we've
|
|
* looked mem up above and also need to patch it in.
|
|
*/
|
|
local_infos[i].memory = vn_device_memory_to_handle(
|
|
mem->base_memory ? mem->base_memory : mem);
|
|
local_infos[i].memoryOffset += mem->base_offset;
|
|
}
|
|
if (local_infos)
|
|
pBindInfos = local_infos;
|
|
|
|
vn_async_vkBindImageMemory2(dev->instance, device, bindInfoCount,
|
|
pBindInfos);
|
|
|
|
vk_free(alloc, local_infos);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
vn_GetImageDrmFormatModifierPropertiesEXT(
|
|
VkDevice device,
|
|
VkImage image,
|
|
VkImageDrmFormatModifierPropertiesEXT *pProperties)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
/* TODO local cache */
|
|
return vn_call_vkGetImageDrmFormatModifierPropertiesEXT(
|
|
dev->instance, device, image, pProperties);
|
|
}
|
|
|
|
void
|
|
vn_GetImageSubresourceLayout(VkDevice device,
|
|
VkImage image,
|
|
const VkImageSubresource *pSubresource,
|
|
VkSubresourceLayout *pLayout)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_image *img = vn_image_from_handle(image);
|
|
|
|
/* override aspect mask for wsi/ahb images with tiling modifier */
|
|
VkImageSubresource local_subresource;
|
|
if ((img->wsi.is_wsi && img->wsi.tiling_override ==
|
|
VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) ||
|
|
img->deferred_info) {
|
|
VkImageAspectFlags aspect = pSubresource->aspectMask;
|
|
switch (aspect) {
|
|
case VK_IMAGE_ASPECT_COLOR_BIT:
|
|
case VK_IMAGE_ASPECT_DEPTH_BIT:
|
|
case VK_IMAGE_ASPECT_STENCIL_BIT:
|
|
case VK_IMAGE_ASPECT_PLANE_0_BIT:
|
|
aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
|
|
break;
|
|
case VK_IMAGE_ASPECT_PLANE_1_BIT:
|
|
aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
|
|
break;
|
|
case VK_IMAGE_ASPECT_PLANE_2_BIT:
|
|
aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* only handle supported aspect override */
|
|
if (aspect != pSubresource->aspectMask) {
|
|
local_subresource = *pSubresource;
|
|
local_subresource.aspectMask = aspect;
|
|
pSubresource = &local_subresource;
|
|
}
|
|
}
|
|
|
|
/* TODO local cache */
|
|
vn_call_vkGetImageSubresourceLayout(dev->instance, device, image,
|
|
pSubresource, pLayout);
|
|
}
|
|
|
|
/* image view commands */
|
|
|
|
VkResult
|
|
vn_CreateImageView(VkDevice device,
|
|
const VkImageViewCreateInfo *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkImageView *pView)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_image *img = vn_image_from_handle(pCreateInfo->image);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
VkImageViewCreateInfo local_info;
|
|
if (img->deferred_info && img->deferred_info->from_external_format) {
|
|
assert(pCreateInfo->format == VK_FORMAT_UNDEFINED);
|
|
|
|
local_info = *pCreateInfo;
|
|
local_info.format = img->deferred_info->create.format;
|
|
pCreateInfo = &local_info;
|
|
|
|
assert(pCreateInfo->format != VK_FORMAT_UNDEFINED);
|
|
}
|
|
|
|
struct vn_image_view *view =
|
|
vk_zalloc(alloc, sizeof(*view), VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!view)
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
vn_object_base_init(&view->base, VK_OBJECT_TYPE_IMAGE_VIEW, &dev->base);
|
|
view->image = img;
|
|
|
|
VkImageView view_handle = vn_image_view_to_handle(view);
|
|
vn_async_vkCreateImageView(dev->instance, device, pCreateInfo, NULL,
|
|
&view_handle);
|
|
|
|
*pView = view_handle;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_DestroyImageView(VkDevice device,
|
|
VkImageView imageView,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_image_view *view = vn_image_view_from_handle(imageView);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
if (!view)
|
|
return;
|
|
|
|
vn_async_vkDestroyImageView(dev->instance, device, imageView, NULL);
|
|
|
|
vn_object_base_fini(&view->base);
|
|
vk_free(alloc, view);
|
|
}
|
|
|
|
/* sampler commands */
|
|
|
|
VkResult
|
|
vn_CreateSampler(VkDevice device,
|
|
const VkSamplerCreateInfo *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkSampler *pSampler)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
struct vn_sampler *sampler =
|
|
vk_zalloc(alloc, sizeof(*sampler), VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!sampler)
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
vn_object_base_init(&sampler->base, VK_OBJECT_TYPE_SAMPLER, &dev->base);
|
|
|
|
VkSampler sampler_handle = vn_sampler_to_handle(sampler);
|
|
vn_async_vkCreateSampler(dev->instance, device, pCreateInfo, NULL,
|
|
&sampler_handle);
|
|
|
|
*pSampler = sampler_handle;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_DestroySampler(VkDevice device,
|
|
VkSampler _sampler,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_sampler *sampler = vn_sampler_from_handle(_sampler);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
if (!sampler)
|
|
return;
|
|
|
|
vn_async_vkDestroySampler(dev->instance, device, _sampler, NULL);
|
|
|
|
vn_object_base_fini(&sampler->base);
|
|
vk_free(alloc, sampler);
|
|
}
|
|
|
|
/* sampler YCbCr conversion commands */
|
|
|
|
VkResult
|
|
vn_CreateSamplerYcbcrConversion(
|
|
VkDevice device,
|
|
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkSamplerYcbcrConversion *pYcbcrConversion)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
const VkExternalFormatANDROID *ext_info =
|
|
vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_FORMAT_ANDROID);
|
|
|
|
VkSamplerYcbcrConversionCreateInfo local_info;
|
|
if (ext_info && ext_info->externalFormat) {
|
|
assert(pCreateInfo->format == VK_FORMAT_UNDEFINED);
|
|
|
|
local_info = *pCreateInfo;
|
|
local_info.format =
|
|
vn_android_drm_format_to_vk_format(ext_info->externalFormat);
|
|
local_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
local_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
local_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
local_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
pCreateInfo = &local_info;
|
|
|
|
assert(pCreateInfo->format != VK_FORMAT_UNDEFINED);
|
|
}
|
|
|
|
struct vn_sampler_ycbcr_conversion *conv =
|
|
vk_zalloc(alloc, sizeof(*conv), VN_DEFAULT_ALIGN,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!conv)
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
vn_object_base_init(&conv->base, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
|
|
&dev->base);
|
|
|
|
VkSamplerYcbcrConversion conv_handle =
|
|
vn_sampler_ycbcr_conversion_to_handle(conv);
|
|
vn_async_vkCreateSamplerYcbcrConversion(dev->instance, device, pCreateInfo,
|
|
NULL, &conv_handle);
|
|
|
|
*pYcbcrConversion = conv_handle;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_DestroySamplerYcbcrConversion(VkDevice device,
|
|
VkSamplerYcbcrConversion ycbcrConversion,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_sampler_ycbcr_conversion *conv =
|
|
vn_sampler_ycbcr_conversion_from_handle(ycbcrConversion);
|
|
const VkAllocationCallbacks *alloc =
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
if (!conv)
|
|
return;
|
|
|
|
vn_async_vkDestroySamplerYcbcrConversion(dev->instance, device,
|
|
ycbcrConversion, NULL);
|
|
|
|
vn_object_base_fini(&conv->base);
|
|
vk_free(alloc, conv);
|
|
}
|
|
|
|
void
|
|
vn_GetDeviceImageMemoryRequirements(
|
|
VkDevice device,
|
|
const VkDeviceImageMemoryRequirements *pInfo,
|
|
VkMemoryRequirements2 *pMemoryRequirements)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
/* TODO per-device cache */
|
|
vn_call_vkGetDeviceImageMemoryRequirements(dev->instance, device, pInfo,
|
|
pMemoryRequirements);
|
|
}
|
|
|
|
void
|
|
vn_GetDeviceImageSparseMemoryRequirements(
|
|
VkDevice device,
|
|
const VkDeviceImageMemoryRequirements *pInfo,
|
|
uint32_t *pSparseMemoryRequirementCount,
|
|
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
/* TODO per-device cache */
|
|
vn_call_vkGetDeviceImageSparseMemoryRequirements(
|
|
dev->instance, device, pInfo, pSparseMemoryRequirementCount,
|
|
pSparseMemoryRequirements);
|
|
}
|