mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Optimization] (TextureState): block memcpy
This commit is contained in:
@@ -416,12 +416,7 @@ namespace MG_GL::GL {
|
|||||||
case GL_TEXTURE_2D: {
|
case GL_TEXTURE_2D: {
|
||||||
GLenum internalFormat = 0, type = 0, format = 0;
|
GLenum internalFormat = 0, type = 0, format = 0;
|
||||||
NormalizePixelFormat(mip.internalFormat, mip.type, mip.format, &internalFormat, &type, &format);
|
NormalizePixelFormat(mip.internalFormat, mip.type, mip.format, &internalFormat, &type, &format);
|
||||||
//
|
|
||||||
// GLenum type = mip.type;
|
|
||||||
// // Mali cannot use GL_FLOAT as depth format
|
|
||||||
// if (mip.internalFormat == GL_DEPTH_COMPONENT) {
|
|
||||||
// type = GL_UNSIGNED_INT;
|
|
||||||
// }
|
|
||||||
CallAndCheck(::GLES::glTexImage2D(
|
CallAndCheck(::GLES::glTexImage2D(
|
||||||
target, level, internalFormat,
|
target, level, internalFormat,
|
||||||
mip.width, mip.height, 0,
|
mip.width, mip.height, 0,
|
||||||
@@ -446,6 +441,8 @@ namespace MG_GL::GL {
|
|||||||
if (!s_textureLevelUploaded[mgTexId][level]) {
|
if (!s_textureLevelUploaded[mgTexId][level]) {
|
||||||
bool levelInitialized = s_textureLevelUploaded[mgTexId].count(level);
|
bool levelInitialized = s_textureLevelUploaded[mgTexId].count(level);
|
||||||
const void* data = !mip.pixelData.empty() ? mip.pixelData.data() : nullptr;
|
const void* data = !mip.pixelData.empty() ? mip.pixelData.data() : nullptr;
|
||||||
|
GLenum internalFormat = 0, type = 0, format = 0;
|
||||||
|
NormalizePixelFormat(mip.internalFormat, mip.type, mip.format, &internalFormat, &type, &format);
|
||||||
|
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case GL_TEXTURE_2D:
|
case GL_TEXTURE_2D:
|
||||||
@@ -454,15 +451,15 @@ namespace MG_GL::GL {
|
|||||||
target, level,
|
target, level,
|
||||||
0, 0,
|
0, 0,
|
||||||
mip.width, mip.height,
|
mip.width, mip.height,
|
||||||
mip.format, mip.type, data
|
format, type, data
|
||||||
);)
|
);)
|
||||||
s_textureLevelUploaded[mgTexId][level] = true;
|
s_textureLevelUploaded[mgTexId][level] = true;
|
||||||
MG_Util::Debug::LogD("Updated texture %u level %d with glTexSubImage2D", mgTexId, level);
|
MG_Util::Debug::LogD("Updated texture %u level %d with glTexSubImage2D", mgTexId, level);
|
||||||
} else {
|
} else {
|
||||||
CallAndCheck(::GLES::glTexImage2D(
|
CallAndCheck(::GLES::glTexImage2D(
|
||||||
target, level, mip.internalFormat,
|
target, level, internalFormat,
|
||||||
mip.width, mip.height, 0,
|
mip.width, mip.height, 0,
|
||||||
mip.format, mip.type, data
|
format, type, data
|
||||||
);)
|
);)
|
||||||
s_textureLevelUploaded[mgTexId][level] = true;
|
s_textureLevelUploaded[mgTexId][level] = true;
|
||||||
MG_Util::Debug::LogD("Initialized texture %u level %d with glTexImage2D", mgTexId, level);
|
MG_Util::Debug::LogD("Initialized texture %u level %d with glTexImage2D", mgTexId, level);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
// TextureObject
|
// TextureObject
|
||||||
|
|
||||||
bool TextureObject::IsImmutable() const {
|
bool TextureObject::IsImmutable() const {
|
||||||
bool immutable = params.texPropertiesInt.count(GL_TEXTURE_IMMUTABLE_FORMAT);
|
bool immutable = params.texPropertiesInt.find(GL_TEXTURE_IMMUTABLE_FORMAT) != params.texPropertiesInt.end();
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: TextureObject::IsImmutable returns %d", immutable);
|
MG_Util::Debug::LogD("MG_State: Texture: TextureObject::IsImmutable returns %d", immutable);
|
||||||
return immutable;
|
return immutable;
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ bool TextureState::IsTextureGenerated(GLuint texture) {
|
|||||||
if (!isValidTexture) {
|
if (!isValidTexture) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated invalid texture %d", texture);
|
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated invalid texture %d", texture);
|
||||||
} else {
|
} else {
|
||||||
generated = textures.at(texture).generated;
|
generated = textures[texture].generated;
|
||||||
if (!generated) {
|
if (!generated) {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture %d not generated", texture, generated);
|
MG_Util::Debug::LogD("MG_State: Texture: IsTextureGenerated texture %d not generated", texture, generated);
|
||||||
}
|
}
|
||||||
@@ -101,12 +101,12 @@ GLenum TextureState::CreateN(GLsizei n, GLuint* textures) {
|
|||||||
|
|
||||||
for (GLsizei i = 0; i < n; ++i) {
|
for (GLsizei i = 0; i < n; ++i) {
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
if (!freeIDs_.empty()) {
|
if (!freeID_.empty()) {
|
||||||
id = *freeIDs_.begin();
|
id = freeID_.back();
|
||||||
freeIDs_.erase(freeIDs_.begin());
|
freeID_.pop_back();
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN reusing free id=%u", id);
|
MG_Util::Debug::LogD("MG_State: Texture: CreateN reusing free id=%u", id);
|
||||||
} else {
|
} else {
|
||||||
id = ++lastUsedID_;
|
id = lastUsedID_++;
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: CreateN new id=%u", id);
|
MG_Util::Debug::LogD("MG_State: Texture: CreateN new id=%u", id);
|
||||||
}
|
}
|
||||||
TextureObject obj;
|
TextureObject obj;
|
||||||
@@ -272,13 +272,19 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
|
|
||||||
GLuint boundTex = textureUnits_[activeTextureUnit_].GetBoundTexture(target);
|
GLuint boundTex = textureUnits_[activeTextureUnit_].GetBoundTexture(target);
|
||||||
TextureObject& tex = textures[boundTex];
|
TextureObject& tex = textures[boundTex];
|
||||||
TextureParams::MipmapLevel mip{};
|
// TextureParams::MipmapLevel mip{};
|
||||||
|
|
||||||
|
auto& mip = tex.params.mipmapData[level];
|
||||||
mip.width = width;
|
mip.width = width;
|
||||||
mip.height = height;
|
mip.height = height;
|
||||||
mip.internalFormat = internalFormat;
|
mip.internalFormat = internalFormat;
|
||||||
mip.format = format;
|
mip.format = format;
|
||||||
mip.type = type;
|
mip.type = type;
|
||||||
if (data != nullptr) {
|
|
||||||
|
if (data == nullptr) {
|
||||||
|
mip.hasData = false;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Texture: Upload2D data pointer is null");
|
||||||
|
} else {
|
||||||
GLint unpackSwapBytes = GetUnpackParam_(GL_UNPACK_SWAP_BYTES);
|
GLint unpackSwapBytes = GetUnpackParam_(GL_UNPACK_SWAP_BYTES);
|
||||||
GLint unpackLSBFirst = GetUnpackParam_(GL_UNPACK_LSB_FIRST);
|
GLint unpackLSBFirst = GetUnpackParam_(GL_UNPACK_LSB_FIRST);
|
||||||
GLint unpackSkipPixels = GetUnpackParam_(GL_UNPACK_SKIP_PIXELS);
|
GLint unpackSkipPixels = GetUnpackParam_(GL_UNPACK_SKIP_PIXELS);
|
||||||
@@ -288,47 +294,69 @@ GLenum TextureState::Upload2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
GLint unpackImageHeight = GetUnpackParam_(GL_UNPACK_IMAGE_HEIGHT);
|
GLint unpackImageHeight = GetUnpackParam_(GL_UNPACK_IMAGE_HEIGHT);
|
||||||
GLint unpackSkipImages = GetUnpackParam_(GL_UNPACK_SKIP_IMAGES);
|
GLint unpackSkipImages = GetUnpackParam_(GL_UNPACK_SKIP_IMAGES);
|
||||||
|
|
||||||
GLsizei rowLength = (unpackRowLength > 0) ? unpackRowLength : width;
|
bool isDefaultUnpack = (unpackSwapBytes == 0) && (unpackLSBFirst == 0) &&
|
||||||
|
(unpackSkipPixels == 0) && (unpackSkipRows == 0) &&
|
||||||
|
(unpackRowLength == 0) && (unpackAlignment == 4) &&
|
||||||
|
(unpackImageHeight == 0) && (unpackSkipImages == 0);
|
||||||
|
|
||||||
size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
size_t bytesPerPixel = CalculateBytesPerPixel_(format, type);
|
||||||
size_t componentSize = GetComponentSize_(type);
|
size_t componentSize = GetComponentSize_(type);
|
||||||
|
|
||||||
size_t srcRowSize = rowLength * bytesPerPixel;
|
|
||||||
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
|
||||||
size_t srcImageStride = (unpackImageHeight > 0) ?
|
|
||||||
srcRowStride * unpackImageHeight :
|
|
||||||
srcRowStride * height;
|
|
||||||
|
|
||||||
const GLubyte* srcData = static_cast<const GLubyte*>(data);
|
|
||||||
srcData += unpackSkipImages * srcImageStride;
|
|
||||||
srcData += unpackSkipRows * srcRowStride;
|
|
||||||
srcData += unpackSkipPixels * bytesPerPixel;
|
|
||||||
|
|
||||||
size_t dstRowStride = width * bytesPerPixel;
|
size_t dstRowStride = width * bytesPerPixel;
|
||||||
size_t dstSize = dstRowStride * height;
|
size_t dstSize = dstRowStride * height;
|
||||||
mip.pixelData.resize(dstSize);
|
mip.pixelData.resize(dstSize);
|
||||||
GLubyte* dstData = mip.pixelData.data();
|
GLubyte *dstData = mip.pixelData.data();
|
||||||
|
|
||||||
for (GLsizei y = 0; y < height; ++y) {
|
if (isDefaultUnpack) {
|
||||||
const GLubyte* srcRow = srcData + y * srcRowStride;
|
const GLubyte *srcData = static_cast<const GLubyte *>(data);
|
||||||
GLubyte* dstRow = dstData + y * dstRowStride;
|
size_t srcRowSize = width * bytesPerPixel;
|
||||||
|
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
||||||
|
|
||||||
if (unpackSwapBytes) {
|
if (srcRowStride == dstRowStride) {
|
||||||
SwapBytesForTexture_(format, type, srcRow, dstRow, width);
|
memcpy(dstData, srcData, dstSize);
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
"MG_State: Texture: Upload2D uploaded %zu bytes with fast path - block memcpy", dstSize);
|
||||||
|
} else {
|
||||||
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
const GLubyte *srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte *dstRow = dstData + y * dstRowStride;
|
||||||
|
memcpy(dstRow, srcRow, srcRowSize);
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
"MG_State: Texture: Upload2D uploaded %zu bytes with fast path - row memcpy", dstSize);
|
||||||
}
|
}
|
||||||
else if (unpackLSBFirst && componentSize == 1) {
|
} else {
|
||||||
ReverseBitOrder_(srcRow, dstRow, width * bytesPerPixel);
|
GLsizei rowLength = (unpackRowLength > 0) ? unpackRowLength : width;
|
||||||
}
|
|
||||||
else {
|
size_t srcRowSize = rowLength * bytesPerPixel;
|
||||||
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
size_t srcRowStride = (srcRowSize + unpackAlignment - 1) & ~(unpackAlignment - 1);
|
||||||
|
size_t srcImageStride = (unpackImageHeight > 0) ?
|
||||||
|
srcRowStride * unpackImageHeight :
|
||||||
|
srcRowStride * height;
|
||||||
|
|
||||||
|
const GLubyte *srcData = static_cast<const GLubyte *>(data);
|
||||||
|
srcData += unpackSkipImages * srcImageStride;
|
||||||
|
srcData += unpackSkipRows * srcRowStride;
|
||||||
|
srcData += unpackSkipPixels * bytesPerPixel;
|
||||||
|
|
||||||
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
const GLubyte *srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte *dstRow = dstData + y * dstRowStride;
|
||||||
|
|
||||||
|
if (unpackSwapBytes) {
|
||||||
|
SwapBytesForTexture_(format, type, srcRow, dstRow, width);
|
||||||
|
} else if (unpackLSBFirst && componentSize == 1) {
|
||||||
|
ReverseBitOrder_(srcRow, dstRow, width * bytesPerPixel);
|
||||||
|
} else {
|
||||||
|
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mip.hasData = true;
|
||||||
|
MG_Util::Debug::LogD(
|
||||||
|
"MG_State: Texture: Upload2D uploaded %zu bytes with unpack params", dstSize);
|
||||||
}
|
}
|
||||||
mip.hasData = true;
|
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D uploaded %zu bytes with unpack params", dstSize);
|
|
||||||
} else {
|
|
||||||
mip.hasData = false;
|
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Upload2D data pointer is null");
|
|
||||||
}
|
}
|
||||||
tex.params.mipmapData[level] = mip;
|
// tex.params.mipmapData[level] = mip;
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,26 +430,66 @@ GLenum TextureState::UpdateRegion2D(GLenum target, GLint level, GLint xoffset,
|
|||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D srcData=%p, dstData=%p", srcData, dstData);
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D srcData=%p, dstData=%p", srcData, dstData);
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D bytesPerPixel=%zu", bytesPerPixel);
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D bytesPerPixel=%zu", bytesPerPixel);
|
||||||
|
|
||||||
for (GLsizei y = 0; y < height; ++y) {
|
// Check if fast path is applicable
|
||||||
const GLubyte* srcRow = srcData + y * srcRowStride;
|
const bool isDefaultUnpack = (unpackSwapBytes == 0) && (unpackLSBFirst == 0) &&
|
||||||
GLubyte* dstRow = dstData + y * dstRowStride;
|
(unpackRowLength == 0) && (unpackAlignment == 4) &&
|
||||||
|
(unpackSkipPixels == 0) && (unpackSkipRows == 0) &&
|
||||||
|
(unpackImageHeight == 0) && (unpackSkipImages == 0);
|
||||||
|
|
||||||
if (unpackSwapBytes) {
|
if (isDefaultUnpack) {
|
||||||
for (GLsizei x = 0; x < width; ++x) {
|
const size_t copySize = width * bytesPerPixel;
|
||||||
const GLubyte* srcPixel = srcRow + x * bytesPerPixel;
|
|
||||||
GLubyte* dstPixel = dstRow + x * bytesPerPixel;
|
if (srcRowStride == dstRowStride) {
|
||||||
SwapPixelBytes_(format, type, srcPixel, dstPixel);
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D block memcpy(dst=%p, src=%p, size=%zu) called.", dstData, srcData, width * bytesPerPixel);
|
||||||
}
|
memcpy(dstData, srcData, copySize * height);
|
||||||
} else if (unpackLSBFirst && GetComponentSize_(type) == 1) {
|
|
||||||
for (size_t i = 0; i < width * bytesPerPixel; ++i) {
|
|
||||||
dstRow[i] = ReverseBits_(srcRow[i]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D memcpy(dst=%p, src=%p, size=%zu) called.", dstRow, srcRow, width * bytesPerPixel);
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte* dstRow = dstData + y * dstRowStride;
|
||||||
|
memcpy(dstRow, srcRow, copySize);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D row memcpy(dst=%p, src=%p, size=%zu) called.", dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const size_t componentSize = GetComponentSize_(type);
|
||||||
|
for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||||
|
GLubyte* dstRow = dstData + y * dstRowStride;
|
||||||
|
|
||||||
|
if (unpackSwapBytes) {
|
||||||
|
for (GLsizei x = 0; x < width; ++x) {
|
||||||
|
SwapPixelBytes_(format, type, srcRow + x*bytesPerPixel, dstRow + x*bytesPerPixel);
|
||||||
|
}
|
||||||
|
} else if (unpackLSBFirst && componentSize == 1) {
|
||||||
|
for (size_t i = 0; i < width * bytesPerPixel; ++i) {
|
||||||
|
dstRow[i] = ReverseBits_(srcRow[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for (GLsizei y = 0; y < height; ++y) {
|
||||||
|
// const GLubyte* srcRow = srcData + y * srcRowStride;
|
||||||
|
// GLubyte* dstRow = dstData + y * dstRowStride;
|
||||||
|
//
|
||||||
|
// if (unpackSwapBytes) {
|
||||||
|
// for (GLsizei x = 0; x < width; ++x) {
|
||||||
|
// const GLubyte* srcPixel = srcRow + x * bytesPerPixel;
|
||||||
|
// GLubyte* dstPixel = dstRow + x * bytesPerPixel;
|
||||||
|
// SwapPixelBytes_(format, type, srcPixel, dstPixel);
|
||||||
|
// }
|
||||||
|
// } else if (unpackLSBFirst && GetComponentSize_(type) == 1) {
|
||||||
|
// for (size_t i = 0; i < width * bytesPerPixel; ++i) {
|
||||||
|
// dstRow[i] = ReverseBits_(srcRow[i]);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D memcpy(dst=%p, src=%p, size=%zu) called.", dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
// memcpy(dstRow, srcRow, width * bytesPerPixel);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
mip.hasData = true;
|
mip.hasData = true;
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D succeeded");
|
MG_Util::Debug::LogD("MG_State: Texture: UpdateRegion2D succeeded");
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
@@ -541,7 +609,7 @@ GLenum TextureState::Delete(GLuint texture) {
|
|||||||
if (it != this->textures.end()) {
|
if (it != this->textures.end()) {
|
||||||
InvalidateTextureInAllUnits_(texture);
|
InvalidateTextureInAllUnits_(texture);
|
||||||
this->textures.erase(it);
|
this->textures.erase(it);
|
||||||
freeIDs_.insert(texture);
|
freeID_.emplace_back(texture);
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: Delete succeeded for texture=%u", texture);
|
MG_Util::Debug::LogD("MG_State: Texture: Delete succeeded for texture=%u", texture);
|
||||||
} else {
|
} else {
|
||||||
MG_Util::Debug::LogW("MG_State: Texture: Delete texture %u not found", texture);
|
MG_Util::Debug::LogW("MG_State: Texture: Delete texture %u not found", texture);
|
||||||
@@ -563,7 +631,7 @@ GLenum TextureState::DeleteN(GLsizei n, const GLuint* textures) {
|
|||||||
if (it != this->textures.end()) {
|
if (it != this->textures.end()) {
|
||||||
InvalidateTextureInAllUnits_(id);
|
InvalidateTextureInAllUnits_(id);
|
||||||
this->textures.erase(it);
|
this->textures.erase(it);
|
||||||
freeIDs_.insert(id);
|
freeID_.emplace_back(id);
|
||||||
MG_Util::Debug::LogD("MG_State: Texture: DeleteN deleted texture=%u", id);
|
MG_Util::Debug::LogD("MG_State: Texture: DeleteN deleted texture=%u", id);
|
||||||
} else {
|
} else {
|
||||||
MG_Util::Debug::LogW("MG_State: Texture: DeleteN texture %u not found", id);
|
MG_Util::Debug::LogW("MG_State: Texture: DeleteN texture %u not found", id);
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ struct ComponentSizes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TextureParams {
|
struct TextureParams {
|
||||||
std::unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
template <typename K, typename V>
|
||||||
std::unordered_map<GLenum, GLint> texPropertiesInt;
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
|
unordered_map<GLenum, GLfloat> texPropertiesFloat;
|
||||||
|
unordered_map<GLenum, GLint> texPropertiesInt;
|
||||||
struct MipmapLevel {
|
struct MipmapLevel {
|
||||||
GLsizei width = 0;
|
GLsizei width = 0;
|
||||||
GLsizei height = 0;
|
GLsizei height = 0;
|
||||||
@@ -30,7 +32,7 @@ struct TextureParams {
|
|||||||
std::vector<GLubyte> pixelData;
|
std::vector<GLubyte> pixelData;
|
||||||
bool hasData = false;
|
bool hasData = false;
|
||||||
};
|
};
|
||||||
std::unordered_map<GLint, MipmapLevel> mipmapData;
|
unordered_map<GLint, MipmapLevel> mipmapData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureObject {
|
class TextureObject {
|
||||||
@@ -44,11 +46,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class TextureUnitState {
|
class TextureUnitState {
|
||||||
|
template <typename K, typename V>
|
||||||
|
using unordered_map = ankerl::unordered_dense::map<K, V>;
|
||||||
private:
|
private:
|
||||||
GLenum activeTarget = GL_TEXTURE_2D;
|
GLenum activeTarget = GL_TEXTURE_2D;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::unordered_map<GLenum, GLuint> boundTextures;
|
unordered_map<GLenum, GLuint> boundTextures;
|
||||||
void Bind(GLenum target, GLuint texture);
|
void Bind(GLenum target, GLuint texture);
|
||||||
GLuint GetBoundTexture(GLenum target);
|
GLuint GetBoundTexture(GLenum target);
|
||||||
};
|
};
|
||||||
@@ -59,8 +63,9 @@ class TextureState {
|
|||||||
private:
|
private:
|
||||||
GLuint activeTextureUnit_ = 0;
|
GLuint activeTextureUnit_ = 0;
|
||||||
|
|
||||||
GLuint lastUsedID_ = 0;
|
GLuint lastUsedID_ = 1;
|
||||||
std::unordered_set<GLuint> freeIDs_;
|
// std::unordered_set<GLuint> freeIDs_;
|
||||||
|
std::vector<GLuint> freeID_;
|
||||||
|
|
||||||
unordered_map<GLenum, TextureObject> proxyTextures_;
|
unordered_map<GLenum, TextureObject> proxyTextures_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user