diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp deleted file mode 100644 index a951bb18..00000000 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// MobileGL - MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.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 "ProgramManager.h" - -namespace MobileGL::MG_Backend::DirectVulkan { - ProgramManager::ProgramManager(VulkanContext &ctx): m_ctx(ctx) {} - - ProgramManager::~ProgramManager() { - Cleanup(); - } - - void ProgramManager::Cleanup() { - auto device = m_ctx.GetDevice(); - if (device != VK_NULL_HANDLE) { - for (auto& [_, stages] : m_shaderStageCreateInfo) { - for (auto& stageInfo : stages) { - if (stageInfo.module != VK_NULL_HANDLE) { - vkDestroyShaderModule(device, stageInfo.module, nullptr); - stageInfo.module = VK_NULL_HANDLE; - } - } - } - } - m_shaderStageCreateInfo.clear(); - XXH64_freeState(m_hashState); - } - - Vector& ProgramManager::CreatePipelineShaderStages(ProgramObject* programObject) { - auto hash = GetHash(programObject); - MOBILEGL_ASSERT(m_shaderStageCreateInfo.find(hash) == m_shaderStageCreateInfo.end(), - "A program with the same hash has already been created"); - Vector info; - auto& shaders = programObject->GetAttachedShaders(); - auto& spirvBinaries = programObject->GetGeneratedSpirv(); - MOBILEGL_ASSERT(shaders.size() == spirvBinaries.size(), - "Shader and SPIR-V binary count mismatch"); - - info.reserve(shaders.size()); - - auto device = m_ctx.GetDevice(); - MOBILEGL_ASSERT(device != VK_NULL_HANDLE, "Vulkan device is null"); - - for (SizeT i = 0; i < shaders.size(); ++i) { - auto shaderStage = shaders[i]->GetShaderStage(); - VkShaderStageFlagBits vkStage = VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM; - switch (shaderStage) { - case ShaderStage::Vertex: - vkStage = VK_SHADER_STAGE_VERTEX_BIT; - break; - case ShaderStage::TessControl: - vkStage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - break; - case ShaderStage::TessEval: - vkStage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - break; - case ShaderStage::Geometry: - vkStage = VK_SHADER_STAGE_GEOMETRY_BIT; - break; - case ShaderStage::Fragment: - vkStage = VK_SHADER_STAGE_FRAGMENT_BIT; - break; - case ShaderStage::Compute: - vkStage = VK_SHADER_STAGE_COMPUTE_BIT; - break; - default: - MOBILEGL_ASSERT(false, "Unsupported shader stage"); - break; - } - - auto& spirv = spirvBinaries[i]; - MOBILEGL_ASSERT(!spirv.empty(), "SPIR-V binary is empty"); - VkShaderModuleCreateInfo smci{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}; - smci.codeSize = spirv.size() * sizeof(Uint); - smci.pCode = reinterpret_cast(spirv.data()); - - VkShaderModule shaderModule = VK_NULL_HANDLE; - VK_VERIFY(vkCreateShaderModule(device, &smci, nullptr, &shaderModule), "vkCreateShaderModule"); - MOBILEGL_ASSERT(shaderModule != VK_NULL_HANDLE, "Failed to create shader module"); - - VkPipelineShaderStageCreateInfo stageInfo{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; - stageInfo.stage = vkStage; - stageInfo.module = shaderModule; - stageInfo.pName = "main"; - info.emplace_back(stageInfo); - } - - auto [it, inserted] = m_shaderStageCreateInfo.emplace(hash, Move(info)); - MOBILEGL_ASSERT(inserted, "Failed to cache shader stage create info"); - return it->second; - } - - Vector* ProgramManager::GetPipelineShaderStages(HashType hash) { - auto it = m_shaderStageCreateInfo.find(hash); - if (it == m_shaderStageCreateInfo.end()) return nullptr; - return &it->second; - } - - Vector* ProgramManager::GetPipelineShaderStages(ProgramObject* programObject) { - return GetPipelineShaderStages(GetHash(programObject)); - } - - 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 diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h b/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h deleted file mode 100644 index 542dfd20..00000000 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/ProgramManager.h +++ /dev/null @@ -1,36 +0,0 @@ -// MobileGL - MobileGL/MG_Backend/DirectVulkan/Managers/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 ProgramObject = MobileGL::MG_State::GLState::ProgramObject; - using HashType = XXH64_hash_t; - ProgramManager(VulkanContext& ctx); - ~ProgramManager(); - - Vector& CreatePipelineShaderStages(ProgramObject* programObject); - Vector* GetPipelineShaderStages(HashType hash); - Vector* GetPipelineShaderStages(ProgramObject* programObject); - private: - - 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 diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.cpp deleted file mode 100644 index 664bb1c9..00000000 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// MobileGL - MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.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 "RenderStateManager.h" - -namespace MobileGL::MG_Backend::DirectVulkan { - RenderStateManager::RenderStateManager() {} - - RenderStateManager::~RenderStateManager() { - Cleanup(); - } - - void RenderStateManager::Cleanup() { - m_renderStateInfo.clear(); - XXH64_freeState(m_hashState); - } - - void RenderStateManager::PatchCreateInfoPointers(RenderStateInfo& stateInfo) { - stateInfo.ColorBlendStateCreateInfo.attachmentCount = - static_cast(stateInfo.ColorBlendAttachmentStates.size()); - stateInfo.ColorBlendStateCreateInfo.pAttachments = - stateInfo.ColorBlendAttachmentStates.empty() ? nullptr : stateInfo.ColorBlendAttachmentStates.data(); - - stateInfo.ViewportStateCreateInfo.viewportCount = 1; - stateInfo.ViewportStateCreateInfo.pViewports = &stateInfo.Viewport; - stateInfo.ViewportStateCreateInfo.scissorCount = 1; - stateInfo.ViewportStateCreateInfo.pScissors = &stateInfo.Scissor; - } - - RenderStateManager::RenderStateInfo& - RenderStateManager::CreatePipelineRenderState(const RenderStateParameters& renderState, Uint colorAttachmentCount) { - auto hash = GetHash(renderState, colorAttachmentCount); - MOBILEGL_ASSERT(m_renderStateInfo.find(hash) == m_renderStateInfo.end(), - "A render state with the same hash has already been created"); - MOBILEGL_ASSERT(colorAttachmentCount > 0, "colorAttachmentCount must be greater than zero"); - MOBILEGL_ASSERT(colorAttachmentCount <= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS, - "colorAttachmentCount exceeds max draw buffers"); - - RenderStateInfo stateInfo; - - MOBILEGL_ASSERT(renderState.Viewport.z() >= 0 && renderState.Viewport.w() >= 0, - "Viewport width/height must be non-negative"); - stateInfo.Viewport.x = static_cast(renderState.Viewport.x()); - stateInfo.Viewport.y = static_cast(renderState.Viewport.y()); - stateInfo.Viewport.width = static_cast(renderState.Viewport.z()); - stateInfo.Viewport.height = static_cast(renderState.Viewport.w()); - stateInfo.Viewport.minDepth = 0.0f; - stateInfo.Viewport.maxDepth = 1.0f; - - if (renderState.ScissorTestEnabled) { - MOBILEGL_ASSERT(renderState.ScissorBox.z() >= 0 && renderState.ScissorBox.w() >= 0, - "Scissor width/height must be non-negative"); - stateInfo.Scissor.offset.x = renderState.ScissorBox.x(); - stateInfo.Scissor.offset.y = renderState.ScissorBox.y(); - stateInfo.Scissor.extent.width = static_cast(renderState.ScissorBox.z()); - stateInfo.Scissor.extent.height = static_cast(renderState.ScissorBox.w()); - } else { - stateInfo.Scissor.offset.x = renderState.Viewport.x(); - stateInfo.Scissor.offset.y = renderState.Viewport.y(); - stateInfo.Scissor.extent.width = static_cast(renderState.Viewport.z()); - stateInfo.Scissor.extent.height = static_cast(renderState.Viewport.w()); - } - - stateInfo.RasterizationStateCreateInfo.depthClampEnable = VK_FALSE; - stateInfo.RasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE; - stateInfo.RasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; - stateInfo.RasterizationStateCreateInfo.cullMode = - renderState.CullFaceEnabled ? ResolveCullMode(renderState.CullFaceModeSetting) : VK_CULL_MODE_NONE; - stateInfo.RasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - stateInfo.RasterizationStateCreateInfo.depthBiasEnable = VK_FALSE; - stateInfo.RasterizationStateCreateInfo.lineWidth = 1.0f; - - stateInfo.DepthStencilStateCreateInfo.depthTestEnable = renderState.DepthTestEnabled ? VK_TRUE : VK_FALSE; - stateInfo.DepthStencilStateCreateInfo.depthWriteEnable = renderState.DepthMask ? VK_TRUE : VK_FALSE; - stateInfo.DepthStencilStateCreateInfo.depthCompareOp = ResolveDepthCompareOp(renderState.DepthFunc); - stateInfo.DepthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE; - stateInfo.DepthStencilStateCreateInfo.stencilTestEnable = VK_FALSE; - stateInfo.DepthStencilStateCreateInfo.minDepthBounds = 0.0f; - stateInfo.DepthStencilStateCreateInfo.maxDepthBounds = 1.0f; - - stateInfo.ColorBlendAttachmentStates.reserve(colorAttachmentCount); - for (Uint i = 0; i < colorAttachmentCount; ++i) { - const auto& blendState = renderState.BlendStates[i]; - VkPipelineColorBlendAttachmentState attachment{}; - attachment.blendEnable = blendState.Enabled ? VK_TRUE : VK_FALSE; - attachment.srcColorBlendFactor = ResolveBlendFactor(blendState.SrcFactorRGB); - attachment.dstColorBlendFactor = ResolveBlendFactor(blendState.DstFactorRGB); - attachment.colorBlendOp = VK_BLEND_OP_ADD; - attachment.srcAlphaBlendFactor = ResolveBlendFactor(blendState.SrcFactorAlpha); - attachment.dstAlphaBlendFactor = ResolveBlendFactor(blendState.DstFactorAlpha); - attachment.alphaBlendOp = VK_BLEND_OP_ADD; - attachment.colorWriteMask = ResolveColorWriteMask(renderState.ColorMask); - stateInfo.ColorBlendAttachmentStates.emplace_back(attachment); - } - - stateInfo.ColorBlendStateCreateInfo.logicOpEnable = VK_FALSE; - stateInfo.ColorBlendStateCreateInfo.logicOp = VK_LOGIC_OP_COPY; - stateInfo.ColorBlendStateCreateInfo.blendConstants[0] = 0.0f; - stateInfo.ColorBlendStateCreateInfo.blendConstants[1] = 0.0f; - stateInfo.ColorBlendStateCreateInfo.blendConstants[2] = 0.0f; - stateInfo.ColorBlendStateCreateInfo.blendConstants[3] = 0.0f; - - PatchCreateInfoPointers(stateInfo); - - auto [it, inserted] = m_renderStateInfo.emplace(hash, Move(stateInfo)); - MOBILEGL_ASSERT(inserted, "Failed to cache pipeline render state create info"); - PatchCreateInfoPointers(it->second); - return it->second; - } - - RenderStateManager::RenderStateInfo* RenderStateManager::GetPipelineRenderState(HashType hash) { - auto it = m_renderStateInfo.find(hash); - if (it == m_renderStateInfo.end()) return nullptr; - return &it->second; - } - - RenderStateManager::RenderStateInfo* - RenderStateManager::GetPipelineRenderState(const RenderStateParameters& renderState, Uint colorAttachmentCount) { - return GetPipelineRenderState(GetHash(renderState, colorAttachmentCount)); - } - - RenderStateManager::HashType RenderStateManager::GetHash(const RenderStateParameters& renderState, - Uint colorAttachmentCount) { - MOBILEGL_ASSERT(m_hashState != nullptr, "Hash state should already be initialized"); - MOBILEGL_ASSERT(colorAttachmentCount > 0, "colorAttachmentCount must be greater than zero"); - MOBILEGL_ASSERT(colorAttachmentCount <= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS, - "colorAttachmentCount exceeds max draw buffers"); - - XXH64_hash_t const seed = MG_Config::CacheVersion; - auto errc = XXH64_reset(m_hashState, seed); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state reset failed"); - - const Int viewport[4] = {renderState.Viewport.x(), renderState.Viewport.y(), renderState.Viewport.z(), - renderState.Viewport.w()}; - errc = XXH64_update(m_hashState, viewport, sizeof(viewport)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - - for (Uint i = 0; i < colorAttachmentCount; ++i) { - const auto& blendState = renderState.BlendStates[i]; - errc = XXH64_update(m_hashState, &blendState.Enabled, sizeof(blendState.Enabled)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &blendState.SrcFactorRGB, sizeof(blendState.SrcFactorRGB)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &blendState.DstFactorRGB, sizeof(blendState.DstFactorRGB)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &blendState.SrcFactorAlpha, sizeof(blendState.SrcFactorAlpha)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &blendState.DstFactorAlpha, sizeof(blendState.DstFactorAlpha)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - } - - errc = XXH64_update(m_hashState, &renderState.DepthTestEnabled, sizeof(renderState.DepthTestEnabled)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &renderState.DepthFunc, sizeof(renderState.DepthFunc)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &renderState.DepthMask, sizeof(renderState.DepthMask)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - - const Bool colorMask[4] = {renderState.ColorMask.x(), renderState.ColorMask.y(), renderState.ColorMask.z(), - renderState.ColorMask.w()}; - errc = XXH64_update(m_hashState, colorMask, sizeof(colorMask)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - - errc = XXH64_update(m_hashState, &renderState.CullFaceEnabled, sizeof(renderState.CullFaceEnabled)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &renderState.CullFaceModeSetting, sizeof(renderState.CullFaceModeSetting)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - - errc = XXH64_update(m_hashState, &renderState.ScissorTestEnabled, sizeof(renderState.ScissorTestEnabled)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - const Int scissor[4] = {renderState.ScissorBox.x(), renderState.ScissorBox.y(), renderState.ScissorBox.z(), - renderState.ScissorBox.w()}; - errc = XXH64_update(m_hashState, scissor, sizeof(scissor)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - - errc = XXH64_update(m_hashState, &colorAttachmentCount, sizeof(colorAttachmentCount)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - - return XXH64_digest(m_hashState); - } - - VkBlendFactor RenderStateManager::ResolveBlendFactor(BlendFactor factor) { - switch (factor) { - case BlendFactor::Zero: - return VK_BLEND_FACTOR_ZERO; - case BlendFactor::One: - return VK_BLEND_FACTOR_ONE; - case BlendFactor::SrcColor: - return VK_BLEND_FACTOR_SRC_COLOR; - case BlendFactor::OneMinusSrcColor: - return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - case BlendFactor::DstColor: - return VK_BLEND_FACTOR_DST_COLOR; - case BlendFactor::OneMinusDstColor: - return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - case BlendFactor::SrcAlpha: - return VK_BLEND_FACTOR_SRC_ALPHA; - case BlendFactor::OneMinusSrcAlpha: - return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - case BlendFactor::DstAlpha: - return VK_BLEND_FACTOR_DST_ALPHA; - case BlendFactor::OneMinusDstAlpha: - return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - case BlendFactor::ConstantColor: - return VK_BLEND_FACTOR_CONSTANT_COLOR; - case BlendFactor::OneMinusConstantColor: - return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; - case BlendFactor::ConstantAlpha: - return VK_BLEND_FACTOR_CONSTANT_ALPHA; - case BlendFactor::OneMinusConstantAlpha: - return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; - default: - MOBILEGL_ASSERT(false, "Unsupported blend factor"); - return VK_BLEND_FACTOR_ONE; - } - } - - VkCompareOp RenderStateManager::ResolveDepthCompareOp(DepthTestFunc func) { - switch (func) { - case DepthTestFunc::Never: - return VK_COMPARE_OP_NEVER; - case DepthTestFunc::Less: - return VK_COMPARE_OP_LESS; - case DepthTestFunc::Equal: - return VK_COMPARE_OP_EQUAL; - case DepthTestFunc::LessEqual: - return VK_COMPARE_OP_LESS_OR_EQUAL; - case DepthTestFunc::Greater: - return VK_COMPARE_OP_GREATER; - case DepthTestFunc::NotEqual: - return VK_COMPARE_OP_NOT_EQUAL; - case DepthTestFunc::GreaterEqual: - return VK_COMPARE_OP_GREATER_OR_EQUAL; - case DepthTestFunc::Always: - return VK_COMPARE_OP_ALWAYS; - default: - MOBILEGL_ASSERT(false, "Unsupported depth compare function"); - return VK_COMPARE_OP_LESS; - } - } - - VkCullModeFlags RenderStateManager::ResolveCullMode(CullFaceMode mode) { - switch (mode) { - case CullFaceMode::Front: - return VK_CULL_MODE_FRONT_BIT; - case CullFaceMode::Back: - return VK_CULL_MODE_BACK_BIT; - case CullFaceMode::FrontAndBack: - return VK_CULL_MODE_FRONT_AND_BACK; - default: - MOBILEGL_ASSERT(false, "Unsupported cull face mode"); - return VK_CULL_MODE_BACK_BIT; - } - } - - VkColorComponentFlags RenderStateManager::ResolveColorWriteMask(const BoolVec4& mask) { - VkColorComponentFlags vkMask = 0; - if (mask.r()) vkMask |= VK_COLOR_COMPONENT_R_BIT; - if (mask.g()) vkMask |= VK_COLOR_COMPONENT_G_BIT; - if (mask.b()) vkMask |= VK_COLOR_COMPONENT_B_BIT; - if (mask.a()) vkMask |= VK_COLOR_COMPONENT_A_BIT; - return vkMask; - } -} // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.h b/MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.h deleted file mode 100644 index 941a912d..00000000 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.h +++ /dev/null @@ -1,54 +0,0 @@ -// MobileGL - MobileGL/MG_Backend/DirectVulkan/Managers/RenderStateManager.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/RenderState/RenderState.h" -#include "Config.h" -#include "xxhash.h" - -namespace MobileGL::MG_Backend::DirectVulkan { - class RenderStateManager { - public: - using RenderStateParameters = MobileGL::RenderStateParameters; - using HashType = XXH64_hash_t; - - struct RenderStateInfo { - VkPipelineColorBlendStateCreateInfo ColorBlendStateCreateInfo{ - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO}; - Vector ColorBlendAttachmentStates; - VkPipelineRasterizationStateCreateInfo RasterizationStateCreateInfo{ - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO}; - VkPipelineViewportStateCreateInfo ViewportStateCreateInfo{ - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO}; - VkPipelineDepthStencilStateCreateInfo DepthStencilStateCreateInfo{ - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO}; - VkViewport Viewport{}; - VkRect2D Scissor{}; - }; - - RenderStateManager(); - ~RenderStateManager(); - - RenderStateInfo& CreatePipelineRenderState(const RenderStateParameters& renderState, Uint colorAttachmentCount); - RenderStateInfo* GetPipelineRenderState(HashType hash); - RenderStateInfo* GetPipelineRenderState(const RenderStateParameters& renderState, Uint colorAttachmentCount); - - private: - void Cleanup(); - static void PatchCreateInfoPointers(RenderStateInfo& stateInfo); - HashType GetHash(const RenderStateParameters& renderState, Uint colorAttachmentCount); - static VkBlendFactor ResolveBlendFactor(BlendFactor factor); - static VkCompareOp ResolveDepthCompareOp(DepthTestFunc func); - static VkCullModeFlags ResolveCullMode(CullFaceMode mode); - static VkColorComponentFlags ResolveColorWriteMask(const BoolVec4& mask); - - UnorderedMap m_renderStateInfo; - XXH64_state_t* const m_hashState = XXH64_createState(); - }; -} // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.cpp deleted file mode 100644 index 7fc47bda..00000000 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// MobileGL - MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.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 "VertexInputStateManager.h" - -namespace MobileGL::MG_Backend::DirectVulkan { - VertexInputStateManager::VertexInputStateManager() {} - - VertexInputStateManager::~VertexInputStateManager() { - Cleanup(); - } - - void VertexInputStateManager::Cleanup() { - m_vertexInputStateInfo.clear(); - XXH64_freeState(m_hashState); - } - - void VertexInputStateManager::PatchCreateInfoPointers(VertexInputStateInfo& stateInfo) { - stateInfo.CreateInfo.vertexBindingDescriptionCount = static_cast(stateInfo.BindingDescriptions.size()); - stateInfo.CreateInfo.pVertexBindingDescriptions = - stateInfo.BindingDescriptions.empty() ? nullptr : stateInfo.BindingDescriptions.data(); - stateInfo.CreateInfo.vertexAttributeDescriptionCount = static_cast(stateInfo.AttributeDescriptions.size()); - stateInfo.CreateInfo.pVertexAttributeDescriptions = - stateInfo.AttributeDescriptions.empty() ? nullptr : stateInfo.AttributeDescriptions.data(); - } - - VertexInputStateManager::VertexInputStateInfo& - VertexInputStateManager::CreatePipelineVertexInputState(VertexArrayObject* vaoObject) { - auto hash = GetHash(vaoObject); - MOBILEGL_ASSERT(m_vertexInputStateInfo.find(hash) == m_vertexInputStateInfo.end(), - "A VAO vertex input state with the same hash has already been created"); - - VertexInputStateInfo stateInfo; - const auto& allAttributes = vaoObject->GetAllAttributes(); - - for (Uint attribIndex = 0; attribIndex < allAttributes.size(); ++attribIndex) { - const auto& attrib = allAttributes[attribIndex]; - if (!attrib.Enabled) continue; - - MOBILEGL_ASSERT(attrib.Size >= 1 && attrib.Size <= 4, "Vertex attribute size out of range"); - MOBILEGL_ASSERT(attrib.Divisor <= 1, - "Vulkan core pipeline vertex input only supports divisor 0/1 without extra extensions"); - - VkVertexInputBindingDescription bindingDesc{}; - bindingDesc.binding = attribIndex; - bindingDesc.inputRate = (attrib.Divisor == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; - - auto componentByteSize = GetDataTypeByteSize(attrib.Type); - auto computedStride = static_cast(componentByteSize * static_cast(attrib.Size)); - bindingDesc.stride = (attrib.Stride > 0) ? static_cast(attrib.Stride) : computedStride; - stateInfo.BindingDescriptions.emplace_back(bindingDesc); - - VkVertexInputAttributeDescription attrDesc{}; - attrDesc.location = attribIndex; - attrDesc.binding = attribIndex; - attrDesc.format = ResolveVertexFormat(attrib); - attrDesc.offset = static_cast(attrib.Offset); - stateInfo.AttributeDescriptions.emplace_back(attrDesc); - } - - PatchCreateInfoPointers(stateInfo); - - auto [it, inserted] = m_vertexInputStateInfo.emplace(hash, Move(stateInfo)); - MOBILEGL_ASSERT(inserted, "Failed to cache pipeline vertex input state create info"); - PatchCreateInfoPointers(it->second); - return it->second; - } - - VertexInputStateManager::VertexInputStateInfo* VertexInputStateManager::GetPipelineVertexInputState(HashType hash) { - auto it = m_vertexInputStateInfo.find(hash); - if (it == m_vertexInputStateInfo.end()) return nullptr; - return &it->second; - } - - VertexInputStateManager::VertexInputStateInfo* - VertexInputStateManager::GetPipelineVertexInputState(VertexArrayObject* vaoObject) { - return GetPipelineVertexInputState(GetHash(vaoObject)); - } - - VertexInputStateManager::HashType VertexInputStateManager::GetHash(VertexArrayObject* vaoObject) { - MOBILEGL_ASSERT(vaoObject != nullptr, "vao object is null"); - 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"); - - const auto& allAttributes = vaoObject->GetAllAttributes(); - for (const auto& attrib : allAttributes) { - errc = XXH64_update(m_hashState, &attrib.Enabled, sizeof(attrib.Enabled)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.Size, sizeof(attrib.Size)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.Type, sizeof(attrib.Type)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.Normalized, sizeof(attrib.Normalized)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.Stride, sizeof(attrib.Stride)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.Offset, sizeof(attrib.Offset)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.IsInteger, sizeof(attrib.IsInteger)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - errc = XXH64_update(m_hashState, &attrib.Divisor, sizeof(attrib.Divisor)); - MOBILEGL_ASSERT(errc == XXH_OK, "Hash state update failed"); - } - - return XXH64_digest(m_hashState); - } - - Uint VertexInputStateManager::GetDataTypeByteSize(DataType type) { - switch (type) { - case DataType::Int8: - case DataType::Uint8: - return 1; - case DataType::Int16: - case DataType::Uint16: - case DataType::Float16: - return 2; - case DataType::Int32: - case DataType::Uint32: - case DataType::Float32: - case DataType::Fixed32: - return 4; - case DataType::Float64: - return 8; - default: - MOBILEGL_ASSERT(false, "Unsupported vertex data type"); - return 0; - } - } - - VkFormat VertexInputStateManager::ResolveVertexFormat(const MG_State::GLState::VertexAttribute& attrib) { - auto size = attrib.Size; - - auto selectFormat = [size](VkFormat c1, VkFormat c2, VkFormat c3, VkFormat c4) { - switch (size) { - case 1: - return c1; - case 2: - return c2; - case 3: - return c3; - case 4: - return c4; - default: - return VK_FORMAT_UNDEFINED; - } - }; - - if (attrib.IsInteger) { - MOBILEGL_ASSERT(!attrib.Normalized, "Integer attributes cannot be normalized in Vulkan integer pipeline IO"); - switch (attrib.Type) { - case DataType::Int8: - return selectFormat(VK_FORMAT_R8_SINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8B8_SINT, - VK_FORMAT_R8G8B8A8_SINT); - case DataType::Uint8: - return selectFormat(VK_FORMAT_R8_UINT, VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8B8_UINT, - VK_FORMAT_R8G8B8A8_UINT); - case DataType::Int16: - return selectFormat(VK_FORMAT_R16_SINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16B16_SINT, - VK_FORMAT_R16G16B16A16_SINT); - case DataType::Uint16: - return selectFormat(VK_FORMAT_R16_UINT, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16B16_UINT, - VK_FORMAT_R16G16B16A16_UINT); - case DataType::Int32: - return selectFormat(VK_FORMAT_R32_SINT, VK_FORMAT_R32G32_SINT, VK_FORMAT_R32G32B32_SINT, - VK_FORMAT_R32G32B32A32_SINT); - case DataType::Uint32: - return selectFormat(VK_FORMAT_R32_UINT, VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32B32_UINT, - VK_FORMAT_R32G32B32A32_UINT); - default: - MOBILEGL_ASSERT(false, "Unsupported integer vertex attribute data type"); - return VK_FORMAT_UNDEFINED; - } - } - - if (attrib.Normalized) { - switch (attrib.Type) { - case DataType::Int8: - return selectFormat(VK_FORMAT_R8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8B8_SNORM, - VK_FORMAT_R8G8B8A8_SNORM); - case DataType::Uint8: - return selectFormat(VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8_UNORM, - VK_FORMAT_R8G8B8A8_UNORM); - case DataType::Int16: - return selectFormat(VK_FORMAT_R16_SNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16B16_SNORM, - VK_FORMAT_R16G16B16A16_SNORM); - case DataType::Uint16: - return selectFormat(VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16B16_UNORM, - VK_FORMAT_R16G16B16A16_UNORM); - default: - MOBILEGL_ASSERT(false, "Unsupported normalized vertex attribute data type"); - return VK_FORMAT_UNDEFINED; - } - } - - switch (attrib.Type) { - case DataType::Float16: - return selectFormat(VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R16G16B16_SFLOAT, - VK_FORMAT_R16G16B16A16_SFLOAT); - case DataType::Float32: - return selectFormat(VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32_SFLOAT, - VK_FORMAT_R32G32B32A32_SFLOAT); - case DataType::Int8: - return selectFormat(VK_FORMAT_R8_SSCALED, VK_FORMAT_R8G8_SSCALED, VK_FORMAT_R8G8B8_SSCALED, - VK_FORMAT_R8G8B8A8_SSCALED); - case DataType::Uint8: - return selectFormat(VK_FORMAT_R8_USCALED, VK_FORMAT_R8G8_USCALED, VK_FORMAT_R8G8B8_USCALED, - VK_FORMAT_R8G8B8A8_USCALED); - case DataType::Int16: - return selectFormat(VK_FORMAT_R16_SSCALED, VK_FORMAT_R16G16_SSCALED, VK_FORMAT_R16G16B16_SSCALED, - VK_FORMAT_R16G16B16A16_SSCALED); - case DataType::Uint16: - return selectFormat(VK_FORMAT_R16_USCALED, VK_FORMAT_R16G16_USCALED, VK_FORMAT_R16G16B16_USCALED, - VK_FORMAT_R16G16B16A16_USCALED); - default: - MOBILEGL_ASSERT(false, "Unsupported floating-point vertex attribute data type"); - return VK_FORMAT_UNDEFINED; - } - } -} // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.h b/MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.h deleted file mode 100644 index bb2e3ca7..00000000 --- a/MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.h +++ /dev/null @@ -1,44 +0,0 @@ -// MobileGL - MobileGL/MG_Backend/DirectVulkan/Managers/VertexInputStateManager.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/VertexArrayState/VertexArrayObject.h" -#include "Config.h" -#include "xxhash.h" - -namespace MobileGL::MG_Backend::DirectVulkan { - class VertexInputStateManager { - public: - using VertexArrayObject = MobileGL::MG_State::GLState::VertexArrayObject; - using HashType = XXH64_hash_t; - - struct VertexInputStateInfo { - VkPipelineVertexInputStateCreateInfo CreateInfo{VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO}; - Vector BindingDescriptions; - Vector AttributeDescriptions; - }; - - VertexInputStateManager(); - ~VertexInputStateManager(); - - VertexInputStateInfo& CreatePipelineVertexInputState(VertexArrayObject* vaoObject); - VertexInputStateInfo* GetPipelineVertexInputState(HashType hash); - VertexInputStateInfo* GetPipelineVertexInputState(VertexArrayObject* vaoObject); - - private: - void Cleanup(); - static void PatchCreateInfoPointers(VertexInputStateInfo& stateInfo); - HashType GetHash(VertexArrayObject* vaoObject); - static VkFormat ResolveVertexFormat(const MG_State::GLState::VertexAttribute& attrib); - static Uint GetDataTypeByteSize(DataType type); - - UnorderedMap m_vertexInputStateInfo; - XXH64_state_t* const 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 9001fe45..7c25e69f 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -10,18 +10,6 @@ #include "MG_State/GLState/ProgramState/ProgramObject.h" -// #ifndef VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR -// #define VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR 0x00000001 -// #endif -// -// #ifndef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME -// #define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration" -// #endif -// -// #ifndef VK_EXT_METAL_SURFACE_EXTENSION_NAME -// #define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface" -// #endif - namespace MobileGL::MG_Backend::DirectVulkan { VkBool32 VulkanRenderer::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType,