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:
committed by
Marge Bot
parent
32c2db1b25
commit
25a37fabb7
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user