diff --git a/CMakeLists.txt b/CMakeLists.txt index 40a0c841..e7de16e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,7 +213,7 @@ set(SOURCE_FILES MobileGL/MG_Backend/DirectVulkan/Renderer/PipelineManager.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/FrameContext.cpp MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp - MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramManager.cpp + MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp MobileGL/MG_State/GLState/Core.cpp MobileGL/MG_State/GLState/ErrorState/Error.cpp diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index ca98911b..929440e1 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -106,8 +106,6 @@ #define TRACY_ZONECOLOR_BACKEND 0x00FF00 #endif -#include "xxhash.h" - // Post-includes for significant project headers #include "MG_Util/Debug/Log.h" #include "MG_Util/Types.h" diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp new file mode 100644 index 00000000..535c910a --- /dev/null +++ b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp @@ -0,0 +1,50 @@ +// +// Created by Swung0x48 on 2026/2/9. +// + +#include "ProgramManager.h" +#include "MG_Backend/DirectVulkan/Renderer/VulkanContext.h" + +namespace MobileGL::MG_Backend::DirectVulkan { + ProgramManager::ProgramManager(VulkanContext &ctx): m_ctx(ctx) {} + + ProgramManager::~ProgramManager() { + Cleanup(); + } + + void ProgramManager::Cleanup() { + XXH64_freeState(m_hashState); + } + + Vector ProgramManager::CreatePipelineShaderStages() { + Vector info; + + return info; + } + + ProgramManager::HashType ProgramManager::GetHash(ProgramObject *programObject) { + MOBILEGL_ASSERT(programObject && programObject->GetLinkStatus(), "program object is null or not successfully linked!"); + MOBILEGL_ASSERT(m_hashState != nullptr, "Hash state should already be initialized"); + + XXH64_hash_t const seed = MG_Config::CacheVersion; + auto errc = XXH64_reset(m_hashState, seed); + MOBILEGL_ASSERT(errc == XXH_OK, "Hash state reset failed"); + + auto& shaders = programObject->GetAttachedShaders(); + auto& spirvBinaries = programObject->GetGeneratedSpirv(); + auto count = shaders.size(); + + for (auto i = 0; i < count; i++) { + auto& shader = shaders[i]; + auto stage = shader->GetShaderStage(); + errc = XXH64_update(m_hashState, &stage, sizeof(stage)); + MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); + errc = XXH64_update(m_hashState, spirvBinaries[i].data(), spirvBinaries[i].size() * sizeof(unsigned)); + MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); + } + + HashType hash = XXH64_digest(m_hashState); + + return hash; + } +} // namespace MobileGL::MG_Backend::DirectVulkan \ No newline at end of file diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h new file mode 100644 index 00000000..262b056b --- /dev/null +++ b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h @@ -0,0 +1,34 @@ +// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/ProgramManager.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 "Includes.h" +#include "MG_State/GLState/ProgramState/ProgramObject.h" +#include "Config.h" +#include "xxhash.h" + +namespace MobileGL::MG_Backend::DirectVulkan { + class VulkanContext; + + class ProgramManager { + public: + using HashType = XXH64_hash_t; + ProgramManager(VulkanContext& ctx); + ~ProgramManager(); + + Vector CreatePipelineShaderStages(); + private: + using ProgramObject = MobileGL::MG_State::GLState::ProgramObject; + + void Cleanup(); + HashType GetHash(ProgramObject* programObject); + VulkanContext& m_ctx; + UnorderedMap> m_shaderStageCreateInfo; + XXH64_state_t* const m_hashState = XXH64_createState(); + }; +} // namespace MobileGL::MG_Backend::DirectVulkan \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 53112caf..19905d2d 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -110,6 +110,11 @@ namespace MobileGL { AddDefaultFragmentShaderIfMissing(); } + std::sort(m_shaders.begin(), m_shaders.end(), + [](SharedPtr& a, SharedPtr& b) { + return a->GetShaderStage() < b->GetShaderStage(); + }); + for (SizeT i = 0; i < m_shaders.size(); i++) { shaderTypes[i] = MG_Util::ConvertShaderStageToGLEnum(m_shaders[i]->GetShaderStage()); MGLOG_D("ProgramObject %u: Preparing shader[%zu] stage %s at %p", m_externalIndex, i, diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h index 99ef4016..29d69743 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h @@ -17,6 +17,7 @@ namespace MobileGL { Geometry, Fragment, Compute, + ShaderStageCount, Unknown = -1 };