[Feat] (MG_State/Texture, MG_Impl/Texture): glTexBuffer (and implement TextureObjectBuffer accordingly)

This commit is contained in:
2025-12-09 21:20:39 +08:00
parent 3f36248638
commit cb4e6b5f19
13 changed files with 118 additions and 31 deletions
+1
View File
@@ -165,6 +165,7 @@ set(SOURCE_FILES
MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp
MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp
MobileGL/MG_State/GLState/TextureState/TextureObject3D.cpp
MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp
MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp
MobileGL/MG_State/GLState/TextureState/TextureState.cpp
MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp
@@ -750,9 +750,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto textureObject = bindingSlot.GetBoundObject();
textureObject->SetInternalFormat(mglInternalFormat);
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get()),
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
textureMipmapObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0});
}
+1 -1
View File
@@ -295,7 +295,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
static_cast<SizeT>(baseSize.z()), 0};
switch (stateTextureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(stateTextureObject.get());
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(stateTextureObject.get());
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
currentTextureInfo.mipmapLevels = mipmapCount;
+56 -15
View File
@@ -7,6 +7,8 @@
#include "MG_Util/Types.h"
#include "Validators.h"
#include "ProxyTexture.h"
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
#include <MG_State/GLState/Core.h>
#include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_State/GLState/ErrorState/Error.h>
@@ -68,9 +70,9 @@ namespace MobileGL {
// Assert this for extra safety.
// This should automatically compiled out in release,
// so that we don't take the perf hit of dyn-cast.
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get()),
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level);
SizeT imageSize = 0;
@@ -403,9 +405,9 @@ namespace MobileGL {
reinterpret_cast<SizeT>(pixels);
}
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get()),
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get()),
"Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
// Allocate in TextureObject
@@ -442,9 +444,48 @@ namespace MobileGL {
THROW_UNIMPL_EXCEPTION;
}
void TexBuffer_State(GLenum target, GLenum internalformat, GLuint texture) {
// TODO: implement
THROW_UNIMPL_EXCEPTION;
void TexBuffer_State(GLenum target, GLenum internalformat, GLuint buffer) {
// ======================= Converting ================================
TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target);
TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
// ===================== Error Checking ==============================
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return;
if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return;
// TODO: make sure `internalformat` is in one of supported format for TexBuffer
auto bufferObject = MG_State::pGLContext->GetBufferObject(buffer);
if (!bufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`buffer` is not zero and is not the name of an existing buffer object."));
return;
}
// ======================= Processing ================================
auto activeUnit =
MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget);
auto textureObject = bindingSlot.GetBoundObject();
// ===================== Error Checking ==============================
if (!TextureImpl::ValidateTextureObject(textureObject)) return;
if (textureObject->GetStorageType() != TextureStorageType::Buffer) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"The effective target of `texture` is not `GL_TEXTURE_BUFFER`."));
return;
}
// ======================= Processing ================================
// Now we can rest assured, and down-cast texture object to texture buffer
auto* texBufferObject = static_cast<MG_State::GLState::TextureObjectBuffer*>(textureObject.get());
auto& bufferSlot = texBufferObject->GetBufferBindingSlot();
bufferSlot.Bind(bufferObject);
texBufferObject->SetInternalFormat(textureInternalFormat);
}
GLboolean IsTexture_State(GLuint texture) {
@@ -660,7 +701,7 @@ namespace MobileGL {
if (params) {
switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
break;
}
@@ -673,7 +714,7 @@ namespace MobileGL {
if (params) {
switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break;
}
@@ -686,7 +727,7 @@ namespace MobileGL {
if (params) {
switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break;
}
@@ -750,7 +791,7 @@ namespace MobileGL {
if (params) {
switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
break;
}
@@ -763,7 +804,7 @@ namespace MobileGL {
if (params) {
switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break;
}
@@ -776,7 +817,7 @@ namespace MobileGL {
if (params) {
switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: {
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(textureObject.get());
const auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(textureObject.get());
*params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break;
}
@@ -1017,8 +1058,8 @@ namespace MobileGL {
TexImage1D_State(target, level, internalFormat, width, border, format, type, pixels);
}
void TexBuffer(GLenum target, GLenum internalformat, GLuint texture) {
TexBuffer_State(target, internalformat, texture);
void TexBuffer(GLenum target, GLenum internalformat, GLuint buffer) {
TexBuffer_State(target, internalformat, buffer);
}
GLboolean IsTexture(GLuint texture) {
@@ -52,8 +52,8 @@ namespace MobileGL {
IntVec3 FramebufferAttachment::GetSize() const {
if (IsTexture()) {
// TODO: get correct upload target
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureMipmapObject*>(m_texture.get()), "Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureMipmapObject*>(m_texture.get());
MOBILEGL_ASSERT(nullptr != dynamic_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get()), "Texture object here should always be an object with mipmap");
auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get());
return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel);
} else if (IsRenderbuffer()) {
// TODO
@@ -38,6 +38,7 @@ namespace MobileGL {
CubeMapNegativeY,
CubeMapPositiveZ,
CubeMapNegativeZ,
TextureBuffer,
ProxyCubeMap,
CubeMapArray,
ProxyCubeMapArray,
@@ -69,9 +69,9 @@ namespace MobileGL {
UintVec2 m_levelRange = {0, 1000};
};
class TextureMipmapObject : public TextureObjectBase {
class TextureObjectMipmap : public TextureObjectBase {
public:
TextureMipmapObject(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {}
TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {}
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
@@ -85,10 +85,10 @@ namespace MobileGL {
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
};
class TextureObjectWithOneMipmap : public TextureMipmapObject {
class TextureObjectWithOneMipmap : public TextureObjectMipmap {
public:
TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex)
: TextureMipmapObject(target, externalIndex) {}
: TextureObjectMipmap(target, externalIndex) {}
virtual ~TextureObjectWithOneMipmap() = default;
Uint GetMipmapLevelCount() const override;
@@ -4,7 +4,7 @@ namespace MobileGL {
namespace MG_State {
namespace GLState {
TextureObject2DCube::TextureObject2DCube(Uint externalIndex)
: TextureMipmapObject(TextureTarget::TextureCubeMap, externalIndex) {}
: TextureObjectMipmap(TextureTarget::TextureCubeMap, externalIndex) {}
Uint TextureObject2DCube::GetMipmapLevelCount() const {
return m_textureStorage.GetLevelCount();
@@ -4,7 +4,7 @@
namespace MobileGL {
namespace MG_State {
namespace GLState {
class TextureObject2DCube : public TextureMipmapObject {
class TextureObject2DCube : public TextureObjectMipmap {
public:
explicit TextureObject2DCube(Uint externalIndex);
@@ -0,0 +1,20 @@
#include "TextureObjectBuffer.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
TextureObjectBuffer::TextureObjectBuffer(Uint externalIndex)
: TextureObjectBase(TextureTarget::TextureBuffer, externalIndex) {}
Uint TextureObjectBuffer::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const {
MOBILEGL_ASSERT(target == TextureUploadTarget::TextureBuffer, "Invalid TextureUploadTarget!");
return 0;
}
BindingSlot<BufferObject>& TextureObjectBuffer::GetBufferBindingSlot(TextureUploadTarget target) {
MOBILEGL_ASSERT(target == TextureUploadTarget::TextureBuffer, "Invalid TextureUploadTarget!");
return m_bufferBindingSlot;
}
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -0,0 +1,23 @@
#pragma once
#include "TextureObject.h"
#include "MG_State/GLState/BufferState/BufferObject.h"
namespace MobileGL {
namespace MG_State {
namespace GLState {
class TextureObjectBuffer : public TextureObjectBase {
public:
TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; }
explicit TextureObjectBuffer(Uint externalIndex);
const Vector<TextureUploadTarget>& GetUploadTargets() const override { return m_uploadTargets; }
BindingSlot<BufferObject>& GetBufferBindingSlot(TextureUploadTarget target = TextureUploadTarget::TextureBuffer);
protected:
Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override;
BindingSlot<BufferObject> m_bufferBindingSlot = BindingSlot<BufferObject>(BufferTarget::Texture);
const Vector<TextureUploadTarget> m_uploadTargets{TextureUploadTarget::TextureBuffer};
};
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -31,8 +31,8 @@ namespace MobileGL {
STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject2DMultisample, TextureTarget::Texture2DMultisample,
{TextureUploadTarget::Texture2DMultisample});
STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer,
{TextureUploadTarget::Unknown});
// STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer,
// {TextureUploadTarget::Unknown});
STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject1DArray, TextureTarget::Texture1DArray,
{TextureUploadTarget::Texture1DArray});
@@ -6,6 +6,7 @@
#include "TextureObject2D.h"
#include "TextureObject3D.h"
#include "TextureObject2DCube.h"
#include "TextureObjectBuffer.h"
#include "TextureObjectStubs.h"
namespace MobileGL {
@@ -46,6 +47,9 @@ namespace MobileGL {
case TextureTarget::Texture3D:
textureObject = MakeShared<TextureObject3D>(index);
break;
case TextureTarget::TextureBuffer:
textureObject = MakeShared<TextureObjectBuffer>(index);
break;
// These texture types are stubbed:
case TextureTarget::TextureRectangle:
@@ -54,9 +58,6 @@ namespace MobileGL {
case TextureTarget::Texture2DMultisample:
textureObject = MakeShared<TextureObject2DMultisample>(index);
break;
case TextureTarget::TextureBuffer:
textureObject = MakeShared<TextureObjectBuffer>(index);
break;
case TextureTarget::Texture1DArray:
textureObject = MakeShared<TextureObject1DArray>(index);
break;