Don't break RPs on view pointer changes

Sometimes view pointers may change despite the underlying Vulkan image view not actually changing, so use vk::ImageViews for tracking to keep RP breaks to a minimum.
This commit is contained in:
Billy Laws 2023-02-12 20:23:10 +00:00
parent a02e1a2536
commit 7a759326b3
2 changed files with 18 additions and 28 deletions

View File

@ -275,34 +275,26 @@ namespace skyline::gpu::interconnect {
allocator = &slot->allocator;
}
static bool ViewsEqual(vk::ImageView a, TextureView *b) {
return (!a && !b) || (a && b && b->GetView() == a);
}
bool CommandExecutor::CreateRenderPassWithSubpass(vk::Rect2D renderArea, span<TextureView *> sampledImages, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment, bool noSubpassCreation) {
auto addSubpass{[&] {
renderPass->AddSubpass(inputAttachments, colorAttachments, depthStencilAttachment, gpu);
lastSubpassColorAttachments.clear();
lastSubpassInputAttachments.clear();
lastSubpassAttachments.clear();
auto insertAttachmentRange{[this](auto &attachments) -> std::pair<size_t, size_t> {
size_t beginIndex{lastSubpassAttachments.size()};
lastSubpassAttachments.insert(lastSubpassAttachments.end(), attachments.begin(), attachments.end());
return {beginIndex, attachments.size()};
}};
auto rangeToSpan{[this](auto &range) -> span<TextureView *> {
return {lastSubpassAttachments.data() + range.first, range.second};
}};
auto inputAttachmentRange{insertAttachmentRange(inputAttachments)};
auto colorAttachmentRange{insertAttachmentRange(colorAttachments)};
lastSubpassInputAttachments = rangeToSpan(inputAttachmentRange);
lastSubpassColorAttachments = rangeToSpan(colorAttachmentRange);
lastSubpassDepthStencilAttachment = depthStencilAttachment;
ranges::transform(colorAttachments, std::back_inserter(lastSubpassColorAttachments), [](TextureView *view){ return view ? view->GetView() : vk::ImageView{};});
ranges::transform(inputAttachments, std::back_inserter(lastSubpassInputAttachments), [](TextureView *view){ return view ? view->GetView() : vk::ImageView{};});
lastSubpassDepthStencilAttachment = depthStencilAttachment ? depthStencilAttachment->GetView() : vk::ImageView{};
}};
span<TextureView *> depthStencilAttachmentSpan{depthStencilAttachment ? span<TextureView *>(depthStencilAttachment) : span<TextureView *>()};
auto outputAttachmentViews{ranges::views::concat(colorAttachments, depthStencilAttachmentSpan)};
bool attachmentsMatch{ranges::equal(lastSubpassInputAttachments, inputAttachments) &&
ranges::equal(lastSubpassColorAttachments, colorAttachments) &&
lastSubpassDepthStencilAttachment == depthStencilAttachment};
bool attachmentsMatch{std::equal(lastSubpassInputAttachments.begin(), lastSubpassInputAttachments.end(), inputAttachments.begin(), inputAttachments.end(), ViewsEqual) &&
std::equal(lastSubpassColorAttachments.begin(), lastSubpassColorAttachments.end(), colorAttachments.begin(), colorAttachments.end(), ViewsEqual) &&
ViewsEqual(lastSubpassDepthStencilAttachment, depthStencilAttachment)};
bool splitRenderPass{renderPass == nullptr || renderPass->renderArea != renderArea || !attachmentsMatch ||
!ranges::all_of(outputAttachmentViews, [this] (auto view) { return !view || view->texture->ValidateRenderPassUsage(renderPassIndex, texture::RenderPassUsage::RenderTarget); }) ||
@ -343,10 +335,9 @@ namespace skyline::gpu::interconnect {
renderPass = nullptr;
subpassCount = 0;
lastSubpassAttachments.clear();
lastSubpassInputAttachments = nullptr;
lastSubpassColorAttachments = nullptr;
lastSubpassDepthStencilAttachment = nullptr;
lastSubpassInputAttachments.clear();
lastSubpassColorAttachments.clear();
lastSubpassDepthStencilAttachment = vk::ImageView{};
}
}

View File

@ -175,10 +175,9 @@ namespace skyline::gpu::interconnect {
std::vector<LockedBuffer> attachedBuffers; //!< All textures that are attached to the current execution
std::vector<TextureView *> lastSubpassAttachments; //!< The storage backing for attachments used in the last subpass
span<TextureView *> lastSubpassInputAttachments; //!< The set of input attachments used in the last subpass
span<TextureView *> lastSubpassColorAttachments; //!< The set of color attachments used in the last subpass
TextureView *lastSubpassDepthStencilAttachment{}; //!< The depth stencil attachment used in the last subpass
std::vector<vk::ImageView> lastSubpassInputAttachments; //!< The set of input attachments used in the last subpass
std::vector<vk::ImageView> lastSubpassColorAttachments; //!< The set of color attachments used in the last subpass
vk::ImageView lastSubpassDepthStencilAttachment{}; //!< The depth stencil attachment used in the last subpass
std::vector<std::function<void()>> flushCallbacks; //!< Set of persistent callbacks that will be called at the start of Execute in order to flush data required for recording
std::vector<std::function<void()>> pipelineChangeCallbacks; //!< Set of persistent callbacks that will be called after any non-Maxwell 3D engine changes the active pipeline