mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-06 12:45:21 +02:00
Merge pull request #12224 from hrydgard/vulkan-barrier-fixes
Vulkan: Add missing barrier between multiple passes to the same target.
This commit is contained in:
@@ -110,3 +110,6 @@ debian/ppsspp/
|
||||
|
||||
# YouCompleteMe file
|
||||
.ycm_extra_conf.pyc
|
||||
|
||||
# RenderDoc
|
||||
*.rdc
|
||||
|
||||
@@ -379,14 +379,18 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &st
|
||||
// Planned optimizations:
|
||||
// * Create copies of render target that are rendered to multiple times and textured from in sequence, and push those render passes
|
||||
// as early as possible in the frame (Wipeout billboards).
|
||||
// * Merge subsequent render passes to the same target that are interspersed with unrelated draws to other render targets (God of War).
|
||||
|
||||
for (int j = 0; j < (int)steps.size() - 1; j++) {
|
||||
for (int j = 0; j < (int)steps.size(); j++) {
|
||||
if (steps[j]->stepType == VKRStepType::RENDER &&
|
||||
steps[j]->render.framebuffer &&
|
||||
steps[j]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
|
||||
// Just leave it at color_optimal.
|
||||
steps[j]->render.finalColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < (int)steps.size() - 1; j++) {
|
||||
// Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer.
|
||||
// Actually let's just bother with the first one for now. This affects Wipeout Pure.
|
||||
if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER &&
|
||||
@@ -458,6 +462,11 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &st
|
||||
case VKRStepType::RENDER_SKIP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Deleting all in one go should be easier on the instruction cache than deleting
|
||||
// them as we go - and easier to debug because we can look backwards in the frame.
|
||||
for (size_t i = 0; i < steps.size(); i++) {
|
||||
delete steps[i];
|
||||
}
|
||||
}
|
||||
@@ -788,6 +797,9 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
VkPipelineStageFlags dstStage{};
|
||||
switch (barrier.oldLayout) {
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
break;
|
||||
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
@@ -829,6 +841,22 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
return;
|
||||
}
|
||||
|
||||
if (step.render.framebuffer && step.render.framebuffer->color.layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.image = step.render.framebuffer->color.image;
|
||||
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
|
||||
// This is supposed to bind a vulkan render pass to the command buffer.
|
||||
PerformBindFramebufferAsRenderTarget(step, cmd);
|
||||
|
||||
@@ -947,6 +975,8 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
int w;
|
||||
int h;
|
||||
if (step.render.framebuffer) {
|
||||
_dbg_assert_(G3D, step.render.finalColorLayout != VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
|
||||
VKRFramebuffer *fb = step.render.framebuffer;
|
||||
framebuf = fb->framebuf;
|
||||
w = fb->width;
|
||||
|
||||
@@ -397,6 +397,8 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// More redundant bind elimination.
|
||||
if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == VKRRenderPassAction::KEEP && curRenderStep_->render.depth == VKRRenderPassAction::KEEP && curRenderStep_->render.stencil == VKRRenderPassAction::KEEP) {
|
||||
// Can trivially kill the last empty render step.
|
||||
assert(steps_.back() == curRenderStep_);
|
||||
@@ -409,10 +411,9 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
|
||||
}
|
||||
|
||||
VKRStep *step = new VKRStep{ VKRStepType::RENDER };
|
||||
// This is what queues up new passes, and can end previous ones.
|
||||
step->render.framebuffer = fb;
|
||||
step->render.color = color;
|
||||
step->render.depth= depth;
|
||||
step->render.depth = depth;
|
||||
step->render.stencil = stencil;
|
||||
step->render.clearColor = clearColor;
|
||||
step->render.clearDepth = clearDepth;
|
||||
@@ -423,8 +424,13 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
|
||||
steps_.push_back(step);
|
||||
|
||||
curRenderStep_ = step;
|
||||
curWidth_ = fb ? fb->width : vulkan_->GetBackbufferWidth();
|
||||
curHeight_ = fb ? fb->height : vulkan_->GetBackbufferHeight();
|
||||
if (fb) {
|
||||
curWidth_ = fb->width;
|
||||
curHeight_ = fb->height;
|
||||
} else {
|
||||
curWidth_ = vulkan_->GetBackbufferWidth();
|
||||
curHeight_ = vulkan_->GetBackbufferHeight();
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride) {
|
||||
|
||||
Reference in New Issue
Block a user