From dfe91e96a5a4c0257683b246f2df031da5893567 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 17 Feb 2026 09:46:29 +0800 Subject: [PATCH] [Feat] (MG_Backend/DirectVulkan): integrate vma, implement VkBufferObject --- .../DirectVulkan/Renderer/VkBufferObject.cpp | 80 +++++++++++++++++++ .../DirectVulkan/Renderer/VkBufferObject.h | 41 ++++++++++ MobileGL/MG_Backend/DirectVulkan/VmaImpl.cpp | 10 +++ 3 files changed, 131 insertions(+) create mode 100644 MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp create mode 100644 MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h create mode 100644 MobileGL/MG_Backend/DirectVulkan/VmaImpl.cpp diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp new file mode 100644 index 00000000..5ca4b8d0 --- /dev/null +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.cpp @@ -0,0 +1,80 @@ +// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.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 "VkBufferObject.h" + +namespace MobileGL::MG_Backend::DirectVulkan { + VkBufferObject::~VkBufferObject() { + Destroy(); + } + + Bool VkBufferObject::Create(VmaAllocator allocator, VkDeviceSize size, VkBufferUsageFlags usage, + VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocationFlags) { + MOBILEGL_ASSERT(allocator != nullptr, "VkBufferObject::Create requires valid VMA allocator"); + MOBILEGL_ASSERT(size > 0, "VkBufferObject::Create requires non-zero size"); + + Destroy(); + m_allocator = allocator; + + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = size; + bufferInfo.usage = usage; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VmaAllocationCreateInfo allocationInfo{}; + allocationInfo.usage = memoryUsage; + allocationInfo.flags = allocationFlags; + + const VkResult result = + vmaCreateBuffer(m_allocator, &bufferInfo, &allocationInfo, &m_buffer, &m_allocation, nullptr); + if (result != VK_SUCCESS) { + MGLOG_E("VkBufferObject::Create failed: vmaCreateBuffer returned %d", result); + m_allocator = nullptr; + m_buffer = VK_NULL_HANDLE; + m_allocation = nullptr; + m_size = 0; + return false; + } + + m_size = size; + return true; + } + + void VkBufferObject::Destroy() { + if (m_allocator != nullptr && m_buffer != VK_NULL_HANDLE && m_allocation != nullptr) { + vmaDestroyBuffer(m_allocator, m_buffer, m_allocation); + } + m_buffer = VK_NULL_HANDLE; + m_allocation = nullptr; + m_allocator = nullptr; + m_size = 0; + } + + Bool VkBufferObject::Upload(const void* data, VkDeviceSize size, VkDeviceSize offset) { + MOBILEGL_ASSERT(IsValid(), "VkBufferObject::Upload called on invalid buffer"); + MOBILEGL_ASSERT(data != nullptr || size == 0, "VkBufferObject::Upload data pointer is null"); + MOBILEGL_ASSERT(offset + size <= m_size, "VkBufferObject::Upload out of range"); + + if (size == 0) { + return true; + } + + void* mapped = nullptr; + const VkResult mapResult = vmaMapMemory(m_allocator, m_allocation, &mapped); + if (mapResult != VK_SUCCESS || mapped == nullptr) { + MGLOG_E("VkBufferObject::Upload failed: vmaMapMemory returned %d", mapResult); + return false; + } + + Memcpy(static_cast(mapped) + offset, data, static_cast(size)); + vmaUnmapMemory(m_allocator, m_allocation); + return true; + } +} // namespace MobileGL::MG_Backend::DirectVulkan + diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h new file mode 100644 index 00000000..58be1a7d --- /dev/null +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.h @@ -0,0 +1,41 @@ +// MobileGL - MobileGL/MG_Backend/DirectVulkan/Renderer/VkBufferObject.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 +#include + +namespace MobileGL::MG_Backend::DirectVulkan { + class VkBufferObject { + public: + VkBufferObject() = default; + ~VkBufferObject(); + + VkBufferObject(const VkBufferObject&) = delete; + VkBufferObject& operator=(const VkBufferObject&) = delete; + + Bool Create(VmaAllocator allocator, VkDeviceSize size, VkBufferUsageFlags usage, + VmaMemoryUsage memoryUsage, VmaAllocationCreateFlags allocationFlags = 0); + void Destroy(); + + Bool Upload(const void* data, VkDeviceSize size, VkDeviceSize offset = 0); + + VkBuffer GetHandle() const { return m_buffer; } + VkDeviceSize GetSize() const { return m_size; } + Bool IsValid() const { return m_allocator != nullptr && m_buffer != VK_NULL_HANDLE && m_allocation != nullptr; } + + private: + VmaAllocator m_allocator = nullptr; + VkBuffer m_buffer = VK_NULL_HANDLE; + VmaAllocation m_allocation = nullptr; + VkDeviceSize m_size = 0; + }; +} // namespace MobileGL::MG_Backend::DirectVulkan + diff --git a/MobileGL/MG_Backend/DirectVulkan/VmaImpl.cpp b/MobileGL/MG_Backend/DirectVulkan/VmaImpl.cpp new file mode 100644 index 00000000..adc1efad --- /dev/null +++ b/MobileGL/MG_Backend/DirectVulkan/VmaImpl.cpp @@ -0,0 +1,10 @@ +// MobileGL - MobileGL/MG_Backend/DirectVulkan/VmaImpl.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 + +#define VMA_IMPLEMENTATION +#include