[Fix] (MG_Backend/DirectVulkan): track image layout naively

This commit is contained in:
2026-03-06 14:53:43 +08:00
parent 8ae66521e3
commit c36bfe0843
4 changed files with 46 additions and 1 deletions
@@ -20,6 +20,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_swapchainObject(swapchainObject) {
RenderPassEntry::s_device = m_device;
s_clearManager = &m_clearManager;
s_textureManager = &m_textureManager;
}
VkRenderPassManager::~VkRenderPassManager() {}
@@ -120,6 +121,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Vector<VkAttachmentDescription> attachmentDescriptions(validDrawBufCount);
Vector<VkAttachmentReference> colorAttachmentRefs(validDrawBufCount);
Vector<PendingClearAttachmentInfo> pendingClearAttachments;
Vector<TrackedAttachmentLayoutInfo> trackedAttachmentLayouts;
auto& textureResources = RenderPassEntry::s_textureResourcesScratch;
textureResources.clear();
textureResources.resize(validDrawBufCount, nullptr);
@@ -184,6 +186,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MOBILEGL_ASSERT(hasClear || textureResources[i]->layout != VK_IMAGE_LAYOUT_UNDEFINED,
"GetOrCreateRenderPass: color attachment textureId=%d has undefined tracked layout with LOAD_OP_LOAD (attachment=%d)",
texture->GetExternalIndex(), i);
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
.texture = texture,
.finalLayout = desc.finalLayout,
});
attachmentViews[i] = textureResources[i]->view;
}
@@ -249,6 +255,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MOBILEGL_ASSERT(clearDepth || clearStencil || depthTextureResource->layout != VK_IMAGE_LAYOUT_UNDEFINED,
"GetOrCreateRenderPass: depth attachment textureId=%d has undefined tracked layout with LOAD_OP_LOAD",
texture.GetExternalIndex());
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
.texture = &texture,
.finalLayout = depthAttachmentDescription.finalLayout,
});
textureResources.emplace_back(depthTextureResource);
attachmentViews.emplace_back(depthTextureResource->view);
if (width == 0 || height == 0) {
@@ -308,6 +318,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
framebuffer,
compatibilityHash,
Move(pendingClearAttachments),
Move(trackedAttachmentLayouts),
static_cast<Uint32>(attachmentViews.size()),
extent,
1 };
@@ -367,7 +378,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
Bool VkRenderPassManager::EndRenderPass(VkCommandBuffer commandBuffer) {
auto* activeRenderPass = s_activeRenderPass;
vkCmdEndRenderPass(commandBuffer);
if (activeRenderPass != nullptr && !activeRenderPass->trackedAttachmentLayouts.empty()) {
MOBILEGL_ASSERT(s_textureManager != nullptr, "EndRenderPass: texture manager is null");
for (const auto& trackedAttachment : activeRenderPass->trackedAttachmentLayouts) {
s_textureManager->UpdateTrackedImageLayout(trackedAttachment.texture, trackedAttachment.finalLayout);
}
}
s_activeRenderPass = nullptr;
return true;
}
@@ -18,11 +18,17 @@
#include <Includes.h>
namespace MobileGL::MG_Backend::DirectVulkan {
struct PendingClearAttachmentInfo {
Uint32 attachmentIndex = 0;
MG_State::GLState::ITextureObject* texture = nullptr;
};
struct TrackedAttachmentLayoutInfo {
MG_State::GLState::ITextureObject* texture = nullptr;
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
};
struct RenderPassEntry {
static inline VkDevice s_device;
static inline Vector<VkTextureManager::TextureResource*> s_textureResourcesScratch;
@@ -30,6 +36,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkFramebuffer framebuffer = VK_NULL_HANDLE;
Uint64 compatibilityHash = 0;
Vector<PendingClearAttachmentInfo> pendingClearAttachments;
Vector<TrackedAttachmentLayoutInfo> trackedAttachmentLayouts;
Uint32 attachmentCount = 0;
IntVec2 extent = {0, 0};
Uint32 subpass = 0;
@@ -41,6 +48,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
std::swap(framebuffer, that.framebuffer);
std::swap(compatibilityHash, that.compatibilityHash);
std::swap(pendingClearAttachments, that.pendingClearAttachments);
std::swap(trackedAttachmentLayouts, that.trackedAttachmentLayouts);
std::swap(attachmentCount, that.attachmentCount);
std::swap(extent, that.extent);
std::swap(subpass, that.subpass);
@@ -50,12 +58,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkFramebuffer framebuffer,
Uint64 compatibilityHash,
const Vector<PendingClearAttachmentInfo>& pendingClearAttachments,
const Vector<TrackedAttachmentLayoutInfo>& trackedAttachmentLayouts,
Uint32 attachmentCount,
IntVec2 extent, int subpass):
renderPass(renderpass),
framebuffer(framebuffer),
compatibilityHash(compatibilityHash),
pendingClearAttachments(Move(pendingClearAttachments)),
trackedAttachmentLayouts(Move(trackedAttachmentLayouts)),
attachmentCount(attachmentCount),
extent(extent),
subpass(subpass)
@@ -70,9 +80,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
}
}
Bool CompatibleWith(const RenderPassEntry& that) {
Bool CompatibleWith(const RenderPassEntry& that) const {
return this->compatibilityHash == that.compatibilityHash;
}
Bool CompatibleWith(Uint64 compatibilityHash) const {
return this->compatibilityHash == compatibilityHash;
}
};
class VkRenderPassManager {
@@ -104,5 +118,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
static inline XXH64_state_t* m_hashState = XXH64_createState();
static inline RenderPassEntry* s_activeRenderPass = nullptr;
static inline VkClearManager* s_clearManager = nullptr;
static inline VkTextureManager* s_textureManager = nullptr;
};
} // namespace MobileGL::MG_Backend::DirectVulkan
@@ -58,6 +58,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return &(it->second);
}
void VkTextureManager::UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout) {
MOBILEGL_ASSERT(texture != nullptr, "UpdateTrackedImageLayout: texture is null");
auto it = m_textureResources.find(texture);
MOBILEGL_ASSERT(it != m_textureResources.end(),
"UpdateTrackedImageLayout: textureId=%d has no tracked resource", texture->GetExternalIndex());
MOBILEGL_ASSERT(it->second.image != VK_NULL_HANDLE,
"UpdateTrackedImageLayout: textureId=%d has null image", texture->GetExternalIndex());
it->second.layout = newLayout;
}
Bool VkTextureManager::TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image,
VkImageLayout& trackedLayout, VkImageLayout newLayout,
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
@@ -75,6 +75,7 @@ public:
TextureResource* SyncTextureAndGetDescriptor(
MG_State::GLState::ITextureObject& texture);
void UpdateTrackedImageLayout(MG_State::GLState::ITextureObject* texture, VkImageLayout newLayout);
static Bool TransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout& trackedLayout,
VkImageLayout newLayout, VkPipelineStageFlags srcStageMask,