mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (MG_Backend/DirectVulkan): Pipeline factory
This commit is contained in:
@@ -213,6 +213,7 @@ set(SOURCE_FILES
|
|||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/SwapchainObject.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/SwapchainObject.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp
|
||||||
|
MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramFactory.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateBuilder.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateBuilder.cpp
|
||||||
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp
|
MobileGL/MG_Backend/DirectVulkan/Renderer/VertexInputStateFactory.cpp
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.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 "PipelineFactory.h"
|
||||||
|
|
||||||
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
PipelineFactory::~PipelineFactory() {
|
||||||
|
DestroyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineFactory::HashType PipelineFactory::ComputeHash(const PipelineCreatePayload& payload) const {
|
||||||
|
XXHASH_VERIFY(XXH64_reset(m_hashState, m_config.CacheVersion));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.programHash, sizeof(payload.programHash)));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.vertexInputHash, sizeof(payload.vertexInputHash)));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.pipelineLayout, sizeof(payload.pipelineLayout)));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.renderPass, sizeof(payload.renderPass)));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.subpass, sizeof(payload.subpass)));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.topology, sizeof(payload.topology)));
|
||||||
|
return XXH64_digest(m_hashState);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipeline PipelineFactory::GetOrCreatePipeline(const PipelineCreatePayload& payload) {
|
||||||
|
const HashType hash = ComputeHash(payload);
|
||||||
|
auto it = m_cache.find(hash);
|
||||||
|
if (it != m_cache.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipeline pipeline = CreatePipeline(payload);
|
||||||
|
m_cache.emplace(hash, pipeline);
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipelineFactory::DestroyAll() {
|
||||||
|
for (auto& pair : m_cache) {
|
||||||
|
if (pair.second != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipeline(m_device, pair.second, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipeline PipelineFactory::CreatePipeline(const PipelineCreatePayload& payload) const {
|
||||||
|
MOBILEGL_ASSERT(payload.stages != nullptr && !payload.stages->empty(), "PipelineFactory: stages are empty");
|
||||||
|
MOBILEGL_ASSERT(payload.vertexInputState != nullptr, "PipelineFactory: vertexInputState is null");
|
||||||
|
MOBILEGL_ASSERT(payload.pipelineLayout != VK_NULL_HANDLE, "PipelineFactory: pipelineLayout is null");
|
||||||
|
MOBILEGL_ASSERT(payload.renderPass != VK_NULL_HANDLE, "PipelineFactory: renderPass is null");
|
||||||
|
|
||||||
|
static constexpr VkDynamicState kDynamicStates[] = {
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicState{};
|
||||||
|
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
|
dynamicState.dynamicStateCount = static_cast<uint32_t>(std::size(kDynamicStates));
|
||||||
|
dynamicState.pDynamicStates = kDynamicStates;
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo ia{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
|
||||||
|
ia.topology = payload.topology;
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo vpci{VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
|
||||||
|
vpci.viewportCount = 1;
|
||||||
|
vpci.scissorCount = 1;
|
||||||
|
|
||||||
|
VkPipelineRasterizationStateCreateInfo raster{VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
|
||||||
|
raster.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
|
raster.cullMode = VK_CULL_MODE_NONE;
|
||||||
|
raster.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
|
raster.lineWidth = 1.0f;
|
||||||
|
|
||||||
|
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
||||||
|
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
|
||||||
|
depthStencil.depthTestEnable = VK_FALSE;
|
||||||
|
depthStencil.depthWriteEnable = VK_FALSE;
|
||||||
|
depthStencil.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
||||||
|
depthStencil.stencilTestEnable = VK_FALSE;
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState colorAttach{};
|
||||||
|
colorAttach.colorWriteMask =
|
||||||
|
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
colorAttach.blendEnable = VK_FALSE;
|
||||||
|
VkPipelineColorBlendStateCreateInfo blend{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
|
||||||
|
blend.attachmentCount = 1;
|
||||||
|
blend.pAttachments = &colorAttach;
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo gpi{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
|
||||||
|
gpi.stageCount = static_cast<Uint32>(payload.stages->size());
|
||||||
|
gpi.pStages = payload.stages->data();
|
||||||
|
gpi.pVertexInputState = payload.vertexInputState;
|
||||||
|
gpi.pInputAssemblyState = &ia;
|
||||||
|
gpi.pViewportState = &vpci;
|
||||||
|
gpi.pRasterizationState = &raster;
|
||||||
|
gpi.pMultisampleState = &ms;
|
||||||
|
gpi.pDepthStencilState = &depthStencil;
|
||||||
|
gpi.pColorBlendState = &blend;
|
||||||
|
gpi.pDynamicState = &dynamicState;
|
||||||
|
gpi.layout = payload.pipelineLayout;
|
||||||
|
gpi.renderPass = payload.renderPass;
|
||||||
|
gpi.subpass = payload.subpass;
|
||||||
|
|
||||||
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
|
VK_VERIFY(vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &gpi, nullptr, &pipeline),
|
||||||
|
"vkCreateGraphicsPipelines");
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineFactory.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 "Config.h"
|
||||||
|
#include "../VkIncludes.h"
|
||||||
|
#include <Includes.h>
|
||||||
|
|
||||||
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
class PipelineFactory {
|
||||||
|
public:
|
||||||
|
using HashType = Uint64;
|
||||||
|
|
||||||
|
struct PipelineCreatePayload {
|
||||||
|
HashType programHash = 0;
|
||||||
|
HashType vertexInputHash = 0;
|
||||||
|
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||||
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
|
Uint32 subpass = 0;
|
||||||
|
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
const Vector<VkPipelineShaderStageCreateInfo>* stages = nullptr;
|
||||||
|
const VkPipelineVertexInputStateCreateInfo* vertexInputState = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit PipelineFactory(VkDevice device, const VulkanRendererConfig& config):
|
||||||
|
m_device(device), m_config(config) {}
|
||||||
|
~PipelineFactory();
|
||||||
|
PipelineFactory(const PipelineFactory&) = delete;
|
||||||
|
|
||||||
|
HashType ComputeHash(const PipelineCreatePayload& payload) const;
|
||||||
|
VkPipeline GetOrCreatePipeline(const PipelineCreatePayload& payload);
|
||||||
|
void DestroyAll();
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkPipeline CreatePipeline(const PipelineCreatePayload& payload) const;
|
||||||
|
|
||||||
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
|
const VulkanRendererConfig& m_config;
|
||||||
|
UnorderedMap<HashType, VkPipeline> m_cache;
|
||||||
|
static inline XXH64_state_t* m_hashState = XXH64_createState();
|
||||||
|
};
|
||||||
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
@@ -76,96 +76,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
VkPipeline VulkanRenderer::CreateGraphicsPipeline(const VkPipelineVertexInputStateCreateInfo& vertexInputState) const {
|
VkPipeline VulkanRenderer::GetOrCreatePipeline(
|
||||||
MOBILEGL_ASSERT(!m_demoPipelineStages.empty(), "CreateGraphicsPipeline requires shader stages");
|
Uint64 programHash, Uint64 vertexInputHash, const VkPipelineVertexInputStateCreateInfo& vertexInputState) {
|
||||||
|
MOBILEGL_ASSERT(m_pipelineFactory != nullptr, "PipelineFactory is not initialized");
|
||||||
|
MOBILEGL_ASSERT(!m_demoPipelineStages.empty(), "GetOrCreatePipeline requires shader stages");
|
||||||
|
|
||||||
VkPipelineDynamicStateCreateInfo dynamicState{};
|
PipelineFactory::PipelineCreatePayload payload{};
|
||||||
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
payload.programHash = programHash;
|
||||||
dynamicState.dynamicStateCount = static_cast<uint32_t>(std::size(s_dynamicStates));
|
payload.vertexInputHash = vertexInputHash;
|
||||||
dynamicState.pDynamicStates = s_dynamicStates;
|
payload.pipelineLayout = m_pipelineLayout;
|
||||||
|
payload.renderPass = m_renderPassLoad;
|
||||||
VkPipelineInputAssemblyStateCreateInfo ia{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO};
|
payload.subpass = 0;
|
||||||
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
payload.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
payload.stages = &m_demoPipelineStages;
|
||||||
VkViewport vp{};
|
payload.vertexInputState = &vertexInputState;
|
||||||
vp.x = 0;
|
return m_pipelineFactory->GetOrCreatePipeline(payload);
|
||||||
vp.y = 0;
|
|
||||||
const auto swapchainExtent = m_swapchainObject.GetExtent();
|
|
||||||
vp.width = (float)swapchainExtent.width;
|
|
||||||
vp.height = (float)swapchainExtent.height;
|
|
||||||
vp.minDepth = 0;
|
|
||||||
vp.maxDepth = 1;
|
|
||||||
VkRect2D scissor{{0, 0}, swapchainExtent};
|
|
||||||
VkPipelineViewportStateCreateInfo vpci{VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO};
|
|
||||||
vpci.viewportCount = 1;
|
|
||||||
vpci.pViewports = &vp;
|
|
||||||
vpci.scissorCount = 1;
|
|
||||||
vpci.pScissors = &scissor;
|
|
||||||
|
|
||||||
VkPipelineRasterizationStateCreateInfo raster{VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO};
|
|
||||||
raster.polygonMode = VK_POLYGON_MODE_FILL;
|
|
||||||
raster.cullMode = VK_CULL_MODE_NONE;
|
|
||||||
raster.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
|
||||||
raster.lineWidth = 1.0f;
|
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
|
||||||
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
|
|
||||||
depthStencil.depthTestEnable = VK_FALSE;
|
|
||||||
depthStencil.depthWriteEnable = VK_FALSE;
|
|
||||||
depthStencil.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
|
||||||
depthStencil.depthBoundsTestEnable = VK_FALSE;
|
|
||||||
depthStencil.stencilTestEnable = VK_FALSE;
|
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState colorAttach{};
|
|
||||||
colorAttach.colorWriteMask =
|
|
||||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
|
||||||
colorAttach.blendEnable = VK_FALSE;
|
|
||||||
VkPipelineColorBlendStateCreateInfo blend{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
|
|
||||||
blend.attachmentCount = 1;
|
|
||||||
blend.pAttachments = &colorAttach;
|
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo gpi{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
|
|
||||||
gpi.stageCount = static_cast<Uint32>(m_demoPipelineStages.size());
|
|
||||||
gpi.pStages = m_demoPipelineStages.data();
|
|
||||||
gpi.pVertexInputState = &vertexInputState;
|
|
||||||
gpi.pInputAssemblyState = &ia;
|
|
||||||
gpi.pViewportState = &vpci;
|
|
||||||
gpi.pRasterizationState = &raster;
|
|
||||||
gpi.pMultisampleState = &ms;
|
|
||||||
gpi.pDepthStencilState = &depthStencil;
|
|
||||||
gpi.pColorBlendState = &blend;
|
|
||||||
gpi.pDynamicState = &dynamicState;
|
|
||||||
gpi.layout = m_pipelineLayout;
|
|
||||||
gpi.renderPass = m_renderPassLoad;
|
|
||||||
gpi.subpass = 0;
|
|
||||||
|
|
||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
|
||||||
VK_VERIFY(vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &gpi, nullptr, &pipeline),
|
|
||||||
"vkCreateGraphicsPipelines");
|
|
||||||
return pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipeline VulkanRenderer::GetOrCreatePipelineVariant(
|
|
||||||
Uint64 hash, const VkPipelineVertexInputStateCreateInfo& vertexInputState) {
|
|
||||||
const auto it = m_pipelineVariants.find(hash);
|
|
||||||
if (it != m_pipelineVariants.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipeline pipeline = CreateGraphicsPipeline(vertexInputState);
|
|
||||||
m_pipelineVariants.emplace(hash, pipeline);
|
|
||||||
return pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanRenderer::DestroyPipelineVariants() {
|
|
||||||
for (auto& pair : m_pipelineVariants) {
|
|
||||||
if (pair.second != VK_NULL_HANDLE) {
|
|
||||||
vkDestroyPipeline(m_device, pair.second, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_pipelineVariants.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::PrepareDemoPipeline() {
|
void VulkanRenderer::PrepareDemoPipeline() {
|
||||||
@@ -196,6 +121,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& stages = m_programFactory->GetOrCreatePipelineShaderStages(programObject, ProgramFactory::CompileOptionBit::None);
|
auto& stages = m_programFactory->GetOrCreatePipelineShaderStages(programObject, ProgramFactory::CompileOptionBit::None);
|
||||||
|
m_demoProgramHash = m_programFactory->ComputeHash(programObject, ProgramFactory::CompileOptionBit::None);
|
||||||
m_demoPipelineStages = stages;
|
m_demoPipelineStages = stages;
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo plci{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
VkPipelineLayoutCreateInfo plci{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
||||||
@@ -203,7 +129,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VertexInputStateBuilder vertexInputBuilder;
|
VertexInputStateBuilder vertexInputBuilder;
|
||||||
const auto& vertexInput = vertexInputBuilder.Build();
|
const auto& vertexInput = vertexInputBuilder.Build();
|
||||||
m_pipeline = CreateGraphicsPipeline(vertexInput);
|
m_pipeline = GetOrCreatePipeline(m_demoProgramHash, 0, vertexInput);
|
||||||
|
|
||||||
// vkDestroyShaderModule(m_device, vs, nullptr);
|
// vkDestroyShaderModule(m_device, vs, nullptr);
|
||||||
// vkDestroyShaderModule(m_device, fs, nullptr);
|
// vkDestroyShaderModule(m_device, fs, nullptr);
|
||||||
@@ -228,6 +154,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
RecreateSwapchain();
|
RecreateSwapchain();
|
||||||
|
|
||||||
|
m_pipelineFactory = MakeUnique<PipelineFactory>(m_device, m_config);
|
||||||
m_programFactory = MakeUnique<ProgramFactory>(m_device, m_config);
|
m_programFactory = MakeUnique<ProgramFactory>(m_device, m_config);
|
||||||
m_vertexInputStateFactory = MakeUnique<VertexInputStateFactory>(m_config);
|
m_vertexInputStateFactory = MakeUnique<VertexInputStateFactory>(m_config);
|
||||||
|
|
||||||
@@ -244,6 +171,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void VulkanRenderer::Shutdown() {
|
void VulkanRenderer::Shutdown() {
|
||||||
VK_VERIFY(vkDeviceWaitIdle(m_device));
|
VK_VERIFY(vkDeviceWaitIdle(m_device));
|
||||||
|
|
||||||
|
m_pipelineFactory.reset();
|
||||||
m_programFactory.reset();
|
m_programFactory.reset();
|
||||||
m_vertexInputStateFactory.reset();
|
m_vertexInputStateFactory.reset();
|
||||||
m_vertexBuffer.Destroy();
|
m_vertexBuffer.Destroy();
|
||||||
@@ -251,11 +179,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
m_frameContext.Destroy(m_device, m_commandPool);
|
m_frameContext.Destroy(m_device, m_commandPool);
|
||||||
|
|
||||||
if (m_pipeline != VK_NULL_HANDLE) {
|
|
||||||
vkDestroyPipeline(m_device, m_pipeline, nullptr);
|
|
||||||
m_pipeline = VK_NULL_HANDLE;
|
m_pipeline = VK_NULL_HANDLE;
|
||||||
}
|
|
||||||
DestroyPipelineVariants();
|
|
||||||
|
|
||||||
if (m_pipelineLayout != VK_NULL_HANDLE) {
|
if (m_pipelineLayout != VK_NULL_HANDLE) {
|
||||||
vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr);
|
||||||
@@ -500,7 +424,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkPipeline pipelineToBind = m_pipeline;
|
VkPipeline pipelineToBind = m_pipeline;
|
||||||
if (vertexInputState) {
|
if (vertexInputState) {
|
||||||
pipelineToBind = GetOrCreatePipelineVariant(vertexInputState->hash, vertexInputState->state);
|
pipelineToBind = GetOrCreatePipeline(m_demoProgramHash, vertexInputState->hash, vertexInputState->state);
|
||||||
if (pipelineToBind == VK_NULL_HANDLE) {
|
if (pipelineToBind == VK_NULL_HANDLE) {
|
||||||
MGLOG_W("DrawArrays skipped: failed to create/get pipeline variant");
|
MGLOG_W("DrawArrays skipped: failed to create/get pipeline variant");
|
||||||
return;
|
return;
|
||||||
@@ -604,7 +528,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkPipeline pipelineToBind = m_pipeline;
|
VkPipeline pipelineToBind = m_pipeline;
|
||||||
if (vertexInputState) {
|
if (vertexInputState) {
|
||||||
pipelineToBind = GetOrCreatePipelineVariant(vertexInputState->hash, vertexInputState->state);
|
pipelineToBind = GetOrCreatePipeline(m_demoProgramHash, vertexInputState->hash, vertexInputState->state);
|
||||||
if (pipelineToBind == VK_NULL_HANDLE) {
|
if (pipelineToBind == VK_NULL_HANDLE) {
|
||||||
MGLOG_W("DrawElements skipped: failed to create/get pipeline variant");
|
MGLOG_W("DrawElements skipped: failed to create/get pipeline variant");
|
||||||
return;
|
return;
|
||||||
@@ -1465,15 +1389,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
CreateDepthStencilResources();
|
CreateDepthStencilResources();
|
||||||
CreateDefaultRenderPass();
|
CreateDefaultRenderPass();
|
||||||
CreateDefaultFramebuffers();
|
CreateDefaultFramebuffers();
|
||||||
DestroyPipelineVariants();
|
if (m_pipelineFactory) {
|
||||||
if (m_pipeline != VK_NULL_HANDLE) {
|
m_pipelineFactory->DestroyAll();
|
||||||
vkDestroyPipeline(m_device, m_pipeline, nullptr);
|
|
||||||
m_pipeline = VK_NULL_HANDLE;
|
|
||||||
}
|
}
|
||||||
if (!m_demoPipelineStages.empty() && m_pipelineLayout != VK_NULL_HANDLE) {
|
m_pipeline = VK_NULL_HANDLE;
|
||||||
|
if (!m_demoPipelineStages.empty() && m_pipelineLayout != VK_NULL_HANDLE && m_pipelineFactory) {
|
||||||
VertexInputStateBuilder vertexInputBuilder;
|
VertexInputStateBuilder vertexInputBuilder;
|
||||||
const auto& vertexInput = vertexInputBuilder.Build();
|
const auto& vertexInput = vertexInputBuilder.Build();
|
||||||
m_pipeline = CreateGraphicsPipeline(vertexInput);
|
m_pipeline = GetOrCreatePipeline(m_demoProgramHash, 0, vertexInput);
|
||||||
}
|
}
|
||||||
if (m_frameContext.GetFrameCount() > 0) {
|
if (m_frameContext.GetFrameCount() > 0) {
|
||||||
m_frameContext.GetCurrent().isCommandRecording = false;
|
m_frameContext.GetCurrent().isCommandRecording = false;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "FrameContext.h"
|
#include "FrameContext.h"
|
||||||
|
#include "PipelineFactory.h"
|
||||||
#include "ProgramFactory.h"
|
#include "ProgramFactory.h"
|
||||||
#include "SwapchainObject.h"
|
#include "SwapchainObject.h"
|
||||||
#include "VkBufferObject.h"
|
#include "VkBufferObject.h"
|
||||||
@@ -117,7 +118,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||||
UnorderedMap<Uint64, VkPipeline> m_pipelineVariants;
|
Uint64 m_demoProgramHash = 0;
|
||||||
Vector<VkPipelineShaderStageCreateInfo> m_demoPipelineStages;
|
Vector<VkPipelineShaderStageCreateInfo> m_demoPipelineStages;
|
||||||
VkBufferObject m_vertexBuffer;
|
VkBufferObject m_vertexBuffer;
|
||||||
VkBufferObject m_indexBuffer;
|
VkBufferObject m_indexBuffer;
|
||||||
@@ -130,6 +131,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Uint32 m_pendingClearStencil = 0;
|
Uint32 m_pendingClearStencil = 0;
|
||||||
Bool m_isMainRenderPassActive = false;
|
Bool m_isMainRenderPassActive = false;
|
||||||
|
|
||||||
|
UniquePtr<PipelineFactory> m_pipelineFactory;
|
||||||
UniquePtr<ProgramFactory> m_programFactory;
|
UniquePtr<ProgramFactory> m_programFactory;
|
||||||
UniquePtr<VertexInputStateFactory> m_vertexInputStateFactory;
|
UniquePtr<VertexInputStateFactory> m_vertexInputStateFactory;
|
||||||
|
|
||||||
@@ -151,9 +153,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkRenderPass CreateDefaultRenderPass(VkAttachmentLoadOp loadOp);
|
VkRenderPass CreateDefaultRenderPass(VkAttachmentLoadOp loadOp);
|
||||||
void CreateDefaultFramebuffers();
|
void CreateDefaultFramebuffers();
|
||||||
void PrepareDemoPipeline();
|
void PrepareDemoPipeline();
|
||||||
VkPipeline CreateGraphicsPipeline(const VkPipelineVertexInputStateCreateInfo& vertexInputState) const;
|
VkPipeline GetOrCreatePipeline(Uint64 programHash, Uint64 vertexInputHash,
|
||||||
VkPipeline GetOrCreatePipelineVariant(Uint64 hash, const VkPipelineVertexInputStateCreateInfo& vertexInputState);
|
const VkPipelineVertexInputStateCreateInfo& vertexInputState);
|
||||||
void DestroyPipelineVariants();
|
|
||||||
void TransitionSwapchainImageToColorAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
void TransitionSwapchainImageToColorAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
||||||
void TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
void TransitionDepthStencilImageToAttachment(VkCommandBuffer commandBuffer, Uint32 imageIndex);
|
||||||
void RecordColorClear(VkCommandBuffer commandBuffer, const VkClearColorValue& clearColor);
|
void RecordColorClear(VkCommandBuffer commandBuffer, const VkClearColorValue& clearColor);
|
||||||
|
|||||||
Reference in New Issue
Block a user