vulkan/wsi: untangle buffer-images from prime

Not all Vulkan implementations allows rendering to linear images, so in
order to support scanning out from these on Windows we might have to copy
through a buffer like we do in the PRIME path.

To avoid reimplementing the same, let's instead generalize the code a
bit so it doesn't have to specfy any PRIME-specific details.

Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12210>
This commit is contained in:
Erik Faye-Lund
2022-02-03 10:57:16 +01:00
committed by Marge Bot
parent 32c2db1b25
commit 25a37fabb7
9 changed files with 279 additions and 202 deletions
+1 -1
View File
@@ -2327,7 +2327,7 @@ radv_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
const struct wsi_image_create_info *wsi_info =
vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
bool scanout = wsi_info && wsi_info->scanout;
bool prime_blit_src = wsi_info && wsi_info->prime_blit_src;
bool prime_blit_src = wsi_info && wsi_info->buffer_blit_src;
return radv_image_create(device,
&(struct radv_image_create_info){
+1 -1
View File
@@ -95,7 +95,7 @@ radv_init_wsi(struct radv_physical_device *physical_device)
physical_device->wsi_device.supports_modifiers = physical_device->rad_info.chip_class >= GFX9;
physical_device->wsi_device.set_memory_ownership = radv_wsi_set_memory_ownership;
physical_device->wsi_device.get_prime_blit_queue = radv_wsi_get_prime_blit_queue;
physical_device->wsi_device.get_buffer_blit_queue = radv_wsi_get_prime_blit_queue;
physical_device->wsi_device.signal_semaphore_with_memory = true;
physical_device->wsi_device.signal_fence_with_memory = true;
+1 -1
View File
@@ -257,7 +257,7 @@ create_image(struct v3dv_device *device,
/* When using the simulator the WSI common code will see that our
* driver wsi device doesn't match the display device and because of that
* it will not attempt to present directly from the swapchain images,
* instead it will use the prime blit path (use_prime_blit flag in
* instead it will use the prime blit path (use_buffer_blit flag in
* struct wsi_swapchain), where it copies the contents of the swapchain
* images to a linear buffer with appropriate row stride for presentation.
* As a result, on that path, swapchain images do not have any special
+1 -1
View File
@@ -133,7 +133,7 @@ vn_wsi_create_image(struct vn_device *dev,
return result;
img->wsi.is_wsi = true;
img->wsi.is_prime_blit_src = wsi_info->prime_blit_src;
img->wsi.is_prime_blit_src = wsi_info->buffer_blit_src;
img->wsi.tiling_override = create_info->tiling;
if (create_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
+211 -35
View File
@@ -28,6 +28,7 @@
#include "util/xmlconfig.h"
#include "vk_device.h"
#include "vk_fence.h"
#include "vk_format.h"
#include "vk_instance.h"
#include "vk_physical_device.h"
#include "vk_queue.h"
@@ -223,7 +224,7 @@ wsi_swapchain_init(const struct wsi_device *wsi,
VkDevice device,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
bool use_prime_blit)
bool use_buffer_blit)
{
VkResult result;
@@ -234,12 +235,12 @@ wsi_swapchain_init(const struct wsi_device *wsi,
chain->wsi = wsi;
chain->device = device;
chain->alloc = *pAllocator;
chain->use_prime_blit = use_prime_blit;
chain->prime_blit_queue = VK_NULL_HANDLE;
if (use_prime_blit && wsi->get_prime_blit_queue)
chain->prime_blit_queue = wsi->get_prime_blit_queue(device);
chain->use_buffer_blit = use_buffer_blit;
chain->buffer_blit_queue = VK_NULL_HANDLE;
if (use_buffer_blit && wsi->get_buffer_blit_queue)
chain->buffer_blit_queue = wsi->get_buffer_blit_queue(device);
int cmd_pools_count = chain->prime_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
chain->cmd_pools =
vk_zalloc(pAllocator, sizeof(VkCommandPool) * cmd_pools_count, 8,
@@ -250,8 +251,8 @@ wsi_swapchain_init(const struct wsi_device *wsi,
for (uint32_t i = 0; i < cmd_pools_count; i++) {
int queue_family_index = i;
if (chain->prime_blit_queue != VK_NULL_HANDLE) {
VK_FROM_HANDLE(vk_queue, queue, chain->prime_blit_queue);
if (chain->buffer_blit_queue != VK_NULL_HANDLE) {
VK_FROM_HANDLE(vk_queue, queue, chain->buffer_blit_queue);
queue_family_index = queue->queue_family_index;
}
const VkCommandPoolCreateInfo cmd_pool_info = {
@@ -335,14 +336,14 @@ wsi_swapchain_finish(struct wsi_swapchain *chain)
vk_free(&chain->alloc, chain->fences);
}
if (chain->prime_blit_semaphores) {
if (chain->buffer_blit_semaphores) {
for (unsigned i = 0; i < chain->image_count; i++)
chain->wsi->DestroySemaphore(chain->device, chain->prime_blit_semaphores[i], &chain->alloc);
chain->wsi->DestroySemaphore(chain->device, chain->buffer_blit_semaphores[i], &chain->alloc);
vk_free(&chain->alloc, chain->prime_blit_semaphores);
vk_free(&chain->alloc, chain->buffer_blit_semaphores);
}
int cmd_pools_count = chain->prime_blit_queue != VK_NULL_HANDLE ?
int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ?
1 : chain->wsi->queue_family_count;
for (uint32_t i = 0; i < cmd_pools_count; i++) {
chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
@@ -500,18 +501,18 @@ wsi_destroy_image(const struct wsi_swapchain *chain,
{
const struct wsi_device *wsi = chain->wsi;
if (image->prime.blit_cmd_buffers) {
if (image->buffer.blit_cmd_buffers) {
for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
1, &image->prime.blit_cmd_buffers[i]);
1, &image->buffer.blit_cmd_buffers[i]);
}
vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
vk_free(&chain->alloc, image->buffer.blit_cmd_buffers);
}
wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
wsi->DestroyImage(chain->device, image->image, &chain->alloc);
wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
wsi->FreeMemory(chain->device, image->buffer.memory, &chain->alloc);
wsi->DestroyBuffer(chain->device, image->buffer.buffer, &chain->alloc);
}
VKAPI_ATTR VkResult VKAPI_CALL
@@ -707,12 +708,12 @@ wsi_CreateSwapchainKHR(VkDevice _device,
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
if (swapchain->prime_blit_queue != VK_NULL_HANDLE) {
swapchain->prime_blit_semaphores = vk_zalloc(alloc,
sizeof (*swapchain->prime_blit_semaphores) * swapchain->image_count,
sizeof (*swapchain->prime_blit_semaphores),
if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
swapchain->buffer_blit_semaphores = vk_zalloc(alloc,
sizeof (*swapchain->buffer_blit_semaphores) * swapchain->image_count,
sizeof (*swapchain->buffer_blit_semaphores),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!swapchain->prime_blit_semaphores) {
if (!swapchain->buffer_blit_semaphores) {
swapchain->destroy(swapchain, alloc);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
@@ -894,7 +895,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
if (result != VK_SUCCESS)
goto fail_present;
if (swapchain->use_prime_blit && swapchain->prime_blit_queue != VK_NULL_HANDLE) {
if (swapchain->use_buffer_blit && swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
const VkSemaphoreCreateInfo sem_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = NULL,
@@ -902,7 +903,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
};
result = wsi->CreateSemaphore(device, &sem_info,
&swapchain->alloc,
&swapchain->prime_blit_semaphores[image_index]);
&swapchain->buffer_blit_semaphores[image_index]);
if (result != VK_SUCCESS)
goto fail_present;
}
@@ -958,22 +959,22 @@ wsi_common_queue_present(const struct wsi_device *wsi,
}
VkFence fence = swapchain->fences[image_index];
if (swapchain->use_prime_blit) {
if (swapchain->prime_blit_queue == VK_NULL_HANDLE) {
/* If we are using default prime blits, we need to perform the blit now. The
if (swapchain->use_buffer_blit) {
if (swapchain->buffer_blit_queue == VK_NULL_HANDLE) {
/* If we are using default buffer blits, we need to perform the blit now. The
* command buffer is attached to the image.
*/
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers =
&image->prime.blit_cmd_buffers[queue_family_index];
mem_signal.memory = image->prime.memory;
&image->buffer.blit_cmd_buffers[queue_family_index];
mem_signal.memory = image->buffer.memory;
} else {
/* If we are using a blit using the driver's private queue, then do an empty
* submit signalling a semaphore, and then submit the blit.
*/
fence = VK_NULL_HANDLE;
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &swapchain->prime_blit_semaphores[image_index];
submit_info.pSignalSemaphores = &swapchain->buffer_blit_semaphores[image_index];
}
}
@@ -982,22 +983,22 @@ wsi_common_queue_present(const struct wsi_device *wsi,
if (result != VK_SUCCESS)
goto fail_present;
if (swapchain->use_prime_blit && swapchain->prime_blit_queue != VK_NULL_HANDLE) {
if (swapchain->use_buffer_blit && swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
submit_info.commandBufferCount = 1;
if (swapchain->prime_blit_queue != VK_NULL_HANDLE) {
submit_info.pCommandBuffers = &image->prime.blit_cmd_buffers[0];
if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
submit_info.pCommandBuffers = &image->buffer.blit_cmd_buffers[0];
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = submit_info.pSignalSemaphores;
submit_info.signalSemaphoreCount = 0;
submit_info.pSignalSemaphores = NULL;
/* Submit the copy to the private transfer queue */
result = wsi->QueueSubmit(swapchain->prime_blit_queue,
result = wsi->QueueSubmit(swapchain->buffer_blit_queue,
1,
&submit_info,
swapchain->fences[image_index]);
}
mem_signal.memory = image->prime.memory;
mem_signal.memory = image->buffer.memory;
}
if (wsi->sw)
@@ -1130,3 +1131,178 @@ wsi_common_bind_swapchain_image(const struct wsi_device *wsi,
return wsi->BindImageMemory(chain->device, vk_image, image->memory, 0);
}
VkResult
wsi_create_buffer_image_mem(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
struct wsi_image *image,
VkExternalMemoryHandleTypeFlags handle_types,
bool implicit_sync)
{
const struct wsi_device *wsi = chain->wsi;
VkResult result;
uint32_t linear_size = info->linear_stride * info->create.extent.height;
linear_size = ALIGN_POT(linear_size, info->size_align);
const VkExternalMemoryBufferCreateInfo buffer_external_info = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
.pNext = NULL,
.handleTypes = handle_types,
};
const VkBufferCreateInfo buffer_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = &buffer_external_info,
.size = linear_size,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
result = wsi->CreateBuffer(chain->device, &buffer_info,
&chain->alloc, &image->buffer.buffer);
if (result != VK_SUCCESS)
return result;
VkMemoryRequirements reqs;
wsi->GetBufferMemoryRequirements(chain->device, image->buffer.buffer, &reqs);
assert(reqs.size <= linear_size);
const struct wsi_memory_allocate_info memory_wsi_info = {
.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
.pNext = NULL,
.implicit_sync = implicit_sync,
};
const VkExportMemoryAllocateInfo memory_export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
.pNext = &memory_wsi_info,
.handleTypes = handle_types,
};
const VkMemoryDedicatedAllocateInfo buf_mem_dedicated_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = &memory_export_info,
.image = VK_NULL_HANDLE,
.buffer = image->buffer.buffer,
};
const VkMemoryAllocateInfo buf_mem_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &buf_mem_dedicated_info,
.allocationSize = linear_size,
.memoryTypeIndex =
info->select_buffer_memory_type(wsi, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &buf_mem_info,
&chain->alloc, &image->buffer.memory);
if (result != VK_SUCCESS)
return result;
result = wsi->BindBufferMemory(chain->device, image->buffer.buffer,
image->buffer.memory, 0);
if (result != VK_SUCCESS)
return result;
wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = NULL,
.image = image->image,
.buffer = VK_NULL_HANDLE,
};
const VkMemoryAllocateInfo memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &memory_dedicated_info,
.allocationSize = reqs.size,
.memoryTypeIndex =
info->select_image_memory_type(wsi, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &memory_info,
&chain->alloc, &image->memory);
if (result != VK_SUCCESS)
return result;
image->num_planes = 1;
image->sizes[0] = linear_size;
image->row_pitches[0] = info->linear_stride;
image->offsets[0] = 0;
return VK_SUCCESS;
}
VkResult
wsi_finish_create_buffer_image(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
VkResult result;
int cmd_buffer_count =
chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
image->buffer.blit_cmd_buffers =
vk_zalloc(&chain->alloc,
sizeof(VkCommandBuffer) * cmd_buffer_count, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!image->buffer.blit_cmd_buffers)
return VK_ERROR_OUT_OF_HOST_MEMORY;
for (uint32_t i = 0; i < cmd_buffer_count; i++) {
const VkCommandBufferAllocateInfo cmd_buffer_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = NULL,
.commandPool = chain->cmd_pools[i],
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
&image->buffer.blit_cmd_buffers[i]);
if (result != VK_SUCCESS)
return result;
const VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
};
wsi->BeginCommandBuffer(image->buffer.blit_cmd_buffers[i], &begin_info);
struct VkBufferImageCopy buffer_image_copy = {
.bufferOffset = 0,
.bufferRowLength = info->linear_stride /
vk_format_get_blocksize(info->create.format),
.bufferImageHeight = 0,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.imageOffset = { .x = 0, .y = 0, .z = 0 },
.imageExtent = info->create.extent,
};
wsi->CmdCopyImageToBuffer(image->buffer.blit_cmd_buffers[i],
image->image,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
image->buffer.buffer,
1, &buffer_image_copy);
result = wsi->EndCommandBuffer(image->buffer.blit_cmd_buffers[i]);
if (result != VK_SUCCESS)
return result;
}
return VK_SUCCESS;
}
VkResult
wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
struct wsi_image_info *info)
{
VkResult result = wsi_configure_image(chain, pCreateInfo,
0 /* handle_types */, info);
if (result != VK_SUCCESS)
return result;
info->create.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
info->wsi.buffer_blit_src = true;
info->finish_create = wsi_finish_create_buffer_image;
return VK_SUCCESS;
}
+4 -4
View File
@@ -60,8 +60,8 @@ struct wsi_image_create_info {
const void *pNext;
bool scanout;
/* if true, the image is a prime blit source */
bool prime_blit_src;
/* if true, the image is a buffer blit source */
bool buffer_blit_src;
};
struct wsi_memory_allocate_info {
@@ -176,9 +176,9 @@ struct wsi_device {
/*
* A driver can implement this callback to return a special queue to execute
* prime blits.
* buffer blits.
*/
VkQueue (*get_prime_blit_queue)(VkDevice device);
VkQueue (*get_buffer_blit_queue)(VkDevice device);
#define WSI_CB(cb) PFN_vk##cb cb
WSI_CB(AllocateMemory);
+24 -146
View File
@@ -115,6 +115,20 @@ select_memory_type(const struct wsi_device *wsi,
unreachable("No memory type found");
}
static uint32_t
prime_select_buffer_memory_type(const struct wsi_device *wsi,
uint32_t type_bits)
{
return select_memory_type(wsi, false, type_bits);
}
static uint32_t
prime_select_image_memory_type(const struct wsi_device *wsi,
uint32_t type_bits)
{
return select_memory_type(wsi, true, type_bits);
}
static const struct VkDrmFormatModifierPropertiesEXT *
get_modifier_props(const struct wsi_image_info *info, uint64_t modifier)
{
@@ -416,87 +430,17 @@ wsi_create_prime_image_mem(const struct wsi_swapchain *chain,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
VkResult result;
uint32_t linear_size = info->linear_stride * info->create.extent.height;
linear_size = ALIGN_POT(linear_size, 4096);
const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
.pNext = NULL,
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
const VkBufferCreateInfo prime_buffer_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = &prime_buffer_external_info,
.size = linear_size,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
&chain->alloc, &image->prime.buffer);
if (result != VK_SUCCESS)
return result;
VkMemoryRequirements reqs;
wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
assert(reqs.size <= linear_size);
const struct wsi_memory_allocate_info memory_wsi_info = {
.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
.pNext = NULL,
.implicit_sync = true,
};
const VkExportMemoryAllocateInfo prime_memory_export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
.pNext = &memory_wsi_info,
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = &prime_memory_export_info,
.image = VK_NULL_HANDLE,
.buffer = image->prime.buffer,
};
const VkMemoryAllocateInfo prime_memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &prime_memory_dedicated_info,
.allocationSize = linear_size,
.memoryTypeIndex = select_memory_type(wsi, false, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &prime_memory_info,
&chain->alloc, &image->prime.memory);
if (result != VK_SUCCESS)
return result;
result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
image->prime.memory, 0);
if (result != VK_SUCCESS)
return result;
wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = NULL,
.image = image->image,
.buffer = VK_NULL_HANDLE,
};
const VkMemoryAllocateInfo memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &memory_dedicated_info,
.allocationSize = reqs.size,
.memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &memory_info,
&chain->alloc, &image->memory);
VkResult result =
wsi_create_buffer_image_mem(chain, info, image,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
true);
if (result != VK_SUCCESS)
return result;
const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
.pNext = NULL,
.memory = image->prime.memory,
.memory = image->buffer.memory,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
int fd;
@@ -506,98 +450,32 @@ wsi_create_prime_image_mem(const struct wsi_swapchain *chain,
image->drm_modifier = info->prime_use_linear_modifier ?
DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
image->num_planes = 1;
image->sizes[0] = linear_size;
image->row_pitches[0] = info->linear_stride;
image->offsets[0] = 0;
image->fds[0] = fd;
return VK_SUCCESS;
}
static VkResult
wsi_finish_create_prime_image(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
VkResult result;
image->prime.blit_cmd_buffers =
vk_zalloc(&chain->alloc,
sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!image->prime.blit_cmd_buffers)
return VK_ERROR_OUT_OF_HOST_MEMORY;
int cmd_buffer_count = chain->prime_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
for (uint32_t i = 0; i < cmd_buffer_count; i++) {
const VkCommandBufferAllocateInfo cmd_buffer_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = NULL,
.commandPool = chain->cmd_pools[i],
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
&image->prime.blit_cmd_buffers[i]);
if (result != VK_SUCCESS)
return result;
const VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
};
wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
struct VkBufferImageCopy buffer_image_copy = {
.bufferOffset = 0,
.bufferRowLength = info->linear_stride /
vk_format_get_blocksize(info->create.format),
.bufferImageHeight = 0,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.imageOffset = { .x = 0, .y = 0, .z = 0 },
.imageExtent = info->create.extent,
};
wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
image->image,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
image->prime.buffer,
1, &buffer_image_copy);
result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
if (result != VK_SUCCESS)
return result;
}
return VK_SUCCESS;
}
VkResult
wsi_configure_prime_image(UNUSED const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
bool use_modifier,
struct wsi_image_info *info)
{
VkResult result = wsi_configure_image(chain, pCreateInfo,
0 /* handle_types */, info);
VkResult result =
wsi_configure_buffer_image(chain, pCreateInfo, info);
if (result != VK_SUCCESS)
return result;
info->create.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
info->wsi.prime_blit_src = true,
info->prime_use_linear_modifier = use_modifier;
const uint32_t cpp = vk_format_get_blocksize(info->create.format);
info->linear_stride = ALIGN_POT(info->create.extent.width * cpp,
WSI_PRIME_LINEAR_STRIDE_ALIGN);
info->size_align = 4096;
info->create_mem = wsi_create_prime_image_mem;
info->finish_create = wsi_finish_create_prime_image;
info->select_buffer_memory_type = prime_select_buffer_memory_type;
info->select_image_memory_type = prime_select_image_memory_type;
return VK_SUCCESS;
}
+32 -9
View File
@@ -44,8 +44,14 @@ struct wsi_image_info {
uint32_t modifier_prop_count;
struct VkDrmFormatModifierPropertiesEXT *modifier_props;
/* For prime blit images, the linear stride in bytes */
/* For buffer blit images, the linear stride in bytes */
uint32_t linear_stride;
uint32_t size_align;
uint32_t (*select_image_memory_type)(const struct wsi_device *wsi,
uint32_t type_bits);
uint32_t (*select_buffer_memory_type)(const struct wsi_device *wsi,
uint32_t type_bits);
uint8_t *(*alloc_shm)(struct wsi_image *image, unsigned size);
@@ -66,7 +72,7 @@ struct wsi_image {
VkBuffer buffer;
VkDeviceMemory memory;
VkCommandBuffer *blit_cmd_buffers;
} prime;
} buffer;
uint64_t drm_modifier;
int num_planes;
@@ -84,20 +90,20 @@ struct wsi_swapchain {
VkDevice device;
VkAllocationCallbacks alloc;
VkFence* fences;
VkSemaphore* prime_blit_semaphores;
VkSemaphore* buffer_blit_semaphores;
VkPresentModeKHR present_mode;
struct wsi_image_info image_info;
uint32_t image_count;
bool use_prime_blit;
bool use_buffer_blit;
/* If the driver wants to use a special queue to execute the prime blit,
* it'll implement the wsi_device::get_prime_blit_queue callback.
/* If the driver wants to use a special queue to execute the buffer blit,
* it'll implement the wsi_device::get_buffer_blit_queue callback.
* The created queue will be stored here and will be used to execute the
* prime blit instead of using the present queue.
* buffer blit instead of using the present queue.
*/
VkQueue prime_blit_queue;
VkQueue buffer_blit_queue;
/* Command pools, one per queue family */
VkCommandPool *cmd_pools;
@@ -123,7 +129,7 @@ wsi_swapchain_init(const struct wsi_device *wsi,
VkDevice device,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
bool use_prime_blit);
bool use_buffer_blit);
enum VkPresentModeKHR
wsi_swapchain_get_present_mode(struct wsi_device *wsi,
@@ -147,6 +153,23 @@ wsi_configure_prime_image(UNUSED const struct wsi_swapchain *chain,
bool use_modifier,
struct wsi_image_info *info);
VkResult
wsi_create_buffer_image_mem(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
struct wsi_image *image,
VkExternalMemoryHandleTypeFlags handle_types,
bool implicit_sync);
VkResult
wsi_finish_create_buffer_image(const struct wsi_swapchain *chain,
const struct wsi_image_info *info,
struct wsi_image *image);
VkResult
wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
struct wsi_image_info *info);
VkResult
wsi_configure_image(const struct wsi_swapchain *chain,
const VkSwapchainCreateInfoKHR *pCreateInfo,
+4 -4
View File
@@ -1858,13 +1858,13 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
/* When our local device is not compatible with the DRI3 device provided by
* the X server we assume this is a PRIME system.
*/
bool use_prime_blit = false;
bool use_buffer_blit = false;
if (!wsi_device->sw)
if (!wsi_x11_check_dri3_compatible(wsi_device, conn))
use_prime_blit = true;
use_buffer_blit = true;
result = wsi_swapchain_init(wsi_device, &chain->base, device,
pCreateInfo, pAllocator, use_prime_blit);
pCreateInfo, pAllocator, use_buffer_blit);
if (result != VK_SUCCESS)
goto fail_alloc;
@@ -1957,7 +1957,7 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
modifiers, num_modifiers, &num_tranches,
pAllocator);
if (chain->base.use_prime_blit) {
if (chain->base.use_buffer_blit) {
bool use_modifier = num_tranches > 0;
result = wsi_configure_prime_image(&chain->base, pCreateInfo,
use_modifier,