[Improvement] (MG_Backend/DirectVulkan): split TextureSamplerManager into TextureManager and SamplerManager

This commit is contained in:
2026-02-24 15:19:34 +08:00
parent e16c0645c0
commit a757669df5
9 changed files with 295 additions and 220 deletions
+2 -1
View File
@@ -227,7 +227,8 @@ set(SOURCE_FILES
MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp
MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderTargetManager.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderTargetManager.cpp
MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp
MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp
MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.cpp
MobileGL/MG_State/GLState/Core.cpp MobileGL/MG_State/GLState/Core.cpp
MobileGL/MG_State/GLState/ErrorState/Error.cpp MobileGL/MG_State/GLState/ErrorState/Error.cpp
@@ -138,7 +138,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool UniformDescriptorBinder::Initialize(VkDevice device, VmaAllocator allocator, Bool UniformDescriptorBinder::Initialize(VkDevice device, VmaAllocator allocator,
VkDeviceSize minUniformBufferOffsetAlignment, Uint32 frameCount, VkDeviceSize minUniformBufferOffsetAlignment, Uint32 frameCount,
Uint32 maxBindings, Uint32 setsPerFrame, VkDeviceSize perFrameUploadBytes, Uint32 maxBindings, Uint32 setsPerFrame, VkDeviceSize perFrameUploadBytes,
VkTextureSamplerManager* textureSamplerManager, VkTextureManager* textureManager, VkSamplerManager* samplerManager,
VkRenderTargetManager* framebufferManager) { VkRenderTargetManager* framebufferManager) {
Shutdown(); Shutdown();
@@ -147,8 +147,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MOBILEGL_ASSERT(frameCount > 0, "UniformDescriptorBinder::Initialize requires frameCount > 0"); MOBILEGL_ASSERT(frameCount > 0, "UniformDescriptorBinder::Initialize requires frameCount > 0");
MOBILEGL_ASSERT(maxBindings > 0, "UniformDescriptorBinder::Initialize requires maxBindings > 0"); MOBILEGL_ASSERT(maxBindings > 0, "UniformDescriptorBinder::Initialize requires maxBindings > 0");
MOBILEGL_ASSERT(setsPerFrame > 0, "UniformDescriptorBinder::Initialize requires setsPerFrame > 0"); MOBILEGL_ASSERT(setsPerFrame > 0, "UniformDescriptorBinder::Initialize requires setsPerFrame > 0");
MOBILEGL_ASSERT(textureSamplerManager != nullptr, MOBILEGL_ASSERT(textureManager != nullptr,
"UniformDescriptorBinder::Initialize requires valid texture sampler manager"); "UniformDescriptorBinder::Initialize requires valid texture manager");
MOBILEGL_ASSERT(samplerManager != nullptr,
"UniformDescriptorBinder::Initialize requires valid sampler manager");
MOBILEGL_ASSERT(framebufferManager != nullptr, MOBILEGL_ASSERT(framebufferManager != nullptr,
"UniformDescriptorBinder::Initialize requires valid framebuffer manager"); "UniformDescriptorBinder::Initialize requires valid framebuffer manager");
@@ -160,7 +162,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_maxBindings = maxBindings; m_maxBindings = maxBindings;
m_setsPerFrame = setsPerFrame; m_setsPerFrame = setsPerFrame;
m_peakDescriptorSetsObserved = 0; m_peakDescriptorSetsObserved = 0;
m_textureSamplerManager = textureSamplerManager; m_textureManager = textureManager;
m_samplerManager = samplerManager;
m_framebufferManager = framebufferManager; m_framebufferManager = framebufferManager;
m_frames.resize(m_frameCount); m_frames.resize(m_frameCount);
@@ -223,7 +226,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_maxBindings = 0; m_maxBindings = 0;
m_setsPerFrame = 0; m_setsPerFrame = 0;
m_peakDescriptorSetsObserved = 0; m_peakDescriptorSetsObserved = 0;
m_textureSamplerManager = nullptr; m_textureManager = nullptr;
m_samplerManager = nullptr;
m_framebufferManager = nullptr; m_framebufferManager = nullptr;
} }
@@ -447,7 +451,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const MG_State::GLState::ProgramObject& program, const MG_State::GLState::ProgramObject& program,
const ProgramLayout& layout, Uint32 binding, const ProgramLayout& layout, Uint32 binding,
VkDescriptorImageInfo& outImageInfo) const { VkDescriptorImageInfo& outImageInfo) const {
MOBILEGL_ASSERT(m_textureSamplerManager != nullptr, "ResolveSamplerDescriptor: texture sampler manager is null"); MOBILEGL_ASSERT(m_textureManager != nullptr, "ResolveSamplerDescriptor: texture manager is null");
MOBILEGL_ASSERT(m_samplerManager != nullptr, "ResolveSamplerDescriptor: sampler manager is null");
if (!MG_State::pGLContext || binding >= layout.samplerUniformLocationByBinding.size()) { if (!MG_State::pGLContext || binding >= layout.samplerUniformLocationByBinding.size()) {
return false; return false;
} }
@@ -480,6 +485,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return false; return false;
} }
const MG_State::GLState::SamplerObject* samplerToUse = samplerOverride ? samplerOverride.get() : nullptr;
if (!samplerToUse) {
auto textureSampler = texture->GetSamplerObject();
if (textureSampler) {
samplerToUse = textureSampler.get();
}
}
if (!samplerToUse) {
return false;
}
if (m_framebufferManager->Transition(commandBuffer, if (m_framebufferManager->Transition(commandBuffer,
VkRenderTargetManager::TransitionResource::OffscreenColorTexture, VkRenderTargetManager::TransitionResource::OffscreenColorTexture,
VkRenderTargetManager::TransitionUsage::ShaderRead, VkRenderTargetManager::TransitionUsage::ShaderRead,
@@ -488,7 +504,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (m_framebufferManager->GetOffscreenColorViewByTexture(texture->GetExternalIndex(), offscreenView) && if (m_framebufferManager->GetOffscreenColorViewByTexture(texture->GetExternalIndex(), offscreenView) &&
offscreenView != VK_NULL_HANDLE) { offscreenView != VK_NULL_HANDLE) {
VkDescriptorImageInfo sampledInfo{}; VkDescriptorImageInfo sampledInfo{};
if (!m_textureSamplerManager->SyncTextureAndGetDescriptor(*texture, samplerOverride.get(), sampledInfo)) { if (!m_textureManager->SyncTextureAndGetDescriptor(*texture, sampledInfo)) {
return false;
}
sampledInfo.sampler = m_samplerManager->GetOrCreateSampler(*samplerToUse);
if (sampledInfo.sampler == VK_NULL_HANDLE) {
return false; return false;
} }
sampledInfo.imageView = offscreenView; sampledInfo.imageView = offscreenView;
@@ -498,7 +518,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
} }
return m_textureSamplerManager->SyncTextureAndGetDescriptor(*texture, samplerOverride.get(), outImageInfo); if (!m_textureManager->SyncTextureAndGetDescriptor(*texture, outImageInfo)) {
return false;
}
outImageInfo.sampler = m_samplerManager->GetOrCreateSampler(*samplerToUse);
return outImageInfo.sampler != VK_NULL_HANDLE;
} }
UniformDescriptorBinder::ProgramLayout* UniformDescriptorBinder::GetOrCreateProgramLayout( UniformDescriptorBinder::ProgramLayout* UniformDescriptorBinder::GetOrCreateProgramLayout(
@@ -767,8 +791,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
static const Uint8 kFallbackData[16] = {}; static const Uint8 kFallbackData[16] = {};
MOBILEGL_ASSERT(m_textureSamplerManager != nullptr, MOBILEGL_ASSERT(m_textureManager != nullptr, "BindProgramUniformBuffers: texture manager is null");
"BindProgramUniformBuffers: texture sampler manager is null"); MOBILEGL_ASSERT(m_samplerManager != nullptr, "BindProgramUniformBuffers: sampler manager is null");
Vector<VkWriteDescriptorSet> writes; Vector<VkWriteDescriptorSet> writes;
writes.reserve(m_maxBindings); writes.reserve(m_maxBindings);
@@ -9,7 +9,8 @@
#pragma once #pragma once
#include "VkBufferObject.h" #include "VkBufferObject.h"
#include "VkTextureSamplerManager.h" #include "VkSamplerManager.h"
#include "VkTextureManager.h"
#include "../VkIncludes.h" #include "../VkIncludes.h"
#include <Includes.h> #include <Includes.h>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
@@ -32,7 +33,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool Initialize(VkDevice device, VmaAllocator allocator, VkDeviceSize minUniformBufferOffsetAlignment, Bool Initialize(VkDevice device, VmaAllocator allocator, VkDeviceSize minUniformBufferOffsetAlignment,
Uint32 frameCount, Uint32 maxBindings = 16, Uint32 setsPerFrame = 64, Uint32 frameCount, Uint32 maxBindings = 16, Uint32 setsPerFrame = 64,
VkDeviceSize perFrameUploadBytes = 4 * 1024 * 1024, VkDeviceSize perFrameUploadBytes = 4 * 1024 * 1024,
VkTextureSamplerManager* textureSamplerManager = nullptr, VkTextureManager* textureManager = nullptr, VkSamplerManager* samplerManager = nullptr,
VkRenderTargetManager* framebufferManager = nullptr); VkRenderTargetManager* framebufferManager = nullptr);
void Shutdown(); void Shutdown();
@@ -97,7 +98,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Uint32 m_maxBindings = 0; Uint32 m_maxBindings = 0;
Uint32 m_setsPerFrame = 0; Uint32 m_setsPerFrame = 0;
Uint32 m_peakDescriptorSetsObserved = 0; Uint32 m_peakDescriptorSetsObserved = 0;
VkTextureSamplerManager* m_textureSamplerManager = nullptr; VkTextureManager* m_textureManager = nullptr;
VkSamplerManager* m_samplerManager = nullptr;
VkRenderTargetManager* m_framebufferManager = nullptr; VkRenderTargetManager* m_framebufferManager = nullptr;
}; };
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -0,0 +1,156 @@
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.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 "VkSamplerManager.h"
#include "MG_State/GLState/Core.h"
namespace MobileGL::MG_Backend::DirectVulkan {
Bool VkSamplerManager::Initialize(const InitInfo& initInfo) {
Shutdown();
m_device = initInfo.device;
m_config = initInfo.config;
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE && m_config != nullptr,
"VkSamplerManager::Initialize failed: invalid initialization info");
return true;
}
void VkSamplerManager::Shutdown() {
for (auto& [_, sampler] : m_samplers) {
if (m_device != VK_NULL_HANDLE && sampler.handle != VK_NULL_HANDLE) {
vkDestroySampler(m_device, sampler.handle, nullptr);
}
sampler.handle = VK_NULL_HANDLE;
}
m_samplers.clear();
m_device = VK_NULL_HANDLE;
m_config = nullptr;
}
Uint64 VkSamplerManager::BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler) const {
MOBILEGL_ASSERT(m_config != nullptr, "VkSamplerManager::BuildSamplerKey: m_config is null");
XXHASH_VERIFY(XXH64_reset(m_hashState, m_config->CacheVersion));
const auto minFilter = sampler.GetMinFilter();
XXHASH_VERIFY(XXH64_update(m_hashState, &minFilter, sizeof(minFilter)));
const auto magFilter = sampler.GetMagFilter();
XXHASH_VERIFY(XXH64_update(m_hashState, &magFilter, sizeof(magFilter)));
const auto mipmapMode = sampler.GetMipmapMode();
XXHASH_VERIFY(XXH64_update(m_hashState, &mipmapMode, sizeof(mipmapMode)));
const auto wrapS = sampler.GetWrapS();
XXHASH_VERIFY(XXH64_update(m_hashState, &wrapS, sizeof(wrapS)));
const auto wrapT = sampler.GetWrapT();
XXHASH_VERIFY(XXH64_update(m_hashState, &wrapT, sizeof(wrapT)));
const auto wrapR = sampler.GetWrapR();
XXHASH_VERIFY(XXH64_update(m_hashState, &wrapR, sizeof(wrapR)));
const auto minLod = sampler.GetMinLod();
XXHASH_VERIFY(XXH64_update(m_hashState, &minLod, sizeof(minLod)));
const auto maxLod = sampler.GetMaxLod();
XXHASH_VERIFY(XXH64_update(m_hashState, &maxLod, sizeof(maxLod)));
const auto lodBias = sampler.GetLodBias();
XXHASH_VERIFY(XXH64_update(m_hashState, &lodBias, sizeof(lodBias)));
const auto compareMode = sampler.GetCompareMode();
XXHASH_VERIFY(XXH64_update(m_hashState, &compareMode, sizeof(compareMode)));
const auto compareFunc = sampler.GetSamplerCompareFunc();
XXHASH_VERIFY(XXH64_update(m_hashState, &compareFunc, sizeof(compareFunc)));
return XXH64_digest(m_hashState);
}
VkSampler VkSamplerManager::GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler) {
const Uint64 key = BuildSamplerKey(sampler);
auto it = m_samplers.find(key);
if (it != m_samplers.end()) {
return it->second.handle;
}
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = ToVkFilter(sampler.GetMagFilter());
samplerInfo.minFilter = ToVkFilter(sampler.GetMinFilter());
samplerInfo.mipmapMode = ToVkMipmapMode(sampler.GetMipmapMode());
samplerInfo.addressModeU = ToVkAddressMode(sampler.GetWrapS());
samplerInfo.addressModeV = ToVkAddressMode(sampler.GetWrapT());
samplerInfo.addressModeW = ToVkAddressMode(sampler.GetWrapR());
samplerInfo.mipLodBias = sampler.GetLodBias();
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.compareEnable = sampler.GetCompareMode() == SamplerCompareMode::CompareToTexture ? VK_TRUE : VK_FALSE;
samplerInfo.compareOp = ToVkCompareOp(sampler.GetSamplerCompareFunc());
samplerInfo.minLod = sampler.GetMinLod();
samplerInfo.maxLod = sampler.GetMaxLod();
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
VkSampler vkSampler = VK_NULL_HANDLE;
VK_VERIFY(vkCreateSampler(m_device, &samplerInfo, nullptr, &vkSampler), "vkCreateSampler(texture)");
SamplerCacheEntry entry{};
entry.handle = vkSampler;
entry.externalIndex = sampler.GetExternalIndex();
entry.version = sampler.GetVersion();
m_samplers[key] = entry;
return vkSampler;
}
VkFilter VkSamplerManager::ToVkFilter(SamplerFilterMode mode) {
return mode == SamplerFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
}
VkSamplerMipmapMode VkSamplerManager::ToVkMipmapMode(SamplerMipmapMode mode) {
switch (mode) {
case SamplerMipmapMode::Nearest:
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
case SamplerMipmapMode::Linear:
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
case SamplerMipmapMode::None:
default:
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
}
}
VkSamplerAddressMode VkSamplerManager::ToVkAddressMode(SamplerWrapMode mode) {
switch (mode) {
case SamplerWrapMode::ClampToEdge:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case SamplerWrapMode::MirroredRepeat:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case SamplerWrapMode::Repeat:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case SamplerWrapMode::ClampToBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case SamplerWrapMode::MirrorClampToEdge:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
default:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
}
}
VkCompareOp VkSamplerManager::ToVkCompareOp(SamplerCompareFunc func) {
switch (func) {
case SamplerCompareFunc::Never:
return VK_COMPARE_OP_NEVER;
case SamplerCompareFunc::Less:
return VK_COMPARE_OP_LESS;
case SamplerCompareFunc::Equal:
return VK_COMPARE_OP_EQUAL;
case SamplerCompareFunc::LessEqual:
return VK_COMPARE_OP_LESS_OR_EQUAL;
case SamplerCompareFunc::Greater:
return VK_COMPARE_OP_GREATER;
case SamplerCompareFunc::NotEqual:
return VK_COMPARE_OP_NOT_EQUAL;
case SamplerCompareFunc::GreaterEqual:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
case SamplerCompareFunc::Always:
default:
return VK_COMPARE_OP_ALWAYS;
}
}
} // namespace MobileGL::MG_Backend::DirectVulkan
@@ -0,0 +1,51 @@
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkSamplerManager.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 "../VulkanRendererConfig.h"
#include <Includes.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h>
namespace MobileGL::MG_State::GLState {
class SamplerObject;
}
namespace MobileGL::MG_Backend::DirectVulkan {
class VkSamplerManager {
public:
struct InitInfo {
VkDevice device = VK_NULL_HANDLE;
const VulkanRendererConfig* config = nullptr;
};
Bool Initialize(const InitInfo& initInfo);
void Shutdown();
VkSampler GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler);
private:
struct SamplerCacheEntry {
VkSampler handle = VK_NULL_HANDLE;
Uint externalIndex = 0;
Uint16 version = 0;
};
Uint64 BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler) const;
static VkFilter ToVkFilter(SamplerFilterMode mode);
static VkSamplerMipmapMode ToVkMipmapMode(SamplerMipmapMode mode);
static VkSamplerAddressMode ToVkAddressMode(SamplerWrapMode mode);
static VkCompareOp ToVkCompareOp(SamplerCompareFunc func);
VkDevice m_device = VK_NULL_HANDLE;
const VulkanRendererConfig* m_config = nullptr;
UnorderedMap<Uint64, SamplerCacheEntry> m_samplers;
static inline XXH64_state_t* m_hashState = XXH64_createState();
};
} // namespace MobileGL::MG_Backend::DirectVulkan
@@ -1,4 +1,4 @@
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp // MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp
// Copyright (c) 2025-2026 MobileGL-Dev // Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0: // Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt // https://www.gnu.org/licenses/gpl-3.0.txt
@@ -6,12 +6,12 @@
// SPDX-License-Identifier: LGPL-3.0-only // SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header // End of Source File Header
#include "VkTextureSamplerManager.h" #include "VkTextureManager.h"
#include "MG_State/GLState/Core.h" #include "MG_State/GLState/Core.h"
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
Bool VkTextureSamplerManager::Initialize(const InitInfo& initInfo) { Bool VkTextureManager::Initialize(const InitInfo& initInfo) {
Shutdown(); Shutdown();
m_device = initInfo.device; m_device = initInfo.device;
@@ -19,39 +19,28 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_allocator = initInfo.allocator; m_allocator = initInfo.allocator;
m_commandPool = initInfo.commandPool; m_commandPool = initInfo.commandPool;
m_graphicsQueue = initInfo.graphicsQueue; m_graphicsQueue = initInfo.graphicsQueue;
m_config = initInfo.config;
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE && m_physicalDevice != VK_NULL_HANDLE && m_allocator != nullptr && MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE && m_physicalDevice != VK_NULL_HANDLE && m_allocator != nullptr &&
m_commandPool != VK_NULL_HANDLE && m_graphicsQueue != VK_NULL_HANDLE && m_config != nullptr, m_commandPool != VK_NULL_HANDLE && m_graphicsQueue != VK_NULL_HANDLE,
"VkTextureSamplerManager::Initialize failed: invalid initialization info"); "VkTextureManager::Initialize failed: invalid initialization info");
return true; return true;
} }
void VkTextureSamplerManager::Shutdown() { void VkTextureManager::Shutdown() {
for (auto& [_, resource] : m_textureResources) { for (auto& [_, resource] : m_textureResources) {
DestroyTextureResource(resource); DestroyTextureResource(resource);
} }
m_textureResources.clear(); m_textureResources.clear();
for (auto& [_, sampler] : m_samplers) {
if (m_device != VK_NULL_HANDLE && sampler.handle != VK_NULL_HANDLE) {
vkDestroySampler(m_device, sampler.handle, nullptr);
}
sampler.handle = VK_NULL_HANDLE;
}
m_samplers.clear();
m_device = VK_NULL_HANDLE; m_device = VK_NULL_HANDLE;
m_physicalDevice = VK_NULL_HANDLE; m_physicalDevice = VK_NULL_HANDLE;
m_allocator = nullptr; m_allocator = nullptr;
m_commandPool = VK_NULL_HANDLE; m_commandPool = VK_NULL_HANDLE;
m_graphicsQueue = VK_NULL_HANDLE; m_graphicsQueue = VK_NULL_HANDLE;
m_config = nullptr;
} }
Bool VkTextureSamplerManager::SyncTextureAndGetDescriptor(const MG_State::GLState::ITextureObject& texture, Bool VkTextureManager::SyncTextureAndGetDescriptor(const MG_State::GLState::ITextureObject& texture,
const MG_State::GLState::SamplerObject* samplerOverride,
VkDescriptorImageInfo& outImageInfo) { VkDescriptorImageInfo& outImageInfo) {
MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE"); MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE, "SyncTextureAndGetDescriptor: m_device == VK_NULL_HANDLE");
@@ -67,30 +56,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return false; return false;
} }
const MG_State::GLState::SamplerObject* samplerToUse = samplerOverride; if (it->second.view == VK_NULL_HANDLE) {
if (!samplerToUse) {
auto textureSampler = texture.GetSamplerObject();
if (textureSampler) {
samplerToUse = textureSampler.get();
}
}
VkSampler sampler = VK_NULL_HANDLE;
if (samplerToUse) {
sampler = GetOrCreateSampler(*samplerToUse);
}
if (it->second.view == VK_NULL_HANDLE || sampler == VK_NULL_HANDLE) {
return false; return false;
} }
outImageInfo.sampler = sampler; outImageInfo.sampler = VK_NULL_HANDLE;
outImageInfo.imageView = it->second.view; outImageInfo.imageView = it->second.view;
outImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; outImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
return true; return true;
} }
Bool VkTextureSamplerManager::EnsureTextureSynced(TextureResource& resource, Bool VkTextureManager::EnsureTextureSynced(TextureResource& resource, const MG_State::GLState::ITextureObject& texture) {
const MG_State::GLState::ITextureObject& texture) {
TextureUploadTarget level0Target = TextureUploadTarget::Unknown; TextureUploadTarget level0Target = TextureUploadTarget::Unknown;
IntVec3 texelSize{0, 0, 0}; IntVec3 texelSize{0, 0, 0};
SizeT byteSize = 0; SizeT byteSize = 0;
@@ -120,8 +96,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
Bool VkTextureSamplerManager::EnsureTextureResource(TextureResource& resource, Bool VkTextureManager::EnsureTextureResource(TextureResource& resource, const MG_State::GLState::ITextureObject& texture,
const MG_State::GLState::ITextureObject& texture,
TextureUploadTarget level0Target, const IntVec3& texelSize, TextureUploadTarget level0Target, const IntVec3& texelSize,
SizeT byteSize) { SizeT byteSize) {
const VkFormat format = ResolveTextureFormat(texture.GetFormat()); const VkFormat format = ResolveTextureFormat(texture.GetFormat());
@@ -183,8 +158,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
Bool VkTextureSamplerManager::UploadLevel0(TextureResource& resource, Bool VkTextureManager::UploadLevel0(TextureResource& resource, const MG_State::GLState::TextureObjectMipmap& mipmapTexture,
const MG_State::GLState::TextureObjectMipmap& mipmapTexture,
TextureUploadTarget level0Target, SizeT byteSize) { TextureUploadTarget level0Target, SizeT byteSize) {
auto& mutableTexture = const_cast<MG_State::GLState::TextureObjectMipmap&>(mipmapTexture); auto& mutableTexture = const_cast<MG_State::GLState::TextureObjectMipmap&>(mipmapTexture);
const void* source = mutableTexture.MapMipmapData(level0Target, 0); const void* source = mutableTexture.MapMipmapData(level0Target, 0);
@@ -270,7 +244,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
Bool VkTextureSamplerManager::ExecuteImmediate(const std::function<void(VkCommandBuffer)>& recorder) const { Bool VkTextureManager::ExecuteImmediate(const std::function<void(VkCommandBuffer)>& recorder) const {
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = m_commandPool; allocInfo.commandPool = m_commandPool;
@@ -300,7 +274,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
void VkTextureSamplerManager::DestroyTextureResource(TextureResource& resource) const { void VkTextureManager::DestroyTextureResource(TextureResource& resource) const {
if (m_device != VK_NULL_HANDLE && resource.view != VK_NULL_HANDLE) { if (m_device != VK_NULL_HANDLE && resource.view != VK_NULL_HANDLE) {
vkDestroyImageView(m_device, resource.view, nullptr); vkDestroyImageView(m_device, resource.view, nullptr);
} }
@@ -315,9 +289,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
resource.format = VK_FORMAT_UNDEFINED; resource.format = VK_FORMAT_UNDEFINED;
} }
Bool VkTextureSamplerManager::ResolveLevel0(const MG_State::GLState::ITextureObject& texture, Bool VkTextureManager::ResolveLevel0(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget,
TextureUploadTarget& outTarget, IntVec3& outTexelSize, IntVec3& outTexelSize, SizeT& outByteSize) {
SizeT& outByteSize) {
const auto* mipTexture = dynamic_cast<const MG_State::GLState::TextureObjectMipmap*>(&texture); const auto* mipTexture = dynamic_cast<const MG_State::GLState::TextureObjectMipmap*>(&texture);
if (!mipTexture) { if (!mipTexture) {
return false; return false;
@@ -332,7 +305,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return outTexelSize.x() > 0 && outTexelSize.y() > 0 && outByteSize > 0; return outTexelSize.x() > 0 && outTexelSize.y() > 0 && outByteSize > 0;
} }
VkFormat VkTextureSamplerManager::ResolveTextureFormat(TextureInternalFormat format) { VkFormat VkTextureManager::ResolveTextureFormat(TextureInternalFormat format) {
switch (format) { switch (format) {
case TextureInternalFormat::RGBA: case TextureInternalFormat::RGBA:
case TextureInternalFormat::RGBA8: case TextureInternalFormat::RGBA8:
@@ -343,125 +316,4 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return VK_FORMAT_UNDEFINED; return VK_FORMAT_UNDEFINED;
} }
} }
Uint64 VkTextureSamplerManager::BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler) const {
MOBILEGL_ASSERT(m_config != nullptr, "VkTextureSamplerManager::BuildSamplerKey: m_config is null");
XXHASH_VERIFY(XXH64_reset(m_hashState, m_config->CacheVersion));
const auto minFilter = sampler.GetMinFilter();
XXHASH_VERIFY(XXH64_update(m_hashState, &minFilter, sizeof(minFilter)));
const auto magFilter = sampler.GetMagFilter();
XXHASH_VERIFY(XXH64_update(m_hashState, &magFilter, sizeof(magFilter)));
const auto mipmapMode = sampler.GetMipmapMode();
XXHASH_VERIFY(XXH64_update(m_hashState, &mipmapMode, sizeof(mipmapMode)));
const auto wrapS = sampler.GetWrapS();
XXHASH_VERIFY(XXH64_update(m_hashState, &wrapS, sizeof(wrapS)));
const auto wrapT = sampler.GetWrapT();
XXHASH_VERIFY(XXH64_update(m_hashState, &wrapT, sizeof(wrapT)));
const auto wrapR = sampler.GetWrapR();
XXHASH_VERIFY(XXH64_update(m_hashState, &wrapR, sizeof(wrapR)));
const auto minLod = sampler.GetMinLod();
XXHASH_VERIFY(XXH64_update(m_hashState, &minLod, sizeof(minLod)));
const auto maxLod = sampler.GetMaxLod();
XXHASH_VERIFY(XXH64_update(m_hashState, &maxLod, sizeof(maxLod)));
const auto lodBias = sampler.GetLodBias();
XXHASH_VERIFY(XXH64_update(m_hashState, &lodBias, sizeof(lodBias)));
const auto compareMode = sampler.GetCompareMode();
XXHASH_VERIFY(XXH64_update(m_hashState, &compareMode, sizeof(compareMode)));
const auto compareFunc = sampler.GetSamplerCompareFunc();
XXHASH_VERIFY(XXH64_update(m_hashState, &compareFunc, sizeof(compareFunc)));
return XXH64_digest(m_hashState);
}
VkSampler VkTextureSamplerManager::GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler) {
const Uint64 key = BuildSamplerKey(sampler);
auto it = m_samplers.find(key);
if (it != m_samplers.end()) {
return it->second.handle;
}
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = ToVkFilter(sampler.GetMagFilter());
samplerInfo.minFilter = ToVkFilter(sampler.GetMinFilter());
samplerInfo.mipmapMode = ToVkMipmapMode(sampler.GetMipmapMode());
samplerInfo.addressModeU = ToVkAddressMode(sampler.GetWrapS());
samplerInfo.addressModeV = ToVkAddressMode(sampler.GetWrapT());
samplerInfo.addressModeW = ToVkAddressMode(sampler.GetWrapR());
samplerInfo.mipLodBias = sampler.GetLodBias();
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.compareEnable = sampler.GetCompareMode() == SamplerCompareMode::CompareToTexture ? VK_TRUE : VK_FALSE;
samplerInfo.compareOp = ToVkCompareOp(sampler.GetSamplerCompareFunc());
samplerInfo.minLod = sampler.GetMinLod();
samplerInfo.maxLod = sampler.GetMaxLod();
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
VkSampler vkSampler = VK_NULL_HANDLE;
VK_VERIFY(vkCreateSampler(m_device, &samplerInfo, nullptr, &vkSampler), "vkCreateSampler(texture)");
SamplerCacheEntry entry{};
entry.handle = vkSampler;
entry.externalIndex = sampler.GetExternalIndex();
entry.version = sampler.GetVersion();
m_samplers[key] = entry;
return vkSampler;
}
VkFilter VkTextureSamplerManager::ToVkFilter(SamplerFilterMode mode) {
return mode == SamplerFilterMode::Nearest ? VK_FILTER_NEAREST : VK_FILTER_LINEAR;
}
VkSamplerMipmapMode VkTextureSamplerManager::ToVkMipmapMode(SamplerMipmapMode mode) {
switch (mode) {
case SamplerMipmapMode::Nearest:
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
case SamplerMipmapMode::Linear:
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
case SamplerMipmapMode::None:
default:
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
}
}
VkSamplerAddressMode VkTextureSamplerManager::ToVkAddressMode(SamplerWrapMode mode) {
switch (mode) {
case SamplerWrapMode::ClampToEdge:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case SamplerWrapMode::MirroredRepeat:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case SamplerWrapMode::Repeat:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case SamplerWrapMode::ClampToBorder:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case SamplerWrapMode::MirrorClampToEdge:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
default:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
}
}
VkCompareOp VkTextureSamplerManager::ToVkCompareOp(SamplerCompareFunc func) {
switch (func) {
case SamplerCompareFunc::Never:
return VK_COMPARE_OP_NEVER;
case SamplerCompareFunc::Less:
return VK_COMPARE_OP_LESS;
case SamplerCompareFunc::Equal:
return VK_COMPARE_OP_EQUAL;
case SamplerCompareFunc::LessEqual:
return VK_COMPARE_OP_LESS_OR_EQUAL;
case SamplerCompareFunc::Greater:
return VK_COMPARE_OP_GREATER;
case SamplerCompareFunc::NotEqual:
return VK_COMPARE_OP_NOT_EQUAL;
case SamplerCompareFunc::GreaterEqual:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
case SamplerCompareFunc::Always:
default:
return VK_COMPARE_OP_ALWAYS;
}
}
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -1,4 +1,4 @@
// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.h // MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.h
// Copyright (c) 2025-2026 MobileGL-Dev // Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0: // Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt // https://www.gnu.org/licenses/gpl-3.0.txt
@@ -9,19 +9,16 @@
#pragma once #pragma once
#include "../VkIncludes.h" #include "../VkIncludes.h"
#include "../VulkanRendererConfig.h"
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h>
#include <MG_State/GLState/TextureState/TextureObject.h> #include <MG_State/GLState/TextureState/TextureObject.h>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
namespace MobileGL::MG_State::GLState { namespace MobileGL::MG_State::GLState {
class ITextureObject; class ITextureObject;
class SamplerObject;
} }
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
class VkTextureSamplerManager { class VkTextureManager {
public: public:
struct InitInfo { struct InitInfo {
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
@@ -29,15 +26,12 @@ public:
VmaAllocator allocator = nullptr; VmaAllocator allocator = nullptr;
VkCommandPool commandPool = VK_NULL_HANDLE; VkCommandPool commandPool = VK_NULL_HANDLE;
VkQueue graphicsQueue = VK_NULL_HANDLE; VkQueue graphicsQueue = VK_NULL_HANDLE;
const VulkanRendererConfig* config = nullptr;
}; };
Bool Initialize(const InitInfo& initInfo); Bool Initialize(const InitInfo& initInfo);
void Shutdown(); void Shutdown();
Bool SyncTextureAndGetDescriptor(const MG_State::GLState::ITextureObject& texture, Bool SyncTextureAndGetDescriptor(const MG_State::GLState::ITextureObject& texture, VkDescriptorImageInfo& outImageInfo);
const MG_State::GLState::SamplerObject* samplerOverride,
VkDescriptorImageInfo& outImageInfo);
private: private:
struct TextureResource { struct TextureResource {
@@ -50,12 +44,6 @@ private:
Uint textureExternalIndex = 0; Uint textureExternalIndex = 0;
}; };
struct SamplerCacheEntry {
VkSampler handle = VK_NULL_HANDLE;
Uint externalIndex = 0;
Uint16 version = 0;
};
Bool EnsureTextureSynced(TextureResource& resource, const MG_State::GLState::ITextureObject& texture); Bool EnsureTextureSynced(TextureResource& resource, const MG_State::GLState::ITextureObject& texture);
Bool EnsureTextureResource(TextureResource& resource, const MG_State::GLState::ITextureObject& texture, Bool EnsureTextureResource(TextureResource& resource, const MG_State::GLState::ITextureObject& texture,
TextureUploadTarget level0Target, const IntVec3& texelSize, SizeT byteSize); TextureUploadTarget level0Target, const IntVec3& texelSize, SizeT byteSize);
@@ -66,23 +54,13 @@ private:
static Bool ResolveLevel0(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget, static Bool ResolveLevel0(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget,
IntVec3& outTexelSize, SizeT& outByteSize); IntVec3& outTexelSize, SizeT& outByteSize);
static VkFormat ResolveTextureFormat(TextureInternalFormat format); static VkFormat ResolveTextureFormat(TextureInternalFormat format);
Uint64 BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler) const;
VkSampler GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler);
static VkFilter ToVkFilter(SamplerFilterMode mode);
static VkSamplerMipmapMode ToVkMipmapMode(SamplerMipmapMode mode);
static VkSamplerAddressMode ToVkAddressMode(SamplerWrapMode mode);
static VkCompareOp ToVkCompareOp(SamplerCompareFunc func);
VkDevice m_device = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
VmaAllocator m_allocator = nullptr; VmaAllocator m_allocator = nullptr;
VkCommandPool m_commandPool = VK_NULL_HANDLE; VkCommandPool m_commandPool = VK_NULL_HANDLE;
VkQueue m_graphicsQueue = VK_NULL_HANDLE; VkQueue m_graphicsQueue = VK_NULL_HANDLE;
const VulkanRendererConfig* m_config = nullptr;
UnorderedMap<Uint, TextureResource> m_textureResources; UnorderedMap<Uint, TextureResource> m_textureResources;
UnorderedMap<Uint64, SamplerCacheEntry> m_samplers;
static inline XXH64_state_t* m_hashState = XXH64_createState();
}; };
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -214,13 +214,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MOBILEGL_ASSERT(m_pipelineFactory != nullptr, "PipelineFactory creation failed."); MOBILEGL_ASSERT(m_pipelineFactory != nullptr, "PipelineFactory creation failed.");
m_programFactory = MakeUnique<ProgramFactory>(m_device, m_config); m_programFactory = MakeUnique<ProgramFactory>(m_device, m_config);
MOBILEGL_ASSERT(m_programFactory != nullptr, "ProgramFactory creation failed."); MOBILEGL_ASSERT(m_programFactory != nullptr, "ProgramFactory creation failed.");
m_textureSamplerManager = MakeUnique<VkTextureSamplerManager>(); m_textureManager = MakeUnique<VkTextureManager>();
MOBILEGL_ASSERT(m_textureSamplerManager != nullptr, "VkTextureSamplerManager creation failed."); MOBILEGL_ASSERT(m_textureManager != nullptr, "VkTextureManager creation failed.");
auto succeeded = false; auto succeeded = false;
succeeded = succeeded = m_textureManager->Initialize(
m_textureSamplerManager->Initialize({m_device, m_physicalDevice.handle, m_allocator, m_commandPool, m_graphicsQueue, {m_device, m_physicalDevice.handle, m_allocator, m_commandPool, m_graphicsQueue});
&m_config}); MOBILEGL_ASSERT(succeeded, "VkTextureManager initialization failed.");
MOBILEGL_ASSERT(succeeded, "VkTextureSamplerManager initialization failed.");
m_samplerManager = MakeUnique<VkSamplerManager>();
MOBILEGL_ASSERT(m_samplerManager != nullptr, "VkSamplerManager creation failed.");
succeeded = m_samplerManager->Initialize({m_device, &m_config});
MOBILEGL_ASSERT(succeeded, "VkSamplerManager initialization failed.");
m_framebufferManager = MakeUnique<VkRenderTargetManager>(); m_framebufferManager = MakeUnique<VkRenderTargetManager>();
MOBILEGL_ASSERT(m_framebufferManager != nullptr, "VkFramebufferManager creation failed."); MOBILEGL_ASSERT(m_framebufferManager != nullptr, "VkFramebufferManager creation failed.");
@@ -232,7 +236,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
succeeded = m_uniformDescriptorBinder->Initialize(m_device, m_allocator, succeeded = m_uniformDescriptorBinder->Initialize(m_device, m_allocator,
m_physicalDevice.properties.limits.minUniformBufferOffsetAlignment, m_physicalDevice.properties.limits.minUniformBufferOffsetAlignment,
m_config.MaxFramesInFlight, 16, 64, 4 * 1024 * 1024, m_config.MaxFramesInFlight, 16, 64, 4 * 1024 * 1024,
m_textureSamplerManager.get(), m_framebufferManager.get()); m_textureManager.get(), m_samplerManager.get(),
m_framebufferManager.get());
MOBILEGL_ASSERT(succeeded, "UniformDescriptorBinder initialization failed."); MOBILEGL_ASSERT(succeeded, "UniformDescriptorBinder initialization failed.");
m_vertexInputStateFactory = MakeUnique<VertexInputStateFactory>(m_config); m_vertexInputStateFactory = MakeUnique<VertexInputStateFactory>(m_config);
MOBILEGL_ASSERT(m_vertexInputStateFactory != nullptr, "VertexInputStateFactory creation failed."); MOBILEGL_ASSERT(m_vertexInputStateFactory != nullptr, "VertexInputStateFactory creation failed.");
@@ -257,9 +262,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
m_pipelineFactory.reset(); m_pipelineFactory.reset();
m_programFactory.reset(); m_programFactory.reset();
if (m_textureSamplerManager) { if (m_samplerManager) {
m_textureSamplerManager->Shutdown(); m_samplerManager->Shutdown();
m_textureSamplerManager.reset(); m_samplerManager.reset();
}
if (m_textureManager) {
m_textureManager->Shutdown();
m_textureManager.reset();
} }
m_vertexInputStateFactory.reset(); m_vertexInputStateFactory.reset();
for (auto& buffer : m_frameVertexUploadBuffers) { for (auto& buffer : m_frameVertexUploadBuffers) {
@@ -17,7 +17,8 @@
#include "VkBufferObject.h" #include "VkBufferObject.h"
#include "VkRenderTargetManager.h" #include "VkRenderTargetManager.h"
#include "VkRenderPassManager.h" #include "VkRenderPassManager.h"
#include "VkTextureSamplerManager.h" #include "VkSamplerManager.h"
#include "VkTextureManager.h"
#include "MG_Util/Math/VectorTypes.h" #include "MG_Util/Math/VectorTypes.h"
#include <Includes.h> #include <Includes.h>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
@@ -154,7 +155,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
UniquePtr<VertexInputStateFactory> m_vertexInputStateFactory; UniquePtr<VertexInputStateFactory> m_vertexInputStateFactory;
UniquePtr<VkRenderTargetManager> m_framebufferManager; UniquePtr<VkRenderTargetManager> m_framebufferManager;
UniquePtr<VkRenderPassManager> m_renderPassManager; UniquePtr<VkRenderPassManager> m_renderPassManager;
UniquePtr<VkTextureSamplerManager> m_textureSamplerManager; UniquePtr<VkTextureManager> m_textureManager;
UniquePtr<VkSamplerManager> m_samplerManager;
void CreateInstance(); void CreateInstance();
VkResult SetupDebugMessenger(); VkResult SetupDebugMessenger();