mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Chore] (MG_Backend/DirectVulkan): use vkCmdClearAttachments to implement clear semantics when there's one compatible render pass in flight (instead of interrupting it)
This commit is contained in:
@@ -32,7 +32,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassManager::HashType VkRenderPassManager::ComputeHash(
|
VkRenderPassManager::HashType VkRenderPassManager::ComputeHash(
|
||||||
const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex) const {
|
const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex, Bool includePendingClear) const {
|
||||||
XXHASH_VERIFY(XXH64_reset(m_hashState, m_config.CacheVersion));
|
XXHASH_VERIFY(XXH64_reset(m_hashState, m_config.CacheVersion));
|
||||||
const Bool isDefaultFbo = (&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get());
|
const Bool isDefaultFbo = (&fbo == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO.get());
|
||||||
if (isDefaultFbo) {
|
if (isDefaultFbo) {
|
||||||
@@ -65,7 +65,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
contentPtr = att.GetRenderbuffer().get();
|
contentPtr = att.GetRenderbuffer().get();
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &contentPtr, sizeof(contentPtr)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &contentPtr, sizeof(contentPtr)));
|
||||||
|
|
||||||
if (att.IsTexture()) {
|
if (includePendingClear && att.IsTexture()) {
|
||||||
auto* texture = att.GetTexture().get();
|
auto* texture = att.GetTexture().get();
|
||||||
auto hasClear = m_clearManager.HasPendingClear(texture);
|
auto hasClear = m_clearManager.HasPendingClear(texture);
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &hasClear, sizeof(hasClear)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &hasClear, sizeof(hasClear)));
|
||||||
@@ -95,7 +95,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
RenderPassEntry& VkRenderPassManager::GetOrCreateRenderPass(const MG_State::GLState::FramebufferObject& fbo,
|
RenderPassEntry& VkRenderPassManager::GetOrCreateRenderPass(const MG_State::GLState::FramebufferObject& fbo,
|
||||||
Uint32 swapchainImageIndex) {
|
Uint32 swapchainImageIndex) {
|
||||||
// retrieve from cache first
|
// retrieve from cache first
|
||||||
auto hash = ComputeHash(fbo, swapchainImageIndex);
|
auto hash = ComputeHash(fbo, swapchainImageIndex, true);
|
||||||
|
auto compatibilityHash = ComputeHash(fbo, swapchainImageIndex, false);
|
||||||
auto it = m_renderPasses.find(hash);
|
auto it = m_renderPasses.find(hash);
|
||||||
if (it != m_renderPasses.end())
|
if (it != m_renderPasses.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
@@ -288,6 +289,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
RenderPassEntry renderPassEntry {
|
RenderPassEntry renderPassEntry {
|
||||||
renderPass,
|
renderPass,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
|
compatibilityHash,
|
||||||
Move(textureResources),
|
Move(textureResources),
|
||||||
Move(pendingClearAttachments),
|
Move(pendingClearAttachments),
|
||||||
static_cast<Uint32>(attachmentViews.size()),
|
static_cast<Uint32>(attachmentViews.size()),
|
||||||
@@ -297,6 +299,64 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return insertedIt->second;
|
return insertedIt->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool VkRenderPassManager::TryClearPendingAttachmentsOnActiveRenderPass(
|
||||||
|
VkCommandBuffer commandBuffer,
|
||||||
|
const RenderPassEntry& compatibleRenderPassEntry) {
|
||||||
|
if (!s_activeRenderPass || !s_clearManager) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (s_activeRenderPass->compatibilityHash != compatibleRenderPassEntry.compatibilityHash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkClearRect clearRect{};
|
||||||
|
clearRect.rect.offset = {0, 0};
|
||||||
|
clearRect.rect.extent = {
|
||||||
|
static_cast<Uint32>(s_activeRenderPass->extent.x()),
|
||||||
|
static_cast<Uint32>(s_activeRenderPass->extent.y())
|
||||||
|
};
|
||||||
|
clearRect.baseArrayLayer = 0;
|
||||||
|
clearRect.layerCount = 1;
|
||||||
|
|
||||||
|
for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) {
|
||||||
|
if (!pending.texture) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearAttachmentPayload clearPayload{};
|
||||||
|
if (!s_clearManager->GetPendingClear(pending.texture, clearPayload)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkClearAttachment clearAttachment{};
|
||||||
|
clearAttachment.clearValue.depthStencil = {1.0f, 0};
|
||||||
|
if (clearPayload.attachmentType >= FramebufferAttachmentType::Color0 &&
|
||||||
|
clearPayload.attachmentType <= FramebufferAttachmentType::Color31) {
|
||||||
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
clearAttachment.colorAttachment = pending.attachmentIndex;
|
||||||
|
clearAttachment.clearValue.color = {
|
||||||
|
clearPayload.color.x(),
|
||||||
|
clearPayload.color.y(),
|
||||||
|
clearPayload.color.z(),
|
||||||
|
clearPayload.color.w()
|
||||||
|
};
|
||||||
|
} else if (clearPayload.attachmentType == FramebufferAttachmentType::Depth) {
|
||||||
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
clearAttachment.clearValue.depthStencil.depth = clearPayload.depth;
|
||||||
|
} else if (clearPayload.attachmentType == FramebufferAttachmentType::Stencil) {
|
||||||
|
clearAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
clearAttachment.clearValue.depthStencil.stencil = clearPayload.stencil;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect);
|
||||||
|
s_clearManager->PopPendingClear(pending.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Bool VkRenderPassManager::BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry) {
|
Bool VkRenderPassManager::BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry) {
|
||||||
// TODO: Transition all the attachments into proper layout before starting the render pass
|
// TODO: Transition all the attachments into proper layout before starting the render pass
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo;
|
VkRenderPassBeginInfo renderPassBeginInfo;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
static inline VkDevice s_device;
|
static inline VkDevice s_device;
|
||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||||
|
Uint64 compatibilityHash = 0;
|
||||||
// Should we hold pointer-to-resource here?
|
// Should we hold pointer-to-resource here?
|
||||||
Vector<VkTextureManager::TextureResource*> textureResources;
|
Vector<VkTextureManager::TextureResource*> textureResources;
|
||||||
Vector<PendingClearAttachmentInfo> pendingClearAttachments;
|
Vector<PendingClearAttachmentInfo> pendingClearAttachments;
|
||||||
@@ -39,6 +40,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
RenderPassEntry(RenderPassEntry&& that) noexcept {
|
RenderPassEntry(RenderPassEntry&& that) noexcept {
|
||||||
std::swap(renderPass, that.renderPass);
|
std::swap(renderPass, that.renderPass);
|
||||||
std::swap(framebuffer, that.framebuffer);
|
std::swap(framebuffer, that.framebuffer);
|
||||||
|
std::swap(compatibilityHash, that.compatibilityHash);
|
||||||
std::swap(textureResources, that.textureResources);
|
std::swap(textureResources, that.textureResources);
|
||||||
std::swap(pendingClearAttachments, that.pendingClearAttachments);
|
std::swap(pendingClearAttachments, that.pendingClearAttachments);
|
||||||
std::swap(attachmentCount, that.attachmentCount);
|
std::swap(attachmentCount, that.attachmentCount);
|
||||||
@@ -48,12 +50,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
RenderPassEntry(
|
RenderPassEntry(
|
||||||
VkRenderPass renderpass,
|
VkRenderPass renderpass,
|
||||||
VkFramebuffer framebuffer,
|
VkFramebuffer framebuffer,
|
||||||
|
Uint64 compatibilityHash,
|
||||||
const std::vector<VkTextureManager::TextureResource*>& textureResources,
|
const std::vector<VkTextureManager::TextureResource*>& textureResources,
|
||||||
const Vector<PendingClearAttachmentInfo>& pendingClearAttachments,
|
const Vector<PendingClearAttachmentInfo>& pendingClearAttachments,
|
||||||
Uint32 attachmentCount,
|
Uint32 attachmentCount,
|
||||||
IntVec2 extent, int subpass):
|
IntVec2 extent, int subpass):
|
||||||
renderPass(renderpass),
|
renderPass(renderpass),
|
||||||
framebuffer(framebuffer),
|
framebuffer(framebuffer),
|
||||||
|
compatibilityHash(compatibilityHash),
|
||||||
textureResources(Move(textureResources)),
|
textureResources(Move(textureResources)),
|
||||||
pendingClearAttachments(Move(pendingClearAttachments)),
|
pendingClearAttachments(Move(pendingClearAttachments)),
|
||||||
attachmentCount(attachmentCount),
|
attachmentCount(attachmentCount),
|
||||||
@@ -82,8 +86,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Bool Initialize();
|
Bool Initialize();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
HashType ComputeHash(const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex) const;
|
HashType ComputeHash(
|
||||||
|
const MG_State::GLState::FramebufferObject& fbo,
|
||||||
|
Uint32 swapchainImageIndex,
|
||||||
|
Bool includePendingClear = true) const;
|
||||||
RenderPassEntry& GetOrCreateRenderPass(const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex);
|
RenderPassEntry& GetOrCreateRenderPass(const MG_State::GLState::FramebufferObject& fbo, Uint32 swapchainImageIndex);
|
||||||
|
static Bool TryClearPendingAttachmentsOnActiveRenderPass(
|
||||||
|
VkCommandBuffer commandBuffer,
|
||||||
|
const RenderPassEntry& compatibleRenderPassEntry);
|
||||||
static Bool BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry);
|
static Bool BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry);
|
||||||
static Bool EndRenderPass(VkCommandBuffer commandBuffer);
|
static Bool EndRenderPass(VkCommandBuffer commandBuffer);
|
||||||
static RenderPassEntry* GetActiveRenderPass();
|
static RenderPassEntry* GetActiveRenderPass();
|
||||||
|
|||||||
@@ -514,11 +514,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
auto& renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired);
|
auto& renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired);
|
||||||
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass();
|
||||||
if (activeRenderPass != &renderPassEntry) {
|
if (activeRenderPass != &renderPassEntry) {
|
||||||
if (activeRenderPass) {
|
if (activeRenderPass &&
|
||||||
VkRenderPassManager::EndRenderPass(frame.commandBuffer);
|
VkRenderPassManager::TryClearPendingAttachmentsOnActiveRenderPass(frame.commandBuffer, renderPassEntry)) {
|
||||||
|
// Keep the current compatible render pass open and clear inside it.
|
||||||
|
} else {
|
||||||
|
if (activeRenderPass) {
|
||||||
|
VkRenderPassManager::EndRenderPass(frame.commandBuffer);
|
||||||
|
}
|
||||||
|
Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry);
|
||||||
|
MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__);
|
||||||
}
|
}
|
||||||
Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry);
|
|
||||||
MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__);
|
|
||||||
} else {
|
} else {
|
||||||
// We probably already have one compatible render pass running. Keep going.
|
// We probably already have one compatible render pass running. Keep going.
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user