From 359ba1c57234b1961083c69f3a6d68e6220dddc5 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sun, 22 Feb 2026 12:51:00 +0800 Subject: [PATCH] [Fix] (MG_Backend/DirectVulkan): properly compute hash for samplers --- .../Renderer/VkTextureSamplerManager.cpp | 42 +++++++++++++++---- .../Renderer/VkTextureSamplerManager.h | 5 +++ .../DirectVulkan/Renderer/VulkanRenderer.cpp | 4 +- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp index 5afec8b6..bbbdb403 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.cpp @@ -11,12 +11,6 @@ #include "MG_State/GLState/Core.h" namespace MobileGL::MG_Backend::DirectVulkan { - namespace { - constexpr Uint64 BuildSamplerKey(Uint externalIndex, Uint16 version) { - return (static_cast(externalIndex) << 16) | static_cast(version); - } - } // namespace - Bool VkTextureSamplerManager::Initialize(const InitInfo& initInfo) { Shutdown(); @@ -24,9 +18,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_physicalDevice = initInfo.physicalDevice; m_commandPool = initInfo.commandPool; m_graphicsQueue = initInfo.graphicsQueue; + m_config = initInfo.config; MOBILEGL_ASSERT(m_device != VK_NULL_HANDLE && m_physicalDevice != VK_NULL_HANDLE && m_commandPool != VK_NULL_HANDLE && - m_graphicsQueue != VK_NULL_HANDLE, "VkTextureSamplerManager::Initialize failed: invalid Vulkan handles"); + m_graphicsQueue != VK_NULL_HANDLE && m_config != nullptr, + "VkTextureSamplerManager::Initialize failed: invalid initialization info"); return true; } @@ -49,6 +45,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_physicalDevice = VK_NULL_HANDLE; m_commandPool = VK_NULL_HANDLE; m_graphicsQueue = VK_NULL_HANDLE; + m_config = nullptr; } Bool VkTextureSamplerManager::SyncTextureAndGetDescriptor(const MG_State::GLState::ITextureObject& texture, @@ -375,8 +372,37 @@ namespace MobileGL::MG_Backend::DirectVulkan { return 0; } + 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.GetExternalIndex(), sampler.GetVersion()); + const Uint64 key = BuildSamplerKey(sampler); auto it = m_samplers.find(key); if (it != m_samplers.end()) { return it->second.handle; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.h index a50de6d5..1af241ef 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureSamplerManager.h @@ -9,6 +9,7 @@ #pragma once #include "../VkIncludes.h" +#include "../VulkanRendererConfig.h" #include #include #include @@ -26,6 +27,7 @@ public: VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkCommandPool commandPool = VK_NULL_HANDLE; VkQueue graphicsQueue = VK_NULL_HANDLE; + const VulkanRendererConfig* config = nullptr; }; Bool Initialize(const InitInfo& initInfo); @@ -63,6 +65,7 @@ private: IntVec3& outTexelSize, SizeT& outByteSize); static VkFormat ResolveTextureFormat(TextureInternalFormat format); Uint32 FindMemoryType(Uint32 typeFilter, VkMemoryPropertyFlags properties) const; + Uint64 BuildSamplerKey(const MG_State::GLState::SamplerObject& sampler) const; VkSampler GetOrCreateSampler(const MG_State::GLState::SamplerObject& sampler); static VkFilter ToVkFilter(SamplerFilterMode mode); @@ -74,8 +77,10 @@ private: VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE; VkCommandPool m_commandPool = VK_NULL_HANDLE; VkQueue m_graphicsQueue = VK_NULL_HANDLE; + const VulkanRendererConfig* m_config = nullptr; UnorderedMap m_textureResources; UnorderedMap m_samplers; + static inline XXH64_state_t* m_hashState = XXH64_createState(); }; } // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 9300c838..d7c53e30 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -226,7 +226,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { m_textureSamplerManager = MakeUnique(); MOBILEGL_ASSERT(m_textureSamplerManager != nullptr, "VkTextureSamplerManager creation failed."); auto succeeded = false; - succeeded = m_textureSamplerManager->Initialize({m_device, m_physicalDevice.handle, m_commandPool, m_graphicsQueue}); + succeeded = + m_textureSamplerManager->Initialize({m_device, m_physicalDevice.handle, m_commandPool, m_graphicsQueue, + &m_config}); MOBILEGL_ASSERT(succeeded, "VkTextureSamplerManager initialization failed."); m_framebufferManager = MakeUnique();