diff --git a/CMakeLists.txt b/CMakeLists.txt index ddc5e619..0ecb5d30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,6 +159,7 @@ set(SOURCE_FILES MobileGL/MG_State/GLState/BufferState/BufferObject.cpp MobileGL/MG_State/GLState/VertexArrayState/VertexArrayState.cpp MobileGL/MG_State/GLState/VertexArrayState/VertexArrayObject.cpp + MobileGL/MG_State/GLState/TextureState/MipmapStorage.cpp MobileGL/MG_State/GLState/TextureState/TextureObject.cpp MobileGL/MG_State/GLState/TextureState/TextureObject1D.cpp MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp diff --git a/MobileGL/MG_State/GLState/TextureState/MipmapStorage.cpp b/MobileGL/MG_State/GLState/TextureState/MipmapStorage.cpp new file mode 100644 index 00000000..413b6881 --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/MipmapStorage.cpp @@ -0,0 +1,63 @@ +#include "MipmapStorage.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + SizeT MipmapStorage::GetLevelCount() const { + return m_data.size(); + } + + void MipmapStorage::AllocateLevel(Uint level, MipmapInput input) { + m_data.reserve(std::bit_ceil(level + 1)); + m_data.resize(level + 1); + m_texelSizes.reserve(std::bit_ceil(level + 1)); + m_texelSizes.resize(level + 1); + m_texelSizes[level] = input.texelSize; + m_isDirty.resize(level + 1, false); + + auto& data = m_data[level]; + data.resize(input.byteSize, 0); + } + + void MipmapStorage::UpdateSubData(Uint level, DataPtr input) { + auto& targetData = m_data; + MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range"); + auto& levelData = targetData[level]; + MOBILEGL_ASSERT(levelData.size() <= input.size, "UpdateSubData: input data larger than allocated"); + + if (input.data && input.size > 0) { + const Uint8* src = static_cast(input.data); + Memcpy(levelData.data(), src, input.size); + m_isDirty[level] = true; + } + } + + void* MipmapStorage::MapData(Uint level) { + auto& targetData = m_data; + MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range"); + auto& levelData = targetData[level]; + return levelData.data(); + } + + IntVec3 MipmapStorage::GetTexelSize(Uint level) const { + auto& targetTexelSizes = m_texelSizes; + if (level >= targetTexelSizes.size()) return {0, 0, 0}; + return targetTexelSizes[level]; + } + + SizeT MipmapStorage::GetByteSize(Uint level) const { + return m_data[level].size(); + } + + void MipmapStorage::MarkDirty(Uint level, bool dirty) { + MOBILEGL_ASSERT(level < m_isDirty.size(), "MarkDirty: level out of range"); + m_isDirty[level] = dirty; + } + + bool MipmapStorage::IsDirty(Uint level) const { + MOBILEGL_ASSERT(level < m_isDirty.size(), "IsDirty: level out of range"); + return m_isDirty[level]; + } + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h b/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h new file mode 100644 index 00000000..105d7080 --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h @@ -0,0 +1,27 @@ +#pragma once +#include "TextureEnum.h" +#include "MG_Util/Types.h" +#include "MG_Util/Math/VectorTypes.h" +#include "TextureTypes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class MipmapStorage { + public: + SizeT GetLevelCount() const; + void AllocateLevel(Uint level, MipmapInput input); + void UpdateSubData(Uint level, DataPtr input); + void* MapData(Uint level); + IntVec3 GetTexelSize(Uint level) const; + SizeT GetByteSize(Uint level) const; + void MarkDirty(Uint level, bool dirty); + bool IsDirty(Uint level) const; + protected: + Vector m_texelSizes; + Vector> m_data; + Vector m_isDirty; + }; + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h b/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h new file mode 100644 index 00000000..27d9f761 --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h @@ -0,0 +1,64 @@ +#pragma once +#include "MipmapStorage.h" +#include "TextureEnum.h" +#include "MG_Util/Types.h" +#include "MG_Util/Math/VectorTypes.h" +#include "TextureTypes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + template + class MipmapUploadTargetArray { + public: + MipmapUploadTargetArray() { static_assert(TargetCount > 0, "Upload target count must be greater than zero"); } + + void AllocateLevel(Uint targetIndex, Uint level, MipmapInput input) { + MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid"); + + m_storage[targetIndex].AllocateLevel(level, input); + } + + void UpdateSubData(Uint targetIndex, Uint level, DataPtr input) { + MOBILEGL_ASSERT(targetIndex < TargetCount, "UpdateSubData: target invalid"); + m_storage[targetIndex].UpdateSubData(level, input); + } + + void* MapData(Uint targetIndex, Uint level) { + MOBILEGL_ASSERT(targetIndex < TargetCount, "UpdateSubData: target invalid"); + return m_storage[targetIndex].MapData(level); + } + + IntVec3 GetTexelSize(Uint targetIndex, Uint level) const { + MOBILEGL_ASSERT(targetIndex < TargetCount, "GetTexelSize: target invalid"); + + return m_storage[targetIndex].GetTexelSize(level); + } + + SizeT GetByteSize(Uint targetIndex, Uint level) const { + MOBILEGL_ASSERT(targetIndex < TargetCount, "GetByteSize: target invalid"); + + return m_storage[targetIndex].GetByteSize(level); + } + + SizeT GetLevelCount() const { + static_assert(TargetCount > 0, "Upload target count must be greater than zero"); + return m_storage[0].GetLevelCount(); + } + + void MarkDirty(Uint targetIndex, Uint level, bool dirty) { + MOBILEGL_ASSERT(targetIndex < TargetCount, "MarkDirty: target invalid"); + m_storage[targetIndex].MarkDirty(level, dirty); + } + + bool IsDirty(Uint targetIndex, Uint level) const { + MOBILEGL_ASSERT(targetIndex < TargetCount, "IsDirty: target invalid"); + return m_storage[targetIndex].IsDirty(level); + } + + protected: + Array m_storage; + }; + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h index 13e0f11d..c71517ee 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h @@ -18,7 +18,7 @@ namespace MobileGL { }; // Don't tinker with order in this enum (especially CubeMap faces), - // it is used in TextureStorage + // it is used in MipmapUploadTargetArray enum class TextureUploadTarget { Texture1D, Texture2D, diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index 9d3a1c77..e7c5854b 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -1,6 +1,6 @@ #pragma once #include "TextureEnum.h" -#include "TextureStorage.h" +#include "MipmapUploadTargetArray.h" #include "MG_Util/Types.h" #include "../SamplerState/SamplerObject.h" #include @@ -106,7 +106,7 @@ namespace MobileGL { Bool IsComplete() const override; protected: - TextureStorage<1> m_textureStorage; + MipmapUploadTargetArray<1> m_textureStorage; }; } // namespace GLState } // namespace MG_State diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h index 08f603ba..a5c6207e 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h @@ -24,7 +24,7 @@ namespace MobileGL { protected: Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; - TextureStorage<6> m_textureStorage; + MipmapUploadTargetArray<6> m_textureStorage; const Vector m_uploadTargets{ TextureUploadTarget::CubeMapPositiveX, TextureUploadTarget::CubeMapNegativeX, TextureUploadTarget::CubeMapPositiveY, TextureUploadTarget::CubeMapNegativeY, diff --git a/MobileGL/MG_State/GLState/TextureState/TextureStorage.h b/MobileGL/MG_State/GLState/TextureState/TextureStorage.h deleted file mode 100644 index f140c2b8..00000000 --- a/MobileGL/MG_State/GLState/TextureState/TextureStorage.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once -#include "TextureEnum.h" -#include "MG_Util/Types.h" -#include "MG_Util/Math/VectorTypes.h" - -namespace MobileGL { - namespace MG_State { - namespace GLState { - struct MipmapInput { - IntVec3 texelSize = {0, 0, 0}; - SizeT byteSize = 0; - }; - - template - class TextureStorage { - public: - TextureStorage() { static_assert(TargetCount > 0, "Mipmap size must be greater than zero"); } - - void AllocateLevel(Uint targetIndex, Uint level, MipmapInput input) { - MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid"); - - auto& targetData = m_data[targetIndex]; - targetData.reserve(std::bit_ceil(level + 1)); - targetData.resize(level + 1); - auto& targetTexelSizes = m_texelSizes[targetIndex]; - targetTexelSizes.reserve(std::bit_ceil(level + 1)); - targetTexelSizes.resize(level + 1); - targetTexelSizes[level] = input.texelSize; - auto& dirtyArr = m_isDirty[targetIndex]; - dirtyArr.resize(level + 1, false); - - auto& data = targetData[level]; - data.resize(input.byteSize, 0); - } - - void UpdateSubData(Uint targetIndex, Uint level, DataPtr input) { - MOBILEGL_ASSERT(targetIndex < TargetCount, "UpdateSubData: target invalid"); - auto& targetData = m_data[targetIndex]; - MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range"); - auto& levelData = targetData[level]; - MOBILEGL_ASSERT(levelData.size() <= input.size, "UpdateSubData: input data larger than allocated"); - - if (input.data && input.size > 0) { - const Uint8* src = static_cast(input.data); - Memcpy(levelData.data(), src, input.size); - m_isDirty[targetIndex][level] = true; - } - } - - void* MapData(Uint targetIndex, Uint level) { - MOBILEGL_ASSERT(targetIndex < TargetCount, "UpdateSubData: target invalid"); - auto& targetData = m_data[targetIndex]; - MOBILEGL_ASSERT(level < targetData.size(), "UpdateSubData: level out of range"); - auto& levelData = targetData[level]; - return levelData.data(); - } - - IntVec3 GetTexelSize(Uint targetIndex, Uint level) const { - MOBILEGL_ASSERT(targetIndex < TargetCount, "GetTexelSize: target invalid"); - - auto& targetTexelSizes = m_texelSizes[targetIndex]; - if (level >= targetTexelSizes.size()) return {0, 0, 0}; - return targetTexelSizes[level]; - } - - SizeT GetByteSize(Uint targetIndex, Uint level) const { - MOBILEGL_ASSERT(targetIndex < TargetCount, "GetByteSize: target invalid"); - - auto& data = m_data[targetIndex]; - return data[level].size(); - } - - SizeT GetLevelCount() const { return m_data[0].size(); } - - void MarkDirty(Uint targetIndex, Uint level, bool dirty) { - MOBILEGL_ASSERT(targetIndex < TargetCount, "MarkDirty: target invalid"); - MOBILEGL_ASSERT(level < m_isDirty[targetIndex].size(), "MarkDirty: level out of range"); - m_isDirty[targetIndex][level] = dirty; - } - - bool IsDirty(Uint targetIndex, Uint level) const { - MOBILEGL_ASSERT(targetIndex < TargetCount, "IsDirty: target invalid"); - MOBILEGL_ASSERT(level < m_isDirty[targetIndex].size(), "IsDirty: level out of range"); - return m_isDirty[targetIndex][level]; - } - - protected: - Array, TargetCount> m_texelSizes; - Array>, TargetCount> m_data; - Array, TargetCount> m_isDirty; - }; - } // namespace GLState - } // namespace MG_State -} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/TextureTypes.h b/MobileGL/MG_State/GLState/TextureState/TextureTypes.h new file mode 100644 index 00000000..b51a10d0 --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureTypes.h @@ -0,0 +1,14 @@ +#pragma once +#include "MG_Util/Types.h" +#include "MG_Util/Math/VectorTypes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + struct MipmapInput { + IntVec3 texelSize = {0, 0, 0}; + SizeT byteSize = 0; + }; + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL