venus: handle wsi image queue ownership transfer for Android
1. pre-allocate command pools at device creation if anb enabled 2. force VK_SHARING_MODE_CONCURRENT for wsi image if necessary 3. pre-allocate and record command buffers at android wsi image creation 4. transfer in the ownership at vkAcquireImageANDROID 5. transfer out the ownership at vkQueueSignalReleaseImageANDROID Signed-off-by: Yiwei Zhang <zzyiwei@chromium.org> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10335>
This commit is contained in:
parent
174fca5498
commit
96ec6b3d8f
|
@ -9,7 +9,6 @@
|
|||
*/
|
||||
|
||||
#include "vn_android.h"
|
||||
#include "vn_common.h"
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <hardware/hwvulkan.h>
|
||||
|
@ -189,12 +188,36 @@ vn_image_from_anb(struct vn_device *dev,
|
|||
VkImageCreateInfo local_image_info = *image_info;
|
||||
local_image_info.pNext = &drm_mod_info;
|
||||
local_image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
||||
|
||||
/* Force VK_SHARING_MODE_CONCURRENT if necessary.
|
||||
* For physical devices supporting multiple queue families, if a swapchain is
|
||||
* created with exclusive mode, we must transfer the image ownership into the
|
||||
* queue family of the present queue. However, there's no way to get that
|
||||
* queue at the 1st acquire of the image. Thus, when multiple queue families
|
||||
* are supported in a physical device, we include all queue families in the
|
||||
* image create info along with VK_SHARING_MODE_CONCURRENT, which forces us
|
||||
* to transfer the ownership into VK_QUEUE_FAMILY_IGNORED. Then if there's
|
||||
* only one queue family, we can safely use queue family index 0.
|
||||
*/
|
||||
if (dev->physical_device->queue_family_count > 1) {
|
||||
local_image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||
local_image_info.queueFamilyIndexCount =
|
||||
dev->physical_device->queue_family_count;
|
||||
local_image_info.pQueueFamilyIndices =
|
||||
dev->android_wsi->queue_family_indices;
|
||||
}
|
||||
|
||||
/* encoder will strip the Android specific pNext structs */
|
||||
result = vn_image_create(dev, &local_image_info, alloc, &img);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
image = vn_image_to_handle(img);
|
||||
|
||||
result = vn_image_android_wsi_init(dev, img, alloc);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
VkMemoryRequirements mem_req;
|
||||
vn_GetImageMemoryRequirements(device, image, &mem_req);
|
||||
if (!mem_req.memoryTypeBits) {
|
||||
|
@ -272,9 +295,19 @@ fail:
|
|||
return vn_error(dev->instance, result);
|
||||
}
|
||||
|
||||
static bool
|
||||
vn_is_queue_compatible_with_wsi(struct vn_queue *queue)
|
||||
{
|
||||
static const int32_t compatible_flags =
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;
|
||||
return compatible_flags & queue->device->physical_device
|
||||
->queue_family_properties[queue->family]
|
||||
.queueFamilyProperties.queueFlags;
|
||||
}
|
||||
|
||||
VkResult
|
||||
vn_AcquireImageANDROID(VkDevice device,
|
||||
UNUSED VkImage image,
|
||||
VkImage image,
|
||||
int nativeFenceFd,
|
||||
VkSemaphore semaphore,
|
||||
VkFence fence)
|
||||
|
@ -285,6 +318,8 @@ vn_AcquireImageANDROID(VkDevice device,
|
|||
struct vn_device *dev = vn_device_from_handle(device);
|
||||
struct vn_semaphore *sem = vn_semaphore_from_handle(semaphore);
|
||||
struct vn_fence *fen = vn_fence_from_handle(fence);
|
||||
struct vn_image *img = vn_image_from_handle(image);
|
||||
struct vn_queue *queue = img->acquire_queue;
|
||||
|
||||
if (nativeFenceFd >= 0) {
|
||||
int ret = sync_wait(nativeFenceFd, INT32_MAX);
|
||||
|
@ -300,7 +335,41 @@ vn_AcquireImageANDROID(VkDevice device,
|
|||
if (fen)
|
||||
vn_fence_signal_wsi(dev, fen);
|
||||
|
||||
return VK_SUCCESS;
|
||||
if (!queue) {
|
||||
/* pick a compatible queue for the 1st acquire of this image */
|
||||
for (uint32_t i = 0; i < dev->queue_count; i++) {
|
||||
if (vn_is_queue_compatible_with_wsi(&dev->queues[i])) {
|
||||
queue = &dev->queues[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!queue)
|
||||
return vn_error(dev->instance, VK_ERROR_UNKNOWN);
|
||||
|
||||
const VkSubmitInfo submit_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 0,
|
||||
.pWaitSemaphores = NULL,
|
||||
.pWaitDstStageMask = NULL,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers =
|
||||
&img->ownership_cmds[queue->family].cmds[VN_IMAGE_OWNERSHIP_ACQUIRE],
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL,
|
||||
};
|
||||
|
||||
VkResult result = vn_QueueSubmit(vn_queue_to_handle(queue), 1,
|
||||
&submit_info, queue->wait_fence);
|
||||
if (result != VK_SUCCESS)
|
||||
return vn_error(dev->instance, result);
|
||||
|
||||
result =
|
||||
vn_WaitForFences(device, 1, &queue->wait_fence, VK_TRUE, UINT64_MAX);
|
||||
vn_ResetFences(device, 1, &queue->wait_fence);
|
||||
|
||||
return vn_result(dev->instance, result);
|
||||
}
|
||||
|
||||
VkResult
|
||||
|
@ -316,13 +385,14 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
|
|||
*/
|
||||
VkResult result = VK_SUCCESS;
|
||||
struct vn_queue *que = vn_queue_from_handle(queue);
|
||||
struct vn_image *img = vn_image_from_handle(image);
|
||||
const VkAllocationCallbacks *alloc = &que->device->base.base.alloc;
|
||||
VkDevice device = vn_device_to_handle(que->device);
|
||||
VkPipelineStageFlags local_stage_masks[8];
|
||||
VkPipelineStageFlags *stage_masks = local_stage_masks;
|
||||
|
||||
if (waitSemaphoreCount == 0)
|
||||
goto out;
|
||||
if (!vn_is_queue_compatible_with_wsi(que))
|
||||
return vn_error(que->device->instance, VK_ERROR_UNKNOWN);
|
||||
|
||||
if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) {
|
||||
stage_masks =
|
||||
|
@ -343,12 +413,15 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
|
|||
.waitSemaphoreCount = waitSemaphoreCount,
|
||||
.pWaitSemaphores = pWaitSemaphores,
|
||||
.pWaitDstStageMask = stage_masks,
|
||||
.commandBufferCount = 0,
|
||||
.pCommandBuffers = NULL,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers =
|
||||
&img->ownership_cmds[que->family].cmds[VN_IMAGE_OWNERSHIP_RELEASE],
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL,
|
||||
};
|
||||
result = vn_QueueSubmit(queue, 1, &submit_info, que->wait_fence);
|
||||
if (stage_masks != local_stage_masks)
|
||||
vk_free(alloc, stage_masks);
|
||||
if (result != VK_SUCCESS)
|
||||
goto out;
|
||||
|
||||
|
@ -356,7 +429,99 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
|
|||
vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX);
|
||||
vn_ResetFences(device, 1, &que->wait_fence);
|
||||
|
||||
img->acquire_queue = que;
|
||||
|
||||
out:
|
||||
*pNativeFenceFd = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult
|
||||
vn_android_wsi_init(struct vn_device *dev, const VkAllocationCallbacks *alloc)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
struct vn_android_wsi *android_wsi =
|
||||
vk_zalloc(alloc, sizeof(struct vn_android_wsi), VN_DEFAULT_ALIGN,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!android_wsi)
|
||||
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
const uint32_t count = dev->physical_device->queue_family_count;
|
||||
if (count > 1) {
|
||||
android_wsi->queue_family_indices =
|
||||
vk_alloc(alloc, sizeof(uint32_t) * count, VN_DEFAULT_ALIGN,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!android_wsi->queue_family_indices) {
|
||||
result = VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
android_wsi->queue_family_indices[i] = i;
|
||||
}
|
||||
|
||||
android_wsi->cmd_pools =
|
||||
vk_zalloc(alloc, sizeof(VkCommandPool) * count, VN_DEFAULT_ALIGN,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!android_wsi->cmd_pools) {
|
||||
result = VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
VkDevice device = vn_device_to_handle(dev);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
const VkCommandPoolCreateInfo cmd_pool_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.queueFamilyIndex = i,
|
||||
};
|
||||
result = vn_CreateCommandPool(device, &cmd_pool_info, alloc,
|
||||
&android_wsi->cmd_pools[i]);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mtx_init(&android_wsi->cmd_pools_lock, mtx_plain);
|
||||
|
||||
dev->android_wsi = android_wsi;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
if (android_wsi->cmd_pools) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (android_wsi->cmd_pools[i] != VK_NULL_HANDLE)
|
||||
vn_DestroyCommandPool(device, android_wsi->cmd_pools[i], alloc);
|
||||
}
|
||||
vk_free(alloc, android_wsi->cmd_pools);
|
||||
}
|
||||
|
||||
if (android_wsi->queue_family_indices)
|
||||
vk_free(alloc, android_wsi->queue_family_indices);
|
||||
|
||||
vk_free(alloc, android_wsi);
|
||||
|
||||
return vn_error(dev->instance, result);
|
||||
}
|
||||
|
||||
void
|
||||
vn_android_wsi_fini(struct vn_device *dev, const VkAllocationCallbacks *alloc)
|
||||
{
|
||||
if (!dev->android_wsi)
|
||||
return;
|
||||
|
||||
mtx_destroy(&dev->android_wsi->cmd_pools_lock);
|
||||
|
||||
VkDevice device = vn_device_to_handle(dev);
|
||||
for (uint32_t i = 0; i < dev->physical_device->queue_family_count; i++) {
|
||||
vn_DestroyCommandPool(device, dev->android_wsi->cmd_pools[i], alloc);
|
||||
}
|
||||
vk_free(alloc, dev->android_wsi->cmd_pools);
|
||||
|
||||
if (dev->android_wsi->queue_family_indices)
|
||||
vk_free(alloc, dev->android_wsi->queue_family_indices);
|
||||
|
||||
vk_free(alloc, dev->android_wsi);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#ifndef VN_ANDROID_H
|
||||
#define VN_ANDROID_H
|
||||
|
||||
#include "vn_common.h"
|
||||
|
||||
#include <vulkan/vk_android_native_buffer.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
@ -20,6 +22,15 @@
|
|||
struct vn_device;
|
||||
struct vn_image;
|
||||
|
||||
struct vn_android_wsi {
|
||||
/* command pools, one per queue family */
|
||||
VkCommandPool *cmd_pools;
|
||||
/* use one lock to simplify */
|
||||
mtx_t cmd_pools_lock;
|
||||
/* for forcing VK_SHARING_MODE_CONCURRENT */
|
||||
uint32_t *queue_family_indices;
|
||||
};
|
||||
|
||||
VkResult
|
||||
vn_image_from_anb(struct vn_device *dev,
|
||||
const VkImageCreateInfo *image_info,
|
||||
|
@ -27,4 +38,28 @@ vn_image_from_anb(struct vn_device *dev,
|
|||
const VkAllocationCallbacks *alloc,
|
||||
struct vn_image **out_img);
|
||||
|
||||
#ifdef ANDROID
|
||||
VkResult
|
||||
vn_android_wsi_init(struct vn_device *dev,
|
||||
const VkAllocationCallbacks *alloc);
|
||||
|
||||
void
|
||||
vn_android_wsi_fini(struct vn_device *dev,
|
||||
const VkAllocationCallbacks *alloc);
|
||||
#else
|
||||
static inline VkResult
|
||||
vn_android_wsi_init(UNUSED struct vn_device *dev,
|
||||
UNUSED const VkAllocationCallbacks *alloc)
|
||||
{
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vn_android_wsi_fini(UNUSED struct vn_device *dev,
|
||||
UNUSED const VkAllocationCallbacks *alloc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VN_ANDROID_H */
|
||||
|
|
|
@ -3158,6 +3158,12 @@ vn_CreateDevice(VkPhysicalDevice physicalDevice,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (dev->base.base.enabled_extensions.ANDROID_native_buffer) {
|
||||
result = vn_android_wsi_init(dev, alloc);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) {
|
||||
struct vn_device_memory_pool *pool = &dev->memory_pools[i];
|
||||
mtx_init(&pool->mutex, mtx_plain);
|
||||
|
@ -3188,6 +3194,9 @@ vn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
|
|||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->base.base.enabled_extensions.ANDROID_native_buffer)
|
||||
vn_android_wsi_fini(dev, alloc);
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++)
|
||||
vn_device_memory_pool_fini(dev, i);
|
||||
|
||||
|
|
|
@ -112,6 +112,8 @@ struct vn_device {
|
|||
uint32_t queue_count;
|
||||
|
||||
struct vn_device_memory_pool memory_pools[VK_MAX_MEMORY_TYPES];
|
||||
|
||||
struct vn_android_wsi *android_wsi;
|
||||
};
|
||||
VK_DEFINE_HANDLE_CASTS(vn_device,
|
||||
base.base.base,
|
||||
|
|
|
@ -18,6 +18,154 @@
|
|||
#include "vn_android.h"
|
||||
#include "vn_device.h"
|
||||
#include "vn_device_memory.h"
|
||||
#include "vn_queue.h"
|
||||
|
||||
static VkResult
|
||||
vn_record_ownership_cmds(struct vn_device *dev,
|
||||
struct vn_image *img,
|
||||
uint32_t family,
|
||||
uint32_t internal_index,
|
||||
uint32_t external_index,
|
||||
VkCommandBuffer *out_cmds)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
VkDevice device = vn_device_to_handle(dev);
|
||||
VkImage image = vn_image_to_handle(img);
|
||||
VkCommandBuffer cmds[2];
|
||||
|
||||
const VkCommandBufferAllocateInfo cmd_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.pNext = NULL,
|
||||
.commandPool = dev->android_wsi->cmd_pools[family],
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = 2,
|
||||
};
|
||||
|
||||
mtx_lock(&dev->android_wsi->cmd_pools_lock);
|
||||
result = vn_AllocateCommandBuffers(device, &cmd_info, cmds);
|
||||
mtx_unlock(&dev->android_wsi->cmd_pools_lock);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
return vn_error(dev->instance, result);
|
||||
|
||||
/* record the foreign/external queue to internal queue transfer */
|
||||
const VkCommandBufferBeginInfo begin_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
};
|
||||
vn_BeginCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_ACQUIRE], &begin_info);
|
||||
VkImageMemoryBarrier barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = NULL,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = 0,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.srcQueueFamilyIndex = external_index,
|
||||
.dstQueueFamilyIndex = internal_index,
|
||||
.image = image,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
vn_CmdPipelineBarrier(
|
||||
cmds[VN_IMAGE_OWNERSHIP_ACQUIRE], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
|
||||
vn_EndCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_ACQUIRE]);
|
||||
|
||||
/* record the internal queue to foreign/external queue transfer */
|
||||
vn_BeginCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_RELEASE], &begin_info);
|
||||
barrier.srcQueueFamilyIndex = internal_index;
|
||||
barrier.dstQueueFamilyIndex = external_index;
|
||||
vn_CmdPipelineBarrier(
|
||||
cmds[VN_IMAGE_OWNERSHIP_RELEASE], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
|
||||
vn_EndCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_RELEASE]);
|
||||
|
||||
out_cmds[VN_IMAGE_OWNERSHIP_ACQUIRE] = cmds[VN_IMAGE_OWNERSHIP_ACQUIRE];
|
||||
out_cmds[VN_IMAGE_OWNERSHIP_RELEASE] = cmds[VN_IMAGE_OWNERSHIP_RELEASE];
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
vn_image_android_wsi_init(struct vn_device *dev,
|
||||
struct vn_image *img,
|
||||
const VkAllocationCallbacks *alloc)
|
||||
{
|
||||
VkDevice device = vn_device_to_handle(dev);
|
||||
VkResult result = VK_SUCCESS;
|
||||
const uint32_t internal_index =
|
||||
img->sharing_mode == VK_SHARING_MODE_EXCLUSIVE
|
||||
? 0
|
||||
: VK_QUEUE_FAMILY_IGNORED;
|
||||
const uint32_t external_index =
|
||||
(dev->base.base.enabled_extensions.EXT_queue_family_foreign ||
|
||||
dev->physical_device->renderer_extensions.EXT_queue_family_foreign)
|
||||
? VK_QUEUE_FAMILY_FOREIGN_EXT
|
||||
: VK_QUEUE_FAMILY_EXTERNAL;
|
||||
const uint32_t count = dev->physical_device->queue_family_count;
|
||||
|
||||
struct vn_image_ownership_cmds *local_cmds =
|
||||
vk_zalloc(alloc, sizeof(*local_cmds) * count, VN_DEFAULT_ALIGN,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!local_cmds)
|
||||
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
/* skip recording if no queue is created from this family */
|
||||
uint32_t j = 0;
|
||||
for (; j < dev->queue_count; j++) {
|
||||
if (dev->queues[j].family == i)
|
||||
break;
|
||||
}
|
||||
if (j == dev->queue_count)
|
||||
continue;
|
||||
|
||||
result = vn_record_ownership_cmds(dev, img, i, internal_index,
|
||||
external_index, local_cmds[i].cmds);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
img->ownership_cmds = local_cmds;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (local_cmds[i].cmds[0] != VK_NULL_HANDLE)
|
||||
vn_FreeCommandBuffers(device, dev->android_wsi->cmd_pools[i], 2,
|
||||
local_cmds[i].cmds);
|
||||
}
|
||||
vk_free(alloc, local_cmds);
|
||||
return vn_error(dev->instance, result);
|
||||
}
|
||||
|
||||
static void
|
||||
vn_image_android_wsi_fini(struct vn_device *dev,
|
||||
struct vn_image *img,
|
||||
const VkAllocationCallbacks *alloc)
|
||||
{
|
||||
if (!dev->android_wsi || !img->ownership_cmds)
|
||||
return;
|
||||
|
||||
VkDevice device = vn_device_to_handle(dev);
|
||||
|
||||
mtx_lock(&dev->android_wsi->cmd_pools_lock);
|
||||
for (uint32_t i = 0; i < dev->physical_device->queue_family_count; i++) {
|
||||
if (img->ownership_cmds[i].cmds[0] != VK_NULL_HANDLE)
|
||||
vn_FreeCommandBuffers(device, dev->android_wsi->cmd_pools[i], 2,
|
||||
img->ownership_cmds[i].cmds);
|
||||
}
|
||||
mtx_unlock(&dev->android_wsi->cmd_pools_lock);
|
||||
|
||||
vk_free(alloc, img->ownership_cmds);
|
||||
}
|
||||
|
||||
static void
|
||||
vn_image_init_memory_requirements(struct vn_image *img,
|
||||
|
@ -125,6 +273,8 @@ vn_image_create(struct vn_device *dev,
|
|||
|
||||
vn_image_init_memory_requirements(img, dev, create_info);
|
||||
|
||||
img->sharing_mode = create_info->sharingMode;
|
||||
|
||||
*out_img = img;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
@ -186,6 +336,8 @@ vn_DestroyImage(VkDevice device,
|
|||
if (!img)
|
||||
return;
|
||||
|
||||
vn_image_android_wsi_fini(dev, img, alloc);
|
||||
|
||||
if (img->private_memory != VK_NULL_HANDLE)
|
||||
vn_FreeMemory(device, img->private_memory, pAllocator);
|
||||
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
|
||||
#include "vn_common.h"
|
||||
|
||||
enum {
|
||||
VN_IMAGE_OWNERSHIP_ACQUIRE = 0,
|
||||
VN_IMAGE_OWNERSHIP_RELEASE = 1,
|
||||
};
|
||||
|
||||
struct vn_image_ownership_cmds {
|
||||
VkCommandBuffer cmds[2];
|
||||
};
|
||||
|
||||
struct vn_image {
|
||||
struct vn_object_base base;
|
||||
|
||||
|
@ -20,6 +29,10 @@ struct vn_image {
|
|||
VkMemoryDedicatedRequirements dedicated_requirements[4];
|
||||
/* For VK_ANDROID_native_buffer, the WSI image owns the memory, */
|
||||
VkDeviceMemory private_memory;
|
||||
/* For queue family ownership transfer of WSI images */
|
||||
VkSharingMode sharing_mode;
|
||||
struct vn_image_ownership_cmds *ownership_cmds;
|
||||
struct vn_queue *acquire_queue;
|
||||
};
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(vn_image,
|
||||
base.base,
|
||||
|
@ -56,4 +69,9 @@ vn_image_create(struct vn_device *dev,
|
|||
const VkAllocationCallbacks *alloc,
|
||||
struct vn_image **out_img);
|
||||
|
||||
VkResult
|
||||
vn_image_android_wsi_init(struct vn_device *dev,
|
||||
struct vn_image *img,
|
||||
const VkAllocationCallbacks *alloc);
|
||||
|
||||
#endif /* VN_IMAGE_H */
|
||||
|
|
Loading…
Reference in New Issue