[Fix] (MG_Backend/DirectVulkan): clear every layer of layered framebuffers in vkCmdClearAttachments paths (rename the never-read RenderPassEntry::subpass to layers)

This commit is contained in:
2026-07-16 21:17:59 -04:00
parent 4172959e49
commit 5184901a5b
3 changed files with 10 additions and 7 deletions
@@ -1015,7 +1015,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
hasDepthStencilAttachment, hasDepthStencilAttachment,
renderPassSampleCount, renderPassSampleCount,
extent, extent,
static_cast<Int>(framebufferLayers) }; framebufferLayers };
MGLOG_D("VkRenderPassManager::GetOrCreateRenderPass: hash=0x%llx compatibilityHash=0x%llx attachmentCount=%u colorAttachmentCount=%u samples=%d extent=%dx%d", MGLOG_D("VkRenderPassManager::GetOrCreateRenderPass: hash=0x%llx compatibilityHash=0x%llx attachmentCount=%u colorAttachmentCount=%u samples=%d extent=%dx%d",
static_cast<unsigned long long>(hash), static_cast<unsigned long long>(hash),
static_cast<unsigned long long>(compatibilityHash), static_cast<unsigned long long>(compatibilityHash),
@@ -68,7 +68,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool hasDepthStencilAttachment = false; Bool hasDepthStencilAttachment = false;
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
IntVec2 extent = {0, 0}; IntVec2 extent = {0, 0};
Uint32 subpass = 0; // VkFramebufferCreateInfo::layers of the entry's framebuffer (>1 for layered GL attachments).
Uint32 layers = 1;
RenderPassEntry() = default; RenderPassEntry() = default;
RenderPassEntry(const RenderPassEntry&) = delete; RenderPassEntry(const RenderPassEntry&) = delete;
@@ -84,7 +85,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
std::swap(hasDepthStencilAttachment, that.hasDepthStencilAttachment); std::swap(hasDepthStencilAttachment, that.hasDepthStencilAttachment);
std::swap(sampleCount, that.sampleCount); std::swap(sampleCount, that.sampleCount);
std::swap(extent, that.extent); std::swap(extent, that.extent);
std::swap(subpass, that.subpass); std::swap(layers, that.layers);
} }
RenderPassEntry( RenderPassEntry(
Uint64 hash, Uint64 hash,
@@ -97,7 +98,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 colorAttachmentCount, Uint32 colorAttachmentCount,
Bool hasDepthStencilAttachment, Bool hasDepthStencilAttachment,
VkSampleCountFlagBits sampleCount, VkSampleCountFlagBits sampleCount,
IntVec2 extent, int subpass): IntVec2 extent, Uint32 layers):
hash(hash), hash(hash),
renderPass(renderpass), renderPass(renderpass),
framebuffer(framebuffer), framebuffer(framebuffer),
@@ -109,7 +110,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
hasDepthStencilAttachment(hasDepthStencilAttachment), hasDepthStencilAttachment(hasDepthStencilAttachment),
sampleCount(sampleCount), sampleCount(sampleCount),
extent(extent), extent(extent),
subpass(subpass) layers(layers)
{} {}
~RenderPassEntry() { ~RenderPassEntry() {
@@ -3646,7 +3646,8 @@ void main() {
m_swapchainObject.GetPreTransform()) m_swapchainObject.GetPreTransform())
: MakeClampedScissorRect(MG_State::pGLContext->GetScissorBox(), renderPassEntry->extent); : MakeClampedScissorRect(MG_State::pGLContext->GetScissorBox(), renderPassEntry->extent);
clearRect.baseArrayLayer = 0; clearRect.baseArrayLayer = 0;
clearRect.layerCount = 1; // GL 3.3 §4.4.7: clearing a layered framebuffer clears every layer.
clearRect.layerCount = renderPassEntry->layers;
if (clearRect.rect.extent.width == 0 || clearRect.rect.extent.height == 0) { if (clearRect.rect.extent.width == 0 || clearRect.rect.extent.height == 0) {
return; return;
} }
@@ -6885,7 +6886,8 @@ void main() {
static_cast<Uint32>(activeRenderPass->extent.y()) static_cast<Uint32>(activeRenderPass->extent.y())
}; };
clearRect.baseArrayLayer = 0; clearRect.baseArrayLayer = 0;
clearRect.layerCount = 1; // Compatible entries share the framebuffer layer count; layered attachments clear every layer.
clearRect.layerCount = compatibleRenderPassEntry.layers;
for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) { for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) {
if (!pending.hasInlinePayload && pending.key.texture == nullptr) { if (!pending.hasInlinePayload && pending.key.texture == nullptr) {