1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-21 13:54:18 +01:00

[dxvk] Make external subpass dependencies part of DxvkRenderPassOps

This will allow us to use finer-grained synchronization around certain
meta operations involving render targets, such as clears.
This commit is contained in:
Philip Rebohle 2019-01-22 15:44:19 +01:00
parent a79409ad02
commit 5b90b6a7ce
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 98 additions and 40 deletions

View File

@ -549,12 +549,22 @@ namespace dxvk {
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) { if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) {
attachments.color[0].view = imageView; attachments.color[0].view = imageView;
attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
ops.barrier.srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
ops.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
ops.colorOps[0] = colorOp; ops.colorOps[0] = colorOp;
} else { } else {
attachments.depth.view = imageView; attachments.depth.view = imageView;
attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
ops.barrier.srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
ops.barrier.srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
ops.depthOps = depthOp; ops.depthOps = depthOp;
} }
ops.barrier.dstStages = imageView->imageInfo().stages;
ops.barrier.dstAccess = imageView->imageInfo().access;
this->renderPassBindFramebuffer( this->renderPassBindFramebuffer(
m_device->createFramebuffer(attachments), m_device->createFramebuffer(attachments),
@ -1762,6 +1772,10 @@ namespace dxvk {
attachments.color[0].view = imageView; attachments.color[0].view = imageView;
attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
ops.barrier.srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
ops.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
ops.colorOps[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; ops.colorOps[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
ops.colorOps[0].loadLayout = imageView->imageInfo().layout; ops.colorOps[0].loadLayout = imageView->imageInfo().layout;
ops.colorOps[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; ops.colorOps[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -1770,6 +1784,11 @@ namespace dxvk {
attachments.depth.view = imageView; attachments.depth.view = imageView;
attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
ops.barrier.srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
ops.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
ops.depthOps.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD; ops.depthOps.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD;
ops.depthOps.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD; ops.depthOps.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD;
ops.depthOps.loadLayout = imageView->imageInfo().layout; ops.depthOps.loadLayout = imageView->imageInfo().layout;
@ -1778,6 +1797,9 @@ namespace dxvk {
ops.depthOps.storeLayout = imageView->imageInfo().layout; ops.depthOps.storeLayout = imageView->imageInfo().layout;
} }
ops.barrier.dstStages = imageView->imageInfo().stages;
ops.barrier.dstAccess = imageView->imageInfo().access;
// We cannot leverage render pass clears // We cannot leverage render pass clears
// because we clear only part of the view // because we clear only part of the view
this->renderPassBindFramebuffer( this->renderPassBindFramebuffer(
@ -2435,6 +2457,25 @@ namespace dxvk {
void DxvkContext::resetRenderPassOps( void DxvkContext::resetRenderPassOps(
const DxvkRenderTargets& renderTargets, const DxvkRenderTargets& renderTargets,
DxvkRenderPassOps& renderPassOps) { DxvkRenderPassOps& renderPassOps) {
renderPassOps.barrier.srcStages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
renderPassOps.barrier.srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
| VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
| VK_ACCESS_INDIRECT_COMMAND_READ_BIT
| VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
| VK_ACCESS_INDEX_READ_BIT
| VK_ACCESS_UNIFORM_READ_BIT
| VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
renderPassOps.barrier.dstStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
renderPassOps.barrier.dstAccess = renderPassOps.barrier.srcAccess
| VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
renderPassOps.depthOps = renderTargets.depth.view != nullptr renderPassOps.depthOps = renderTargets.depth.view != nullptr
? DxvkDepthAttachmentOps { ? DxvkDepthAttachmentOps {
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD,

View File

@ -121,44 +121,39 @@ namespace dxvk {
if (m_format.depth.format == VK_FORMAT_UNDEFINED) if (m_format.depth.format == VK_FORMAT_UNDEFINED)
subpass.pDepthStencilAttachment = nullptr; subpass.pDepthStencilAttachment = nullptr;
const std::array<VkSubpassDependency, 4> subpassDeps = {{ std::array<VkSubpassDependency, 3> subpassDeps;
{ VK_SUBPASS_EXTERNAL, 0, uint32_t subpassDepCount = 0;
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, if (ops.barrier.srcStages & (
0, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) {
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | subpassDeps[subpassDepCount++] = { 0, 0,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 0 },
{ 0, 0,
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, /* XXX */ VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, /* XXX */
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 }, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 };
{ 0, 0, }
if (ops.barrier.srcStages & (
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT |
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) {
subpassDeps[subpassDepCount++] = { 0, 0,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT, 0 }, VK_ACCESS_SHADER_READ_BIT, 0 };
{ 0, VK_SUBPASS_EXTERNAL, }
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, if (ops.barrier.srcStages && ops.barrier.dstStages) {
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | subpassDeps[subpassDepCount++] = {
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 0, VK_SUBPASS_EXTERNAL,
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT | ops.barrier.srcStages,
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT | ops.barrier.dstStages,
VK_ACCESS_SHADER_WRITE_BIT, ops.barrier.srcAccess,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | ops.barrier.dstAccess, 0 };
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | }
VK_ACCESS_HOST_READ_BIT |
VK_ACCESS_INDEX_READ_BIT |
VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_UNIFORM_READ_BIT |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 },
}};
VkRenderPassCreateInfo info; VkRenderPassCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
@ -168,8 +163,8 @@ namespace dxvk {
info.pAttachments = attachments.data(); info.pAttachments = attachments.data();
info.subpassCount = 1; info.subpassCount = 1;
info.pSubpasses = &subpass; info.pSubpasses = &subpass;
info.dependencyCount = subpassDeps.size(); info.dependencyCount = subpassDepCount;
info.pDependencies = subpassDeps.data(); info.pDependencies = subpassDepCount ? subpassDeps.data() : nullptr;
VkRenderPass renderPass = VK_NULL_HANDLE; VkRenderPass renderPass = VK_NULL_HANDLE;
@ -185,12 +180,19 @@ namespace dxvk {
bool DxvkRenderPass::compareOps( bool DxvkRenderPass::compareOps(
const DxvkRenderPassOps& a, const DxvkRenderPassOps& a,
const DxvkRenderPassOps& b) { const DxvkRenderPassOps& b) {
bool eq = a.depthOps.loadOpD == b.depthOps.loadOpD bool eq = a.barrier.srcStages == b.barrier.srcStages
&& a.depthOps.loadOpS == b.depthOps.loadOpS && a.barrier.srcAccess == b.barrier.srcAccess
&& a.depthOps.loadLayout == b.depthOps.loadLayout && a.barrier.dstStages == b.barrier.dstStages
&& a.depthOps.storeOpD == b.depthOps.storeOpD && a.barrier.dstAccess == b.barrier.dstAccess;
&& a.depthOps.storeOpS == b.depthOps.storeOpS
&& a.depthOps.storeLayout == b.depthOps.storeLayout; if (eq) {
eq &= a.depthOps.loadOpD == b.depthOps.loadOpD
&& a.depthOps.loadOpS == b.depthOps.loadOpS
&& a.depthOps.loadLayout == b.depthOps.loadLayout
&& a.depthOps.storeOpD == b.depthOps.storeOpD
&& a.depthOps.storeOpS == b.depthOps.storeOpS
&& a.depthOps.storeLayout == b.depthOps.storeLayout;
}
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
eq &= a.colorOps[i].loadOp == b.colorOps[i].loadOp eq &= a.colorOps[i].loadOp == b.colorOps[i].loadOp

View File

@ -66,6 +66,20 @@ namespace dxvk {
}; };
/**
* \brief Render pass barrier
*
* External subpass dependency that is to be
* executed after a render pass has completed.
*/
struct DxvkRenderPassBarrier {
VkPipelineStageFlags srcStages = 0;
VkAccessFlags srcAccess = 0;
VkPipelineStageFlags dstStages = 0;
VkAccessFlags dstAccess = 0;
};
/** /**
* \brief Render pass transitions * \brief Render pass transitions
* *
@ -74,6 +88,7 @@ namespace dxvk {
* from a group of render passes with the same format. * from a group of render passes with the same format.
*/ */
struct DxvkRenderPassOps { struct DxvkRenderPassOps {
DxvkRenderPassBarrier barrier;
DxvkDepthAttachmentOps depthOps; DxvkDepthAttachmentOps depthOps;
DxvkColorAttachmentOps colorOps[MaxNumRenderTargets]; DxvkColorAttachmentOps colorOps[MaxNumRenderTargets];
}; };