| /* |
| * 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); |
| } |