vkd3d: Implement swap chain blits using dynamic rendering.

Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
Philip Rebohle 2021-11-11 17:53:54 +01:00 committed by Hans-Kristian Arntzen
parent 024ef02f9b
commit 3783eaf4f7
3 changed files with 60 additions and 143 deletions

View File

@ -591,89 +591,14 @@ void vkd3d_copy_image_ops_cleanup(struct vkd3d_copy_image_ops *meta_copy_image_o
vkd3d_free(meta_copy_image_ops->pipelines);
}
static VkResult vkd3d_meta_create_swapchain_render_pass(struct d3d12_device *device,
const struct vkd3d_swapchain_pipeline_key *key, VkRenderPass *render_pass)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkRenderPassCreateInfo2KHR render_pass_info;
VkAttachmentDescription2KHR attachment_desc;
VkAttachmentReference2KHR attachment_ref;
VkSubpassDescription2KHR subpass_desc;
VkSubpassDependency2KHR subpass_dep;
attachment_desc.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
attachment_desc.pNext = NULL;
attachment_desc.loadOp = key->load_op;
attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment_desc.format = key->format;
attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment_desc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
attachment_desc.flags = 0;
attachment_ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
attachment_ref.pNext = NULL;
attachment_ref.attachment = 0;
attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_ref.aspectMask = 0; /* input attachment aspect mask */
subpass_desc.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
subpass_desc.pNext = NULL;
subpass_desc.flags = 0;
subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_desc.viewMask = 0;
subpass_desc.inputAttachmentCount = 0;
subpass_desc.pInputAttachments = NULL;
subpass_desc.colorAttachmentCount = 1;
subpass_desc.pColorAttachments = &attachment_ref;
subpass_desc.pResolveAttachments = NULL;
subpass_desc.pDepthStencilAttachment = NULL;
subpass_desc.preserveAttachmentCount = 0;
subpass_desc.pPreserveAttachments = NULL;
subpass_dep.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR;
subpass_dep.pNext = NULL;
subpass_dep.srcSubpass = VK_SUBPASS_EXTERNAL;
subpass_dep.dstSubpass = 0;
subpass_dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dep.srcAccessMask = 0;
subpass_dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpass_dep.dependencyFlags = 0;
subpass_dep.viewOffset = 0;
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
render_pass_info.pNext = NULL;
render_pass_info.flags = 0;
render_pass_info.attachmentCount = 1;
render_pass_info.pAttachments = &attachment_desc;
render_pass_info.subpassCount = 1;
render_pass_info.pSubpasses = &subpass_desc;
render_pass_info.dependencyCount = 1;
render_pass_info.pDependencies = &subpass_dep;
render_pass_info.correlatedViewMaskCount = 0;
render_pass_info.pCorrelatedViewMasks = NULL;
return VK_CALL(vkCreateRenderPass2KHR(device->vk_device, &render_pass_info, NULL, render_pass));
}
static HRESULT vkd3d_meta_create_swapchain_pipeline(struct vkd3d_meta_ops *meta_ops,
const struct vkd3d_swapchain_pipeline_key *key, struct vkd3d_swapchain_pipeline *pipeline)
{
const struct vkd3d_vk_device_procs *vk_procs = &meta_ops->device->vk_procs;
struct vkd3d_swapchain_ops *meta_swapchain_ops = &meta_ops->swapchain;
VkPipelineColorBlendAttachmentState blend_att;
VkPipelineColorBlendStateCreateInfo cb_state;
VkResult vr;
if ((vr = vkd3d_meta_create_swapchain_render_pass(meta_ops->device, key, &pipeline->vk_render_pass)))
{
ERR("Failed to create render pass, vr %d.\n", vr);
return hresult_from_vk_result(vr);
}
memset(&cb_state, 0, sizeof(cb_state));
memset(&blend_att, 0, sizeof(blend_att));
cb_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
@ -690,10 +615,7 @@ static HRESULT vkd3d_meta_create_swapchain_pipeline(struct vkd3d_meta_ops *meta_
meta_swapchain_ops->vk_vs_module, meta_swapchain_ops->vk_fs_module, 1,
NULL, &cb_state,
NULL, &pipeline->vk_pipeline)) < 0)
{
VK_CALL(vkDestroyRenderPass(meta_ops->device->vk_device, pipeline->vk_render_pass, NULL));
return hresult_from_vk_result(vr);
}
pipeline->key = *key;
return S_OK;
@ -1023,7 +945,6 @@ void vkd3d_swapchain_ops_cleanup(struct vkd3d_swapchain_ops *meta_swapchain_ops,
{
struct vkd3d_swapchain_pipeline *pipeline = &meta_swapchain_ops->pipelines[i];
VK_CALL(vkDestroyRenderPass(device->vk_device, pipeline->vk_render_pass, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline->vk_pipeline, NULL));
}
@ -1064,7 +985,6 @@ HRESULT vkd3d_meta_get_swapchain_pipeline(struct vkd3d_meta_ops *meta_ops,
if (!memcmp(key, &pipeline->key, sizeof(*key)))
{
info->vk_render_pass = pipeline->vk_render_pass;
info->vk_pipeline = pipeline->vk_pipeline;
pthread_mutex_unlock(&meta_swapchain_ops->mutex);
return S_OK;
@ -1086,7 +1006,6 @@ HRESULT vkd3d_meta_get_swapchain_pipeline(struct vkd3d_meta_ops *meta_ops,
return hr;
}
info->vk_render_pass = pipeline->vk_render_pass;
info->vk_pipeline = pipeline->vk_pipeline;
pthread_mutex_unlock(&meta_swapchain_ops->mutex);

View File

@ -180,7 +180,6 @@ struct d3d12_swapchain
VkImage vk_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkImageView vk_swapchain_image_views[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkFramebuffer vk_framebuffers[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkCommandBuffer vk_cmd_buffers[DXGI_MAX_SWAP_CHAIN_BUFFERS];
bool vk_acquire_semaphores_signaled[DXGI_MAX_SWAP_CHAIN_BUFFERS];
VkSemaphore vk_acquire_semaphores[DXGI_MAX_SWAP_CHAIN_BUFFERS];
@ -817,8 +816,6 @@ static HRESULT d3d12_swapchain_get_user_graphics_pipeline(struct d3d12_swapchain
HRESULT hr;
key.bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
key.load_op = swapchain->desc.Scaling == DXGI_SCALING_NONE ?
VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
key.filter = swapchain->desc.Scaling == DXGI_SCALING_NONE ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
key.format = format;
@ -987,16 +984,13 @@ static VkResult d3d12_swapchain_record_swapchain_blit(struct d3d12_swapchain *sw
VkCommandBuffer vk_cmd_buffer, unsigned int dst_index, unsigned int src_index)
{
const struct vkd3d_vk_device_procs *vk_procs = d3d12_swapchain_procs(swapchain);
VkSubpassBeginInfoKHR subpass_begin_info;
VkSubpassEndInfoKHR subpass_end_info;
VkRenderingAttachmentInfoKHR attachment_info;
VkCommandBufferBeginInfo begin_info;
VkRenderPassBeginInfo rp_info;
VkClearValue clear_value;
VkImageMemoryBarrier image_barrier;
VkRenderingInfoKHR rendering_info;
VkViewport viewport;
VkResult vr;
memset(&clear_value, 0, sizeof(clear_value));
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.pNext = NULL;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
@ -1008,39 +1002,28 @@ static VkResult d3d12_swapchain_record_swapchain_blit(struct d3d12_swapchain *sw
return vr;
}
rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rp_info.pNext = NULL;
rp_info.renderPass = swapchain->pipeline.vk_render_pass;
rp_info.framebuffer = swapchain->vk_framebuffers[dst_index];
rp_info.renderArea.offset.x = 0;
rp_info.renderArea.offset.y = 0;
rp_info.renderArea.extent.width = swapchain->vk_swapchain_width;
rp_info.renderArea.extent.height = swapchain->vk_swapchain_height;
subpass_begin_info.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR;
subpass_begin_info.pNext = NULL;
subpass_begin_info.contents = VK_SUBPASS_CONTENTS_INLINE;
subpass_end_info.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR;
subpass_end_info.pNext = NULL;
memset(&attachment_info, 0, sizeof(attachment_info));
attachment_info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;
attachment_info.imageView = swapchain->vk_swapchain_image_views[dst_index];
attachment_info.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_info.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_info.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (swapchain->desc.Scaling == DXGI_SCALING_NONE)
{
rp_info.clearValueCount = 1;
rp_info.pClearValues = &clear_value;
}
else
{
rp_info.clearValueCount = 0;
rp_info.pClearValues = NULL;
}
attachment_info.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
memset(&rendering_info, 0, sizeof(rendering_info));
rendering_info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR;
rendering_info.renderArea.extent.width = swapchain->vk_swapchain_width;
rendering_info.renderArea.extent.height = swapchain->vk_swapchain_height;
rendering_info.layerCount = 1;
rendering_info.colorAttachmentCount = 1;
rendering_info.pColorAttachments = &attachment_info;
viewport.x = viewport.y = 0.0f;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VK_CALL(vkCmdBeginRenderPass2KHR(vk_cmd_buffer, &rp_info, &subpass_begin_info));
if (swapchain->desc.Scaling == DXGI_SCALING_NONE)
{
viewport.width = (float)swapchain->desc.Width;
@ -1052,15 +1035,48 @@ static VkResult d3d12_swapchain_record_swapchain_blit(struct d3d12_swapchain *sw
viewport.height = swapchain->vk_swapchain_height;
}
VK_CALL(vkCmdSetViewport(vk_cmd_buffer, 0, 1, &viewport));
VK_CALL(vkCmdSetScissor(vk_cmd_buffer, 0, 1, &rp_info.renderArea));
image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_barrier.pNext = NULL;
image_barrier.srcAccessMask = 0;
image_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.image = swapchain->vk_swapchain_images[dst_index];
image_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
image_barrier.subresourceRange.baseMipLevel = 0;
image_barrier.subresourceRange.levelCount = 1;
image_barrier.subresourceRange.baseArrayLayer = 0;
image_barrier.subresourceRange.layerCount = 1;
if (attachment_info.loadOp != VK_ATTACHMENT_LOAD_OP_DONT_CARE)
image_barrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
VK_CALL(vkCmdPipelineBarrier(vk_cmd_buffer,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, 0, NULL, 0, NULL, 1, &image_barrier));
VK_CALL(vkCmdBeginRenderingKHR(vk_cmd_buffer, &rendering_info));
VK_CALL(vkCmdSetViewport(vk_cmd_buffer, 0, 1, &viewport));
VK_CALL(vkCmdSetScissor(vk_cmd_buffer, 0, 1, &rendering_info.renderArea));
VK_CALL(vkCmdBindPipeline(vk_cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, swapchain->pipeline.vk_pipeline));
VK_CALL(vkCmdBindDescriptorSets(vk_cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
swapchain->pipeline.vk_pipeline_layout, 0, 1, &swapchain->descriptors.sets[src_index],
0, NULL));
VK_CALL(vkCmdDraw(vk_cmd_buffer, 3, 1, 0, 0));
VK_CALL(vkCmdEndRenderPass2KHR(vk_cmd_buffer, &subpass_end_info));
VK_CALL(vkCmdEndRenderingKHR(vk_cmd_buffer));
image_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
image_barrier.dstAccessMask = 0;
image_barrier.oldLayout = image_barrier.newLayout;
image_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VK_CALL(vkCmdPipelineBarrier(vk_cmd_buffer,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, 0, NULL, 0, NULL, 1, &image_barrier));
if ((vr = VK_CALL(vkEndCommandBuffer(vk_cmd_buffer))) < 0)
WARN("Failed to end command buffer, vr %d.\n", vr);
@ -1068,7 +1084,7 @@ static VkResult d3d12_swapchain_record_swapchain_blit(struct d3d12_swapchain *sw
return vr;
}
static void d3d12_swapchain_destroy_framebuffers(struct d3d12_swapchain *swapchain)
static void d3d12_swapchain_destroy_views(struct d3d12_swapchain *swapchain)
{
const struct vkd3d_vk_device_procs *vk_procs = d3d12_swapchain_procs(swapchain);
VkDevice vk_device = d3d12_swapchain_device(swapchain)->vk_device;
@ -1077,30 +1093,18 @@ static void d3d12_swapchain_destroy_framebuffers(struct d3d12_swapchain *swapcha
for (i = 0; i < swapchain->buffer_count; i++)
{
VK_CALL(vkDestroyImageView(vk_device, swapchain->vk_swapchain_image_views[i], NULL));
VK_CALL(vkDestroyFramebuffer(vk_device, swapchain->vk_framebuffers[i], NULL));
swapchain->vk_swapchain_image_views[i] = VK_NULL_HANDLE;
swapchain->vk_framebuffers[i] = VK_NULL_HANDLE;
}
}
static HRESULT d3d12_swapchain_create_framebuffers(struct d3d12_swapchain *swapchain, VkFormat format)
static HRESULT d3d12_swapchain_create_views(struct d3d12_swapchain *swapchain, VkFormat format)
{
const struct vkd3d_vk_device_procs *vk_procs = d3d12_swapchain_procs(swapchain);
VkDevice vk_device = d3d12_swapchain_device(swapchain)->vk_device;
VkImageViewCreateInfo image_view_info;
VkFramebufferCreateInfo fb_info;
unsigned int i;
VkResult vr;
fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fb_info.pNext = NULL;
fb_info.flags = 0;
fb_info.renderPass = swapchain->pipeline.vk_render_pass;
fb_info.width = swapchain->vk_swapchain_width;
fb_info.height = swapchain->vk_swapchain_height;
fb_info.layers = 1;
fb_info.attachmentCount = 1;
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_info.pNext = NULL;
image_view_info.flags = 0;
@ -1121,9 +1125,6 @@ static HRESULT d3d12_swapchain_create_framebuffers(struct d3d12_swapchain *swapc
image_view_info.image = swapchain->vk_swapchain_images[i];
if ((vr = VK_CALL(vkCreateImageView(vk_device, &image_view_info, NULL, &swapchain->vk_swapchain_image_views[i]))))
return hresult_from_vk_result(vr);
fb_info.pAttachments = &swapchain->vk_swapchain_image_views[i];
if ((vr = VK_CALL(vkCreateFramebuffer(vk_device, &fb_info, NULL, &swapchain->vk_framebuffers[i]))))
return hresult_from_vk_result(vr);
}
return S_OK;
@ -1225,7 +1226,7 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
VkResult vr;
HRESULT hr;
d3d12_swapchain_destroy_framebuffers(swapchain);
d3d12_swapchain_destroy_views(swapchain);
if ((vr = VK_CALL(vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL))) < 0)
{
@ -1255,7 +1256,7 @@ static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
if (queue_desc.Type == D3D12_COMMAND_LIST_TYPE_DIRECT)
{
if (FAILED(hr = d3d12_swapchain_create_framebuffers(swapchain, vk_swapchain_format)))
if (FAILED(hr = d3d12_swapchain_create_views(swapchain, vk_swapchain_format)))
return hr;
}
@ -1575,7 +1576,7 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s
return hr;
d3d12_swapchain_destroy_buffers(swapchain, FALSE);
d3d12_swapchain_destroy_framebuffers(swapchain);
d3d12_swapchain_destroy_views(swapchain);
swapchain->buffer_count = 0;
return S_OK;
}
@ -1637,7 +1638,7 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
const struct vkd3d_vk_device_procs *vk_procs = d3d12_swapchain_procs(swapchain);
d3d12_swapchain_destroy_buffers(swapchain, TRUE);
d3d12_swapchain_destroy_framebuffers(swapchain);
d3d12_swapchain_destroy_views(swapchain);
if (swapchain->frame_latency_event)
CloseHandle(swapchain->frame_latency_event);

View File

@ -2600,7 +2600,6 @@ void vkd3d_copy_image_ops_cleanup(struct vkd3d_copy_image_ops *meta_copy_image_o
struct vkd3d_swapchain_pipeline_key
{
VkPipelineBindPoint bind_point;
VkAttachmentLoadOp load_op;
VkFormat format;
VkFilter filter;
};
@ -2609,13 +2608,11 @@ struct vkd3d_swapchain_info
{
VkDescriptorSetLayout vk_set_layout;
VkPipelineLayout vk_pipeline_layout;
VkRenderPass vk_render_pass;
VkPipeline vk_pipeline;
};
struct vkd3d_swapchain_pipeline
{
VkRenderPass vk_render_pass;
VkPipeline vk_pipeline;
struct vkd3d_swapchain_pipeline_key key;
};