dzn: Use DXGI swapchains

Makes things so much faster than doing CPU copies using StretchBlt().

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16200>
This commit is contained in:
Boris Brezillon
2022-04-27 19:34:57 +02:00
committed by Marge Bot
parent 2f462105fa
commit 5f1b8b3e6c
5 changed files with 121 additions and 19 deletions

View File

@@ -1088,20 +1088,22 @@ dzn_CmdPipelineBarrier2(VkCommandBuffer commandBuffer,
const VkImageSubresourceRange *range = &ibarrier->subresourceRange;
VK_FROM_HANDLE(dzn_image, image, ibarrier->image);
/* We use placed resource's simple model, in which only one resource
* pointing to a given heap is active at a given time. To make the
* resource active we need to add an aliasing barrier.
*/
D3D12_RESOURCE_BARRIER aliasing_barrier = {
.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Aliasing = {
.pResourceBefore = NULL,
.pResourceAfter = image->res,
},
};
if (image->mem->swapchain_res != image->res) {
/* We use placed resource's simple model, in which only one resource
* pointing to a given heap is active at a given time. To make the
* resource active we need to add an aliasing barrier.
*/
D3D12_RESOURCE_BARRIER aliasing_barrier = {
.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Aliasing = {
.pResourceBefore = NULL,
.pResourceAfter = image->res,
},
};
ID3D12GraphicsCommandList1_ResourceBarrier(cmdbuf->cmdlist, 1, &aliasing_barrier);
ID3D12GraphicsCommandList1_ResourceBarrier(cmdbuf->cmdlist, 1, &aliasing_barrier);
}
dzn_cmd_buffer_queue_image_range_layout_transition(cmdbuf, image, range,
ibarrier->oldLayout,

View File

@@ -279,6 +279,9 @@ dzn_instance_create(const VkInstanceCreateInfo *pCreateInfo,
vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
&dzn_instance_entrypoints,
true);
vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
&wsi_instance_entrypoints,
false);
VkResult result =
vk_instance_init(&instance->vk, &instance_extensions,
@@ -2143,12 +2146,19 @@ dzn_device_create(struct dzn_physical_device *pdev,
{
struct dzn_instance *instance = container_of(pdev->vk.instance, struct dzn_instance, vk);
uint32_t graphics_queue_count = 0;
uint32_t queue_count = 0;
for (uint32_t qf = 0; qf < pCreateInfo->queueCreateInfoCount; qf++) {
const VkDeviceQueueCreateInfo *qinfo = &pCreateInfo->pQueueCreateInfos[qf];
queue_count += qinfo->queueCount;
if (pdev->queue_families[qinfo->queueFamilyIndex].props.queueFlags & VK_QUEUE_GRAPHICS_BIT)
graphics_queue_count += qinfo->queueCount;
}
/* Add a swapchain queue if there's no or too many graphics queues */
if (graphics_queue_count != 1)
queue_count++;
VK_MULTIALLOC(ma);
VK_MULTIALLOC_DECL(&ma, struct dzn_device, device, 1);
VK_MULTIALLOC_DECL(&ma, struct dzn_queue, queues, queue_count);
@@ -2257,9 +2267,35 @@ dzn_device_create(struct dzn_physical_device *pdev,
dzn_device_destroy(device, pAllocator);
return result;
}
if (graphics_queue_count == 1 &&
pdev->queue_families[qinfo->queueFamilyIndex].props.queueFlags & VK_QUEUE_GRAPHICS_BIT)
device->swapchain_queue = &queues[qindex - 1];
}
}
if (!device->swapchain_queue) {
const float swapchain_queue_priority = 0.0f;
VkDeviceQueueCreateInfo swapchain_queue_info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.flags = 0,
.queueCount = 1,
.pQueuePriorities = &swapchain_queue_priority,
};
for (uint32_t qf = 0; qf < pdev->queue_family_count; qf++) {
if (pdev->queue_families[qf].props.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
swapchain_queue_info.queueFamilyIndex = qf;
break;
}
}
result = dzn_queue_init(&queues[qindex], device, &swapchain_queue_info, 0);
if (result != VK_SUCCESS) {
dzn_device_destroy(device, pAllocator);
return result;
}
device->swapchain_queue = &queues[qindex++];
device->need_swapchain_blits = true;
}
assert(queue_count == qindex);
*out = dzn_device_to_handle(device);
return VK_SUCCESS;
@@ -2372,6 +2408,9 @@ dzn_device_memory_destroy(struct dzn_device_memory *mem,
if (mem->heap)
ID3D12Heap_Release(mem->heap);
if (mem->swapchain_res)
ID3D12Resource_Release(mem->swapchain_res);
vk_object_base_finish(&mem->base);
vk_free2(&device->vk.alloc, pAllocator, mem);
}

View File

@@ -817,9 +817,12 @@ dzn_BindImageMemory2(VkDevice dev,
image->mem = mem;
image->mem_offset = bind_info->memoryOffset;
HRESULT hres;
HRESULT hres = S_OK;
if (device->dev10 && image->castable_format_count > 0) {
if (mem->swapchain_res) {
image->res = mem->swapchain_res;
ID3D12Resource_AddRef(image->res);
} else if (device->dev10 && image->castable_format_count > 0) {
D3D12_RESOURCE_DESC1 desc = {
.Dimension = image->desc.Dimension,
.Alignment = image->desc.Alignment,

View File

@@ -271,6 +271,12 @@ struct dzn_device {
#define DZN_QUERY_REFS_RES_SIZE (DZN_QUERY_REFS_ALL_ZEROS_OFFSET + DZN_QUERY_REFS_SECTION_SIZE)
ID3D12Resource *refs;
} queries;
/* Will be the app's graphics queue if there's exactly one, otherwise this will be
* a dedicated graphics queue to host swapchain blits.
*/
bool need_swapchain_blits;
struct dzn_queue *swapchain_queue;
};
void dzn_meta_finish(struct dzn_device *device);
@@ -290,6 +296,11 @@ struct dzn_device_memory {
struct list_head link;
/* Swapchain image resource, NULL if the memory is not backed by
* a DXGI swapchain.
*/
ID3D12Resource *swapchain_res;
ID3D12Heap *heap;
VkDeviceSize size;

View File

@@ -31,6 +31,50 @@ dzn_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
return vk_instance_get_proc_addr_unchecked(pdevice->vk.instance, pName);
}
static void *
dzn_wsi_get_d3d12_command_queue(VkDevice dev)
{
VK_FROM_HANDLE(dzn_device, device, dev);
return device->swapchain_queue->cmdqueue;
}
static VkQueue
dzn_wsi_get_blit_queue(VkDevice dev)
{
VK_FROM_HANDLE(dzn_device, device, dev);
return dzn_queue_to_handle(device->swapchain_queue);
}
static bool
dzn_wsi_needs_blits(VkDevice dev)
{
VK_FROM_HANDLE(dzn_device, device, dev);
return device->need_swapchain_blits;
}
static VkResult
dzn_wsi_create_image_memory(VkDevice dev, void *resource,
const VkAllocationCallbacks *alloc,
VkDeviceMemory *out)
{
VK_FROM_HANDLE(dzn_device, device, dev);
struct dzn_device_memory *mem =
vk_zalloc2(&device->vk.alloc, alloc, sizeof(*mem), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!mem)
return VK_ERROR_OUT_OF_HOST_MEMORY;
vk_object_base_init(&device->vk, &mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY);
mem->swapchain_res = resource;
ID3D12Resource_AddRef(mem->swapchain_res);
*out = dzn_device_memory_to_handle(mem);
return VK_SUCCESS;
}
void
dzn_wsi_finish(struct dzn_physical_device *physical_device)
{
@@ -43,18 +87,21 @@ dzn_wsi_init(struct dzn_physical_device *physical_device)
{
VkResult result;
/* TODO: implement a proper, non-sw winsys for D3D12 */
bool sw_device = true;
result = wsi_device_init(&physical_device->wsi_device,
dzn_physical_device_to_handle(physical_device),
dzn_wsi_proc_addr,
&physical_device->vk.instance->alloc,
-1, NULL, sw_device);
-1, NULL, false);
if (result != VK_SUCCESS)
return result;
physical_device->wsi_device.win32.get_d3d12_command_queue =
dzn_wsi_get_d3d12_command_queue;
physical_device->wsi_device.win32.requires_blits = dzn_wsi_needs_blits;
physical_device->wsi_device.get_blit_queue = dzn_wsi_get_blit_queue;
physical_device->wsi_device.win32.create_image_memory =
dzn_wsi_create_image_memory;
physical_device->wsi_device.supports_modifiers = false;
physical_device->vk.wsi_device = &physical_device->wsi_device;