mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Refactor] (MG_State/Texture): decouple texture object and mipmap storage
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<const Uint8*>(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
|
||||
@@ -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<IntVec3> m_texelSizes;
|
||||
Vector<Vector<Uint8>> m_data;
|
||||
Vector<bool> m_isDirty;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -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 <SizeT TargetCount>
|
||||
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<MipmapStorage, TargetCount> m_storage;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -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,
|
||||
|
||||
@@ -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 <Includes.h>
|
||||
@@ -106,7 +106,7 @@ namespace MobileGL {
|
||||
Bool IsComplete() const override;
|
||||
|
||||
protected:
|
||||
TextureStorage<1> m_textureStorage;
|
||||
MipmapUploadTargetArray<1> m_textureStorage;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace MobileGL {
|
||||
|
||||
protected:
|
||||
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
|
||||
TextureStorage<6> m_textureStorage;
|
||||
MipmapUploadTargetArray<6> m_textureStorage;
|
||||
const Vector<TextureUploadTarget> m_uploadTargets{
|
||||
TextureUploadTarget::CubeMapPositiveX, TextureUploadTarget::CubeMapNegativeX,
|
||||
TextureUploadTarget::CubeMapPositiveY, TextureUploadTarget::CubeMapNegativeY,
|
||||
|
||||
@@ -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 <SizeT TargetCount>
|
||||
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<const Uint8*>(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<Vector<IntVec3>, TargetCount> m_texelSizes;
|
||||
Array<Vector<Vector<Uint8>>, TargetCount> m_data;
|
||||
Array<Vector<bool>, TargetCount> m_isDirty;
|
||||
};
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user