mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Refactor] (MG_Backend/DirectVulkan): Decouple default render pass management from VulkanRenderer.
This commit is contained in:
@@ -223,6 +223,7 @@ set(SOURCE_FILES
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VkFramebufferManager.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp
|
||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp
|
||||
|
||||
MobileGL/MG_State/GLState/Core.cpp
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp
|
||||
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||
// Licensed under the GNU Lesser General Public License v3.0:
|
||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
|
||||
#include "VkRenderPassManager.h"
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Bool VkRenderPassManager::Initialize(const InitInfo& initInfo) {
|
||||
Shutdown();
|
||||
|
||||
if (initInfo.device == VK_NULL_HANDLE || initInfo.colorFormat == VK_FORMAT_UNDEFINED ||
|
||||
initInfo.depthStencilFormat == VK_FORMAT_UNDEFINED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_device = initInfo.device;
|
||||
m_colorFormat = initInfo.colorFormat;
|
||||
m_depthStencilFormat = initInfo.depthStencilFormat;
|
||||
m_renderPassLoad = CreateDefaultRenderPass(VK_ATTACHMENT_LOAD_OP_LOAD);
|
||||
m_renderPassClear = CreateDefaultRenderPass(VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||
MGLOG_D("VkRenderPassManager: RenderPasses created (LOAD/CLEAR).");
|
||||
return m_renderPassLoad != VK_NULL_HANDLE && m_renderPassClear != VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void VkRenderPassManager::Shutdown() {
|
||||
if (m_device != VK_NULL_HANDLE) {
|
||||
if (m_renderPassClear != VK_NULL_HANDLE) {
|
||||
vkDestroyRenderPass(m_device, m_renderPassClear, nullptr);
|
||||
}
|
||||
if (m_renderPassLoad != VK_NULL_HANDLE) {
|
||||
vkDestroyRenderPass(m_device, m_renderPassLoad, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
m_renderPassClear = VK_NULL_HANDLE;
|
||||
m_renderPassLoad = VK_NULL_HANDLE;
|
||||
m_colorFormat = VK_FORMAT_UNDEFINED;
|
||||
m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
m_device = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkRenderPass VkRenderPassManager::GetLoadRenderPass() const {
|
||||
return m_renderPassLoad;
|
||||
}
|
||||
|
||||
VkRenderPass VkRenderPassManager::GetClearRenderPass() const {
|
||||
return m_renderPassClear;
|
||||
}
|
||||
|
||||
VkRenderPass VkRenderPassManager::CreateDefaultRenderPass(VkAttachmentLoadOp colorLoadOp) const {
|
||||
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "VkRenderPassManager: device is null");
|
||||
MOBILEGL_ASSERT(m_colorFormat != VK_FORMAT_UNDEFINED, "VkRenderPassManager: color format is undefined");
|
||||
MOBILEGL_ASSERT(m_depthStencilFormat != VK_FORMAT_UNDEFINED,
|
||||
"VkRenderPassManager: depth/stencil format is undefined");
|
||||
|
||||
VkAttachmentDescription color{};
|
||||
color.format = m_colorFormat;
|
||||
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
color.loadOp = colorLoadOp;
|
||||
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
color.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
color.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
|
||||
VkAttachmentDescription depthStencil{};
|
||||
depthStencil.format = m_depthStencilFormat;
|
||||
depthStencil.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
depthStencil.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthStencil.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkAttachmentReference colorRef{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||
VkAttachmentReference depthStencilRef{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
||||
|
||||
VkSubpassDescription subpass{};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &colorRef;
|
||||
subpass.pDepthStencilAttachment = &depthStencilRef;
|
||||
|
||||
VkAttachmentDescription attachments[2] = {color, depthStencil};
|
||||
|
||||
VkRenderPassCreateInfo createInfo{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
createInfo.attachmentCount = 2;
|
||||
createInfo.pAttachments = attachments;
|
||||
createInfo.subpassCount = 1;
|
||||
createInfo.pSubpasses = &subpass;
|
||||
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
VK_VERIFY(vkCreateRenderPass(m_device, &createInfo, nullptr, &renderPass), "vkCreateRenderPass(default)");
|
||||
return renderPass;
|
||||
}
|
||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||
@@ -0,0 +1,38 @@
|
||||
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h
|
||||
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||
// Licensed under the GNU Lesser General Public License v3.0:
|
||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../VkIncludes.h"
|
||||
#include <Includes.h>
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
class VkRenderPassManager {
|
||||
public:
|
||||
struct InitInfo {
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkFormat colorFormat = VK_FORMAT_UNDEFINED;
|
||||
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
};
|
||||
|
||||
Bool Initialize(const InitInfo& initInfo);
|
||||
void Shutdown();
|
||||
|
||||
VkRenderPass GetLoadRenderPass() const;
|
||||
VkRenderPass GetClearRenderPass() const;
|
||||
|
||||
private:
|
||||
VkRenderPass CreateDefaultRenderPass(VkAttachmentLoadOp colorLoadOp) const;
|
||||
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkFormat m_colorFormat = VK_FORMAT_UNDEFINED;
|
||||
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
VkRenderPass m_renderPassLoad = VK_NULL_HANDLE;
|
||||
VkRenderPass m_renderPassClear = VK_NULL_HANDLE;
|
||||
};
|
||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||
@@ -144,7 +144,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
payload.programHash = programHash;
|
||||
payload.vertexInputHash = vertexInputHash;
|
||||
payload.pipelineLayout = pipelineLayout;
|
||||
payload.renderPass = (m_activeRenderPass != VK_NULL_HANDLE) ? m_activeRenderPass : m_renderPassLoad;
|
||||
payload.renderPass = (m_activeRenderPass != VK_NULL_HANDLE) ? m_activeRenderPass : GetDefaultLoadRenderPass();
|
||||
payload.subpass = 0;
|
||||
payload.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
if (MG_State::pGLContext != nullptr) {
|
||||
@@ -202,6 +202,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
CreateAllocator();
|
||||
|
||||
CreateCommandPool();
|
||||
m_renderPassManager = MakeUnique<VkRenderPassManager>();
|
||||
|
||||
RecreateSwapchain();
|
||||
|
||||
@@ -281,6 +282,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
ShutdownSwapchain();
|
||||
m_renderPassManager.reset();
|
||||
|
||||
if (m_commandPool != VK_NULL_HANDLE) {
|
||||
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
|
||||
@@ -603,7 +605,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = m_renderPassLoad;
|
||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
||||
@@ -1304,7 +1306,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = m_renderPassLoad;
|
||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
||||
@@ -1883,7 +1885,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = m_renderPassLoad;
|
||||
renderPassInfo.renderPass = GetDefaultLoadRenderPass();
|
||||
renderPassInfo.framebuffer = m_framebuffers[m_imageIndexAcquired];
|
||||
renderPassInfo.renderArea.offset = {0, 0};
|
||||
renderPassInfo.renderArea.extent = m_swapchainObject.GetExtent();
|
||||
@@ -2531,52 +2533,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_I("Command pool created");
|
||||
}
|
||||
|
||||
VkRenderPass VulkanRenderer::CreateDefaultRenderPass(VkAttachmentLoadOp loadOp) {
|
||||
VkAttachmentDescription color{};
|
||||
color.format = m_swapchainObject.GetSurfaceFormat().format;
|
||||
color.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
color.loadOp = loadOp;
|
||||
color.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
color.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
color.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
|
||||
VkAttachmentDescription depthStencil{};
|
||||
depthStencil.format = m_depthStencilFormat;
|
||||
depthStencil.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
depthStencil.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthStencil.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depthStencil.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthStencil.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkAttachmentReference colorRef{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
|
||||
VkAttachmentReference depthStencilRef{1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
|
||||
VkSubpassDescription sub{};
|
||||
sub.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
sub.colorAttachmentCount = 1;
|
||||
sub.pColorAttachments = &colorRef;
|
||||
sub.pDepthStencilAttachment = &depthStencilRef;
|
||||
|
||||
VkAttachmentDescription attachments[] = {color, depthStencil};
|
||||
|
||||
VkRenderPassCreateInfo rpci{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
|
||||
rpci.attachmentCount = static_cast<Uint32>(std::size(attachments));
|
||||
rpci.pAttachments = attachments;
|
||||
rpci.subpassCount = 1;
|
||||
rpci.pSubpasses = ⊂
|
||||
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
VK_VERIFY(vkCreateRenderPass(m_device, &rpci, nullptr, &renderPass), "vkCreateRenderPass");
|
||||
VkRenderPass VulkanRenderer::GetDefaultLoadRenderPass() const {
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "GetDefaultLoadRenderPass: render pass manager is null");
|
||||
const VkRenderPass renderPass = m_renderPassManager->GetLoadRenderPass();
|
||||
MOBILEGL_ASSERT(renderPass != VK_NULL_HANDLE,
|
||||
"GetDefaultLoadRenderPass: default load render pass is unavailable");
|
||||
return renderPass;
|
||||
}
|
||||
|
||||
void VulkanRenderer::CreateDefaultRenderPass() {
|
||||
m_renderPassLoad = CreateDefaultRenderPass(VK_ATTACHMENT_LOAD_OP_LOAD);
|
||||
m_renderPassClear = CreateDefaultRenderPass(VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||
MGLOG_D("RenderPasses created (LOAD/CLEAR).");
|
||||
}
|
||||
|
||||
void VulkanRenderer::CreateDefaultFramebuffers() {
|
||||
// Create framebuffers now (use swapchain imageviews)
|
||||
const auto& imageViews = m_swapchainObject.GetImageViews();
|
||||
@@ -2586,7 +2550,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
for (SizeT i = 0; i < imageViews.size(); ++i) {
|
||||
VkImageView attachments[] = {imageViews[i], m_depthStencilImageViews[i]};
|
||||
VkFramebufferCreateInfo fbci{VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
fbci.renderPass = m_renderPassLoad;
|
||||
fbci.renderPass = GetDefaultLoadRenderPass();
|
||||
fbci.attachmentCount = static_cast<Uint32>(std::size(attachments));
|
||||
fbci.pAttachments = attachments;
|
||||
fbci.width = swapchainExtent.width;
|
||||
@@ -2750,14 +2714,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
DestroyDepthStencilResources();
|
||||
|
||||
if (m_renderPassClear != VK_NULL_HANDLE) {
|
||||
vkDestroyRenderPass(m_device, m_renderPassClear, nullptr);
|
||||
m_renderPassClear = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (m_renderPassLoad != VK_NULL_HANDLE) {
|
||||
vkDestroyRenderPass(m_device, m_renderPassLoad, nullptr);
|
||||
m_renderPassLoad = VK_NULL_HANDLE;
|
||||
if (m_renderPassManager) {
|
||||
m_renderPassManager->Shutdown();
|
||||
}
|
||||
|
||||
m_swapchainObject.Shutdown(m_device);
|
||||
@@ -2781,7 +2739,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
static_cast<Uint32>(m_swapchainObject.GetImageCount())),
|
||||
"RecreateSwapchain, InitializeSwapchainSemaphores");
|
||||
CreateDepthStencilResources();
|
||||
CreateDefaultRenderPass();
|
||||
MOBILEGL_ASSERT(m_renderPassManager != nullptr, "RecreateSwapchain: render pass manager is null");
|
||||
VkRenderPassManager::InitInfo renderPassInitInfo{};
|
||||
renderPassInitInfo.device = m_device;
|
||||
renderPassInitInfo.colorFormat = m_swapchainObject.GetSurfaceFormat().format;
|
||||
renderPassInitInfo.depthStencilFormat = m_depthStencilFormat;
|
||||
MOBILEGL_ASSERT(m_renderPassManager->Initialize(renderPassInitInfo),
|
||||
"RecreateSwapchain: render pass manager initialization failed");
|
||||
CreateDefaultFramebuffers();
|
||||
if (m_pipelineFactory) {
|
||||
m_pipelineFactory->DestroyAll();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "VertexInputStateFactory.h"
|
||||
#include "VkBufferObject.h"
|
||||
#include "VkFramebufferManager.h"
|
||||
#include "VkRenderPassManager.h"
|
||||
#include "VkTextureSamplerManager.h"
|
||||
#include "MG_Util/Math/VectorTypes.h"
|
||||
#include <Includes.h>
|
||||
@@ -124,8 +125,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||
|
||||
VkRenderPass m_renderPassLoad = VK_NULL_HANDLE;
|
||||
VkRenderPass m_renderPassClear = VK_NULL_HANDLE;
|
||||
Vector<VkFramebuffer> m_framebuffers;
|
||||
VkFormat m_depthStencilFormat = VK_FORMAT_UNDEFINED;
|
||||
Vector<VkImage> m_depthStencilImages;
|
||||
@@ -155,6 +154,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
UniquePtr<UniformDescriptorBinder> m_uniformDescriptorBinder;
|
||||
UniquePtr<VertexInputStateFactory> m_vertexInputStateFactory;
|
||||
UniquePtr<VkFramebufferManager> m_framebufferManager;
|
||||
UniquePtr<VkRenderPassManager> m_renderPassManager;
|
||||
UniquePtr<VkTextureSamplerManager> m_textureSamplerManager;
|
||||
|
||||
void CreateInstance();
|
||||
@@ -171,8 +171,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
void CreateFrameContexts();
|
||||
void CreateDepthStencilResources();
|
||||
void DestroyDepthStencilResources();
|
||||
void CreateDefaultRenderPass();
|
||||
VkRenderPass CreateDefaultRenderPass(VkAttachmentLoadOp loadOp);
|
||||
VkRenderPass GetDefaultLoadRenderPass() const;
|
||||
void CreateDefaultFramebuffers();
|
||||
void PrepareDemoPipeline();
|
||||
VkPipeline GetOrCreatePipeline(const MG_State::GLState::ProgramObject& program, VkPipelineLayout pipelineLayout,
|
||||
|
||||
Reference in New Issue
Block a user