mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Improvement] (MG_Backend/DirectVulkan): split TextureSamplerManager into TextureManager and SamplerManager
This commit is contained in:
+2
-1
@@ -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
|
||||||
+17
-165
@@ -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
|
||||||
+3
-25
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user