From 6f8c76f06cd99c5da368651ee534aee40b928732 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sun, 1 Mar 2026 22:39:30 +0800 Subject: [PATCH] [Fix] (MG_Backend/DirectVulkan): fixing Vulkan backend initialization --- .../Renderer/VkRenderPassManager.cpp | 22 +++++++----- .../Renderer/VkRenderPassManager.h | 21 +++++++++++ .../Renderer/VkTextureManager.cpp | 36 ++++++++++++++++--- .../DirectVulkan/Renderer/VkTextureManager.h | 4 ++- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 4 +-- MobileGL/MG_Util/Debug/Log.cpp | 1 + 6 files changed, 71 insertions(+), 17 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp index 498fcbb0..08264fe6 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp @@ -115,6 +115,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { case TextureTarget::Texture2D: { auto* texture2d = static_cast(texture); + desc.flags = 0; desc.format = MG_Util::ConvertTextureInternalFormatToVkEnum( texture2d->GetFormat()); @@ -156,6 +157,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkTextureManager::TextureResource* depthTextureResource = nullptr; if (depthAtt.IsComplete() && depthAtt.IsTexture()) { auto& texture = *depthAtt.GetTexture(); + depthAttachmentDescription.flags = 0; depthAttachmentDescription.format = MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat()); depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; @@ -170,6 +172,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { depthTextureResource = m_textureManager.SyncTextureAndGetDescriptor(texture); MOBILEGL_ASSERT(depthTextureResource, "GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at depth attachment"); attachmentDescriptions.emplace_back(depthAttachmentDescription); + textureResources.emplace_back(depthTextureResource); } // Depth attachment ref @@ -224,14 +227,14 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkFramebuffer framebuffer = VK_NULL_HANDLE; VK_VERIFY(vkCreateFramebuffer(m_device, &framebufferCreateInfo, nullptr, &framebuffer)); IntVec2 extent = {width, height}; - m_renderPasses[hash] = { renderPass, framebuffer, Move(textureResources), extent, 1 }; - return m_renderPasses[hash]; + RenderPassEntry renderPassEntry { + renderPass, framebuffer, Move(textureResources), extent, 1 }; + auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry)); + return insertedIt->second; } Bool VkRenderPassManager::BeginRenderPass(VkCommandBuffer commandBuffer, RenderPassEntry& renderPassEntry) { // TODO: Transition all the attachments into proper layout before starting the render pass - - VkRenderPassBeginInfo renderPassBeginInfo; renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassBeginInfo.pNext = nullptr; @@ -242,12 +245,13 @@ namespace MobileGL::MG_Backend::DirectVulkan { (Uint32)renderPassEntry.extent.x(), (Uint32)renderPassEntry.extent.y() }; // TODO: should query proper clear color - VkClearValue clearValue; - clearValue.color = { 0.0f, 0.0f, 0.0f, 1.0f }; - clearValue.depthStencil = { 1.0f, 0 }; + VkClearValue defaultClearValue; + defaultClearValue.color = { 0.0f, 0.0f, 0.0f, 1.0f }; + defaultClearValue.depthStencil = { 1.0f, 0 }; + Vector clearValue(renderPassEntry.textureResources.size(), defaultClearValue); - renderPassBeginInfo.clearValueCount = 1; - renderPassBeginInfo.pClearValues = &clearValue; + renderPassBeginInfo.clearValueCount = clearValue.size(); + renderPassBeginInfo.pClearValues = clearValue.data(); vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h index b7292df5..9d73d129 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h @@ -26,6 +26,27 @@ namespace MobileGL::MG_Backend::DirectVulkan { IntVec2 extent = {0, 0}; Uint32 subpass = 0; + RenderPassEntry() = default; + RenderPassEntry(const RenderPassEntry&) = delete; + RenderPassEntry(RenderPassEntry&& that) noexcept { + std::swap(renderPass, that.renderPass); + std::swap(framebuffer, that.framebuffer); + std::swap(textureResources, that.textureResources); + std::swap(extent, that.extent); + std::swap(subpass, that.subpass); + } + RenderPassEntry( + VkRenderPass renderpass, + VkFramebuffer framebuffer, + const std::vector& textureResources, + IntVec2 extent, int subpass): + renderPass(renderpass), + framebuffer(framebuffer), + textureResources(Move(textureResources)), + extent(extent), + subpass(subpass) + {} + ~RenderPassEntry() { if (renderPass != VK_NULL_HANDLE) { vkDestroyRenderPass(s_device, renderPass, nullptr); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 18d15af8..4b7c0377 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -167,6 +167,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { resource.~TextureResource(); + auto aspect = GetAspectMaskForFormat(format); + VkImageCreateInfo imageInfo{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.imageType = VK_IMAGE_TYPE_2D; @@ -178,7 +180,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { imageInfo.format = format; imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageInfo.usage = + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + ((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) | + ((aspect & VK_IMAGE_ASPECT_DEPTH_BIT || aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ? + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0); imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VmaAllocationCreateInfo allocationInfo{}; @@ -192,7 +199,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { viewInfo.image = resource.image; viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.format = format; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.subresourceRange.aspectMask = aspect; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = mipLevels; viewInfo.subresourceRange.baseArrayLayer = 0; @@ -203,6 +210,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { resource.extent = {static_cast(texelSize.x()), static_cast(texelSize.y())}; resource.mipLevels = mipLevels; resource.format = format; + resource.aspect = viewInfo.subresourceRange.aspectMask; return true; } @@ -270,6 +278,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { // TODO: Could be uploaded asynchronously? const Bool ok = ExecuteCmdBufImmediate([&](VkCommandBuffer commandBuffer) { + const VkImageAspectFlags aspectMask = GetAspectMaskForFormat(outResource.format); Bool ok = TransitionImageLayout(commandBuffer, outResource.image, outResource.layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, @@ -277,7 +286,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_PIPELINE_STAGE_TRANSFER_BIT, outResource.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ? VK_ACCESS_SHADER_READ_BIT : 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_ASPECT_COLOR_BIT); + aspectMask); MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL failed"); for (const auto& item : uploadItems) { @@ -285,7 +294,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { copy.bufferOffset = item.offset; copy.bufferRowLength = 0; copy.bufferImageHeight = 0; - copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy.imageSubresource.aspectMask = aspectMask; copy.imageSubresource.mipLevel = item.level; copy.imageSubresource.baseArrayLayer = 0; copy.imageSubresource.layerCount = 1; @@ -302,7 +311,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_ASPECT_COLOR_BIT); + aspectMask); MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed"); outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; return ok; @@ -421,4 +430,21 @@ namespace MobileGL::MG_Backend::DirectVulkan { return VK_FORMAT_UNDEFINED; } } + + VkImageAspectFlags VkTextureManager::GetAspectMaskForFormat(VkFormat format) { + switch (format) { + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT: + return VK_IMAGE_ASPECT_DEPTH_BIT; + case VK_FORMAT_S8_UINT: + return VK_IMAGE_ASPECT_STENCIL_BIT; + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + default: + return VK_IMAGE_ASPECT_COLOR_BIT; + } + } } // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h index 219b657e..6340d451 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h @@ -36,8 +36,9 @@ public: VkExtent2D extent = {0, 0}; Uint32 mipLevels = 1; VkFormat format = VK_FORMAT_UNDEFINED; + VkImageAspectFlags aspect = VK_IMAGE_ASPECT_NONE; - TextureResource() {} + TextureResource() = default; TextureResource(const TextureResource&) = delete; TextureResource(TextureResource&& that) noexcept { std::swap(this->image, that.image); @@ -100,6 +101,7 @@ private: Uint32& outMipLevelCount); static Uint32 GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture, TextureUploadTarget target); static VkFormat GetVkFormat(TextureInternalFormat format); + static VkImageAspectFlags GetAspectMaskForFormat(VkFormat format); VkDevice m_device = VK_NULL_HANDLE; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index e97708f5..9a36fc60 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -463,7 +463,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { auto vertexInputHash = m_vertexInputStateFactory->ComputeHash(vao); auto& vis = m_vertexInputStateFactory->GetOrCreateVertexInputState(vao); auto pipelineLayout = m_uniformDescriptorBinder->GetOrCreatePipelineLayout(program); - auto renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(drawFbo); + auto& renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(drawFbo); auto depthTestEnabled = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::DepthTest); BlendFactor srcRGB = BlendFactor::One; BlendFactor dstRGB = BlendFactor::Zero; @@ -477,7 +477,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { .vertexInputHash = vertexInputHash, .pipelineLayout = pipelineLayout, .renderPass = renderPassEntry.renderPass, - .subpass = renderPassEntry.subpass, + .subpass = 0, .topology = toVkTopology(mode), .depthTestEnable = depthTestEnabled, .depthWriteEnable = depthTestEnabled && MG_State::pGLContext->GetDepthMask(), diff --git a/MobileGL/MG_Util/Debug/Log.cpp b/MobileGL/MG_Util/Debug/Log.cpp index 32ccc68a..115a2a9c 100644 --- a/MobileGL/MG_Util/Debug/Log.cpp +++ b/MobileGL/MG_Util/Debug/Log.cpp @@ -97,6 +97,7 @@ namespace MobileGL { #if MOBILEGL_LOG_ENABLE_CONSOLE std::fwrite(out.c_str(), 1, out.size(), stdout); + fflush(stdout); #endif #if MOBILEGL_LOG_ENABLE_ANDROID && defined(__ANDROID__)