From 62be9fed93b809a9ec7f4557f4a369ed48e798f2 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Wed, 16 Jul 2025 17:51:32 +0800 Subject: [PATCH] [Feat] (MG_State/GLState): Implement BufferObject. --- CMakeLists.txt | 3 + MobileGL/Includes.h | 5 ++ .../GLState/BufferState/BufferObject.h | 88 +++++++++++++++++++ .../GLState/BufferState/BufferState.cpp | 48 ++++++++++ .../GLState/BufferState/BufferState.h | 34 +++++++ MobileGL/MG_State/GLState/Core.cpp | 1 + MobileGL/MG_State/GLState/Core.h | 23 +++++ MobileGL/MG_Util/Miscellany/IndexGenerator.h | 52 +++++++++++ MobileGL/MG_Util/Types.h | 35 ++++++++ 9 files changed, 289 insertions(+) create mode 100644 MobileGL/MG_State/GLState/BufferState/BufferObject.h create mode 100644 MobileGL/MG_State/GLState/BufferState/BufferState.cpp create mode 100644 MobileGL/MG_State/GLState/BufferState/BufferState.h create mode 100644 MobileGL/MG_State/GLState/Core.cpp create mode 100644 MobileGL/MG_State/GLState/Core.h create mode 100644 MobileGL/MG_Util/Miscellany/IndexGenerator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 131ac6dc..f02eacde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,9 @@ add_library(${CMAKE_PROJECT_NAME} SHARED MobileGL/MG_Backend/Init.cpp MobileGL/MG_Util/Pipelines/Shader/GLSLtoSPIRVPipeline.cpp + + MobileGL/MG_State/GLState/Core.cpp + MobileGL/MG_State/GLState/BufferState/BufferState.cpp ) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index 0afe6273..347b3ee0 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -72,6 +72,7 @@ #include #include +#include "MG_Util/Miscellany/IndexGenerator.h" #include "MG_Util/GLExtensions.h" #include "MG_Util/Types.h" #include "MG_Util/Debug/Log.h" @@ -90,3 +91,7 @@ #include "MG_Util/Pipelines/Pipeline.hpp" #include "MG_Util/Pipelines/Shader/GLSLtoSPIRVPipeline.h" + +#include "MG_State/GLState/BufferState/BufferObject.h" +#include "MG_State/GLState/BufferState/BufferState.h" +#include "MG_State/GLState/Core.h" diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.h b/MobileGL/MG_State/GLState/BufferState/BufferObject.h new file mode 100644 index 00000000..a3009c68 --- /dev/null +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.h @@ -0,0 +1,88 @@ +#pragma once + +namespace MobileGL { + enum class BufferTarget { + Vertex, + Index, + Uniform, + Array, + ElementArray, + CopyRead, + CopyWrite, + PixelPack, + PixelUnpack, + Query, + Texture, + TransformFeedback, + AtomicCounter, + DispatchIndirect, + DrawIndirect, + ShaderStorage + }; + + enum class BufferUsage { + StreamDraw, + StreamRead, + StreamCopy, + StaticDraw, + StaticRead, + StaticCopy, + DynamicDraw, + DynamicRead, + DynamicCopy + }; + + enum class BufferMappingAccessBit : Uint { + Read = 0x01, + Write = 0x02, + InvalidateRange = 0x04, + InvalidateBuffer = 0x08, + FlushExplicit = 0x10, + Unsynchronized = 0x20 + }; + + inline BufferMappingAccessBit operator|(BufferMappingAccessBit a, BufferMappingAccessBit b) { + using T = std::underlying_type_t; + return static_cast(static_cast(a) | static_cast(b)); + } + + inline BufferMappingAccessBit& operator|=(BufferMappingAccessBit& a, BufferMappingAccessBit b) { + a = a | b; + return a; + } + + inline BufferMappingAccessBit operator&(BufferMappingAccessBit a, BufferMappingAccessBit b) { + using T = std::underlying_type_t; + return static_cast(static_cast(a) & static_cast(b)); + } + + inline bool any(BufferMappingAccessBit a) { + using T = std::underlying_type_t; + return static_cast(a) != 0; + } + + namespace MG_State { + namespace GLState { + class BufferObject { + public: + void UploadData(DataPtr data); + void SetUsage(BufferUsage usage); + SizeT GetSize() const; + BufferUsage GetUsage() const; + Range1D GetDirtyRange() const; + SharedPtr AquireMemory(Bool markMapped); + SharedPtr AquireMemoryRange(Range1D range, BufferMappingAccessBit access); + Bool IsMapped() const; + + private: + Int m_id = 0; + SizeT m_size = 0; + BufferUsage m_usage = BufferUsage::StaticDraw; + Data m_data; + Bool m_isMapped; + BufferMappingAccessBit m_mappingAccess; + UniquePtr m_dirtyRange; + }; + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/BufferState/BufferState.cpp b/MobileGL/MG_State/GLState/BufferState/BufferState.cpp new file mode 100644 index 00000000..eb47c699 --- /dev/null +++ b/MobileGL/MG_State/GLState/BufferState/BufferState.cpp @@ -0,0 +1,48 @@ +#include "../../../Includes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + void BufferObject::UploadData(DataPtr data) { + m_size = data.size; + memcpy(m_data.data(), data.data, data.size); + m_dirtyRange = MakeUnique(0, m_size); + m_dirtyRange->Extend(0, m_size); + } + + SharedPtr BufferObject::AquireMemory(Bool markMapped = true) { + if (markMapped) { + m_isMapped = true; + m_mappingAccess = BufferMappingAccessBit::Read | BufferMappingAccessBit::Write; + } + return MakeShared(m_data); + } + + SharedPtr BufferObject::AquireMemoryRange(Range1D range, BufferMappingAccessBit access) { + m_isMapped = true; + m_mappingAccess = access; + return MakeShared(m_data); + } + + void BufferObject::SetUsage(BufferUsage usage) { + m_usage = usage; + } + + SizeT BufferObject::GetSize() const { + return m_size; + } + + BufferUsage BufferObject::GetUsage() const { + return m_usage; + } + + Range1D BufferObject::GetDirtyRange() const { + return *m_dirtyRange; + } + + Bool BufferObject::IsMapped() const { + return m_isMapped; + } + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/BufferState/BufferState.h b/MobileGL/MG_State/GLState/BufferState/BufferState.h new file mode 100644 index 00000000..63cc3e5f --- /dev/null +++ b/MobileGL/MG_State/GLState/BufferState/BufferState.h @@ -0,0 +1,34 @@ +#pragma once + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class BufferState { + public: + SharedPtr GetBufferObjectByIndex(Uint index) { + auto it = m_bufferObjects.find(index); + if (it != m_bufferObjects.end()) { + return it->second; + } + return nullptr; + } + + Vector GenerateByNum(Uint number) { + Vector buffers; + m_indexGenerator.Generate(number, reinterpret_cast(&buffers)); + return buffers; + } + + SharedPtr CreateBufferObject(Uint index) { + auto bufferObject = MakeShared(); + m_bufferObjects[index] = bufferObject; + return bufferObject; + } + + private: + UnorderedMap> m_bufferObjects; + IndexGenerator m_indexGenerator; + }; + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp new file mode 100644 index 00000000..0b8af78e --- /dev/null +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -0,0 +1 @@ +#include "../../Includes.h" diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h new file mode 100644 index 00000000..e238b0fc --- /dev/null +++ b/MobileGL/MG_State/GLState/Core.h @@ -0,0 +1,23 @@ +#pragma once + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class GLContext { + public: + GLContext() = default; + + // Buffer + Vector GenBuffersByNum(Uint number); + SharedPtr GetBufferObjByIndex(Uint index); + SharedPtr GetBufferObjByTarget(BufferTarget target); + SharedPtr CreateBufferObject(Uint index); + void BindBufferTarget(BufferTarget target, SharedPtr bufferObject); + + private: + // Buffer + BufferState bufferState_; + }; + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_Util/Miscellany/IndexGenerator.h b/MobileGL/MG_Util/Miscellany/IndexGenerator.h new file mode 100644 index 00000000..c1b5a713 --- /dev/null +++ b/MobileGL/MG_Util/Miscellany/IndexGenerator.h @@ -0,0 +1,52 @@ +#pragma once + +namespace MobileGL { + template + class IndexGenerator { + public: + IndexGenerator() : next_index_(1) {} + explicit IndexGenerator(IndexType n) : next_index_(1) { + is_valid_.reserve(n); + } + + void Generate(size_t n, IndexType* indices) { + if (n <= 0) { + return; + } + + size_t count_from_freed = std::min(n, freed_indices_.size()); + for (size_t i = 0; i < count_from_freed; ++i) { + indices[i] = freed_indices_.back(); + freed_indices_.pop_back(); + if (indices[i] >= is_valid_.size()) { + is_valid_.resize(static_cast(indices[i]) + 1, false); + } + is_valid_[indices[i]] = true; + } + + for (size_t i = count_from_freed; i < n; ++i) { + indices[i] = next_index_++; + if (indices[i] >= is_valid_.size()) { + is_valid_.resize(static_cast(indices[i]) + 1, false); + } + is_valid_[indices[i]] = true; + } + } + + void Delete(IndexType index) { + if (index < is_valid_.size() && is_valid_[index] == true) { + is_valid_[index] = false; + freed_indices_.push_back(index); + } + } + + bool IsValid(IndexType index) const { + return index < is_valid_.size() && is_valid_[index] == true; + } + + private: + IndexType next_index_; + std::vector freed_indices_; + std::vector is_valid_; + }; +} \ No newline at end of file diff --git a/MobileGL/MG_Util/Types.h b/MobileGL/MG_Util/Types.h index 449ec945..94d24649 100644 --- a/MobileGL/MG_Util/Types.h +++ b/MobileGL/MG_Util/Types.h @@ -58,6 +58,41 @@ namespace MobileGL { SizeT size; }; + enum class DataType { + Int8, + Uint8, + Int16, + Uint16, + Int32, + Uint32, + Float16, + Float32, + Float64, + Fixed32 + }; + + struct Range1D { + const SizeT maxEnd; + const SizeT minStart; + SizeT start; + SizeT end; + + Range1D(SizeT minStart_, SizeT maxEnd_) + : minStart(minStart_), maxEnd(maxEnd_), start(minStart_), end(minStart_) { + if (minStart_ >= maxEnd_) { + throw RuntimeError("Invalid range: minStart must be less than maxEnd"); + } + } + + void Extend(SizeT newStart, SizeT newEnd) { + if (newStart < minStart || newEnd > maxEnd) { + throw RuntimeError("Range exceeds bounds"); + } + start = std::min(start, newStart); + end = std::max(end, newEnd); + } + }; + struct Version { Int Major; Int Minor;