Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/vulkan/wrapper/wrapper_device_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ wrapper_AllocateMemory(VkDevice _device,
vk_error(device, result);
goto out;
}
mem->alloc_size = pAllocateInfo->allocationSize;

VkExternalMemoryHandleTypeFlags valid_handle_types = 0;
if (dedicated_allocate_info) {
Expand Down
31 changes: 31 additions & 0 deletions src/vulkan/wsi/wsi_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ wsi_device_init(struct wsi_device *wsi,
};
GetPhysicalDeviceProperties2(pdevice, &wsi->properties2);

wsi->enable_ahb_ownership_release =
debug_get_bool_option("WRAPPER_AHB_OWNERSHIP_RELEASE",
pddp.driverID ==
VK_DRIVER_ID_NVIDIA_PROPRIETARY);

const char *wine_preload_reserve = getenv("WINEPRELOADRESERVE"); // e.g. 000400000-0008b4000 or 140000000-1400a8000
bool is_win32 = false;

Expand Down Expand Up @@ -888,6 +893,20 @@ wsi_destroy_image(const struct wsi_swapchain *chain,
vk_free(&chain->alloc, image->blit.cmd_buffers);
}

#ifdef __TERMUX__
if (image->ahb_release_cmd_buffers) {
for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
if (!chain->cmd_pools[i] ||
image->ahb_release_cmd_buffers[i] == VK_NULL_HANDLE)
continue;
wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
1, &image->ahb_release_cmd_buffers[i]);
}
vk_free(&chain->alloc, image->ahb_release_cmd_buffers);
image->ahb_release_cmd_buffers = NULL;
}
#endif

wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
wsi->DestroyImage(chain->device, image->image, &chain->alloc);
wsi->DestroyImage(chain->device, image->blit.image, &chain->alloc);
Expand Down Expand Up @@ -1598,6 +1617,18 @@ wsi_common_queue_present(const struct wsi_device *wsi,
submit_info.pWaitDstStageMask = stage_flags;
}
}
#ifdef __TERMUX__
else if (image->ahb_release_cmd_buffers &&
image->ahb_release_cmd_buffers[queue_family_index] != VK_NULL_HANDLE) {
/* No blit: an external consumer reads this AHardwareBuffer directly,
* so hand the image over explicitly. The release transfer makes the
* contents available outside this device; see
* wsi_create_ahb_release_cmd_buffers. */
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers =
&image->ahb_release_cmd_buffers[queue_family_index];
}
#endif

VkFence fence = swapchain->fences[image_index];

Expand Down
1 change: 1 addition & 0 deletions src/vulkan/wsi/wsi_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ struct wsi_device {

bool needs_blit;
bool emulate_bgra8;
bool enable_ahb_ownership_release;

/* Set to true if the implementation is ok with linear WSI images. */
bool wants_linear;
Expand Down
110 changes: 110 additions & 0 deletions src/vulkan/wsi/wsi_common_android.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,107 @@ wsi_create_ahardware_buffer_image_mem(const struct wsi_swapchain *chain,
return VK_SUCCESS;
}

/* Release the image to an external consumer.
*
* The direct AHardwareBuffer path exports an image that another Vulkan device
* may read. Vulkan models that handoff as a queue-family ownership transfer.
* The producing device must perform the release so driver-private image state
* is made available to the importer.
*/
static VkResult
wsi_create_ahb_release_cmd_buffers(const struct wsi_swapchain *chain,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
VkResult result;

const uint32_t count = wsi->queue_family_count;
image->ahb_release_cmd_buffers =
vk_zalloc(&chain->alloc, sizeof(VkCommandBuffer) * count, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!image->ahb_release_cmd_buffers)
return VK_ERROR_OUT_OF_HOST_MEMORY;

for (uint32_t i = 0; i < count; i++) {
if (!chain->cmd_pools[i])
continue;

const VkCommandBufferAllocateInfo cmd_buffer_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = chain->cmd_pools[i],
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
&image->ahb_release_cmd_buffers[i]);
if (result != VK_SUCCESS) {
WRAPPER_LOG(error, "Failed to allocate ahb release cmd buffer, res %d",
result);
return result;
}

const VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
};
result = wsi->BeginCommandBuffer(image->ahb_release_cmd_buffers[i],
&begin_info);
if (result != VK_SUCCESS) {
WRAPPER_LOG(error, "Failed to begin ahb release cmd buffer, res %d",
result);
return result;
}

const VkImageMemoryBarrier release = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
/* The WSI does not know how the application produced the image.
* Cover every write rather than assuming color-attachment or blit
* presentation. */
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
/* Ignored for a release operation. */
.dstAccessMask = 0,
.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
/* The importer has to begin its acquire from the layout this release
* ends in, and it cannot name PRESENT_SRC_KHR for an image that does
* not belong to its own swapchain. GENERAL is valid on both sides and,
* unlike UNDEFINED, keeps the contents -- which is the whole point of
* handing the image over. */
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = i,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT,
.image = image->image,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
wsi->CmdPipelineBarrier(image->ahb_release_cmd_buffers[i],
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, 0, NULL, 0, NULL, 1, &release);

result = wsi->EndCommandBuffer(image->ahb_release_cmd_buffers[i]);
if (result != VK_SUCCESS) {
WRAPPER_LOG(error, "Failed to record ahb release barrier, res %d",
result);
return result;
}
}

mesa_logd("Recorded AHB ownership release barriers");
return VK_SUCCESS;
}

static VkResult
wsi_finish_create_ahardware_buffer_image(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
struct wsi_image *image)
{
return wsi_create_ahb_release_cmd_buffers(chain, image);
}

static VkResult
wsi_create_ahardware_buffer_blit_context(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
Expand Down Expand Up @@ -408,6 +509,15 @@ wsi_configure_android_image(
info->create_mem = wsi_create_ahardware_buffer_blit_context;
} else {
info->create_mem = wsi_create_ahardware_buffer_image_mem;
/* Legacy VkImageMemoryBarrier only permits FOREIGN_EXT ownership
* transfers for exclusive images. Preserve the existing concurrent
* path instead of recording an invalid barrier for it. */
if (info->create.sharingMode == VK_SHARING_MODE_EXCLUSIVE &&
chain->wsi->enable_ahb_ownership_release) {
WRAPPER_LOG(info,
"Enabling AHB ownership release for direct exclusive swapchain");
info->finish_create = wsi_finish_create_ahardware_buffer_image;
}
}

return VK_SUCCESS;
Expand Down
4 changes: 4 additions & 0 deletions src/vulkan/wsi/wsi_common_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ struct wsi_image {
void *cpu_map;
#ifdef __TERMUX__
struct AHardwareBuffer *ahardware_buffer;
/* Command buffers, one per queue family, holding the queue-family ownership
* release into VK_QUEUE_FAMILY_FOREIGN_EXT. Submitted before the image is
* handed to an external consumer. See wsi_create_ahb_release_cmd_buffers. */
VkCommandBuffer *ahb_release_cmd_buffers;
#endif
};

Expand Down