1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-13 19:29:14 +01:00

[dxvk] Suspend render pass when updating framebuffer

Saves barriers in case some of the previously bound framebuffer
arre reused in the new one.
This commit is contained in:
Philip Rebohle 2021-02-10 01:59:48 +01:00
parent d3b2db5978
commit ba698430cb
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 67 additions and 27 deletions

View File

@ -3388,6 +3388,7 @@ namespace dxvk {
this->flushClears(true);
m_flags.set(DxvkContextFlag::GpRenderPassBound);
m_flags.clr(DxvkContextFlag::GpRenderPassSuspended);
m_execBarriers.recordCommands(m_cmd);
@ -3413,7 +3414,7 @@ namespace dxvk {
}
void DxvkContext::spillRenderPass(bool flushClears) {
void DxvkContext::spillRenderPass(bool suspend) {
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
m_flags.clr(DxvkContextFlag::GpRenderPassBound);
@ -3423,14 +3424,25 @@ namespace dxvk {
m_queryManager.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS);
this->renderPassUnbindFramebuffer();
this->transitionRenderTargetLayouts(m_gfxBarriers);
if (suspend)
m_flags.set(DxvkContextFlag::GpRenderPassSuspended);
else
this->transitionRenderTargetLayouts(m_gfxBarriers);
m_gfxBarriers.recordCommands(m_cmd);
this->unbindGraphicsPipeline();
m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters);
} else if (flushClears) {
} else if (!suspend) {
// We may end a previously suspended render pass
if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) {
m_flags.clr(DxvkContextFlag::GpRenderPassSuspended);
this->transitionRenderTargetLayouts(m_gfxBarriers);
m_gfxBarriers.recordCommands(m_cmd);
}
// Execute deferred clears if necessary
this->flushClears(false);
}
@ -3958,7 +3970,7 @@ namespace dxvk {
if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) {
m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
this->spillRenderPass(false);
this->spillRenderPass(true);
auto fb = m_device->createFramebuffer(m_state.om.renderTargets);
this->updateRenderTargetLayouts(fb, m_state.om.framebuffer);
@ -4009,16 +4021,7 @@ namespace dxvk {
const DxvkAttachment& color = m_state.om.framebuffer->getColorTarget(i);
if (color.view != nullptr) {
barriers.accessImage(
color.view->image(),
color.view->subresources(),
m_rtLayouts.color[i],
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
color.view->imageInfo().layout,
color.view->imageInfo().stages,
color.view->imageInfo().access);
this->transitionColorAttachment(barriers, color, m_rtLayouts.color[i]);
m_rtLayouts.color[i] = color.view->imageInfo().layout;
}
}
@ -4026,23 +4029,44 @@ namespace dxvk {
const DxvkAttachment& depth = m_state.om.framebuffer->getDepthTarget();
if (depth.view != nullptr) {
barriers.accessImage(
depth.view->image(),
depth.view->subresources(),
m_rtLayouts.depth,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
m_rtLayouts.depth != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0,
depth.view->imageInfo().layout,
depth.view->imageInfo().stages,
depth.view->imageInfo().access);
this->transitionDepthAttachment(barriers, depth, m_rtLayouts.depth);
m_rtLayouts.depth = depth.view->imageInfo().layout;
}
}
void DxvkContext::transitionColorAttachment(
DxvkBarrierSet& barriers,
const DxvkAttachment& attachment,
VkImageLayout oldLayout) {
barriers.accessImage(
attachment.view->image(),
attachment.view->subresources(), oldLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
attachment.view->imageInfo().layout,
attachment.view->imageInfo().stages,
attachment.view->imageInfo().access);
}
void DxvkContext::transitionDepthAttachment(
DxvkBarrierSet& barriers,
const DxvkAttachment& attachment,
VkImageLayout oldLayout) {
barriers.accessImage(
attachment.view->image(),
attachment.view->subresources(), oldLayout,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
oldLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0,
attachment.view->imageInfo().layout,
attachment.view->imageInfo().stages,
attachment.view->imageInfo().access);
}
void DxvkContext::updateRenderTargetLayouts(
const Rc<DxvkFramebuffer>& newFb,
const Rc<DxvkFramebuffer>& oldFb) {
@ -4076,6 +4100,9 @@ namespace dxvk {
if (found)
layouts.color[j] = m_rtLayouts.color[i];
}
if (!found && m_flags.test(DxvkContextFlag::GpRenderPassSuspended))
this->transitionColorAttachment(m_execBarriers, oldAttachment, m_rtLayouts.color[i]);
}
}
@ -4090,6 +4117,8 @@ namespace dxvk {
if (found)
layouts.depth = m_rtLayouts.depth;
else if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended))
this->transitionDepthAttachment(m_execBarriers, oldAttachment, m_rtLayouts.depth);
}
}

View File

@ -1102,7 +1102,7 @@ namespace dxvk {
bool useRenderPass);
void startRenderPass();
void spillRenderPass(bool flushClears = true);
void spillRenderPass(bool suspend = false);
void renderPassBindFramebuffer(
const Rc<DxvkFramebuffer>& framebuffer,
@ -1148,6 +1148,16 @@ namespace dxvk {
void transitionRenderTargetLayouts(
DxvkBarrierSet& barriers);
void transitionColorAttachment(
DxvkBarrierSet& barriers,
const DxvkAttachment& attachment,
VkImageLayout oldLayout);
void transitionDepthAttachment(
DxvkBarrierSet& barriers,
const DxvkAttachment& attachment,
VkImageLayout oldLayout);
void updateRenderTargetLayouts(
const Rc<DxvkFramebuffer>& newFb,
const Rc<DxvkFramebuffer>& oldFb);

View File

@ -22,6 +22,7 @@ namespace dxvk {
*/
enum class DxvkContextFlag : uint32_t {
GpRenderPassBound, ///< Render pass is currently bound
GpRenderPassSuspended, ///< Render pass is currently suspended
GpXfbActive, ///< Transform feedback is enabled
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
GpDirtyPipeline, ///< Graphics pipeline binding is out of date