[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/TextureObject2D.cpp
MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp
MobileGL/MG_State/GLState/TextureState/TextureObject3D.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/TextureUnit.cpp
MobileGL/MG_State/GLState/TextureState/TextureState.cpp MobileGL/MG_State/GLState/TextureState/TextureState.cpp
MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp
@@ -750,9 +750,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto textureObject = bindingSlot.GetBoundObject(); auto textureObject = bindingSlot.GetBoundObject();
textureObject->SetInternalFormat(mglInternalFormat); 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"); "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}); 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}; static_cast<SizeT>(baseSize.z()), 0};
switch (stateTextureObject->GetStorageType()) { switch (stateTextureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
currentTextureInfo.mipmapLevels = mipmapCount; currentTextureInfo.mipmapLevels = mipmapCount;
+56 -15
View File
@@ -7,6 +7,8 @@
#include "MG_Util/Types.h" #include "MG_Util/Types.h"
#include "Validators.h" #include "Validators.h"
#include "ProxyTexture.h" #include "ProxyTexture.h"
#include "MG_State/GLState/TextureState/TextureObjectBuffer.h"
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
#include <MG_Util/Metrics/TextureMetrics.h> #include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_State/GLState/ErrorState/Error.h> #include <MG_State/GLState/ErrorState/Error.h>
@@ -68,9 +70,9 @@ namespace MobileGL {
// Assert this for extra safety. // Assert this for extra safety.
// This should automatically compiled out in release, // This should automatically compiled out in release,
// so that we don't take the perf hit of dyn-cast. // 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"); "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); auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level);
SizeT imageSize = 0; SizeT imageSize = 0;
@@ -403,9 +405,9 @@ namespace MobileGL {
reinterpret_cast<SizeT>(pixels); 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"); "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 // Allocate in TextureObject
@@ -442,9 +444,48 @@ namespace MobileGL {
THROW_UNIMPL_EXCEPTION; THROW_UNIMPL_EXCEPTION;
} }
void TexBuffer_State(GLenum target, GLenum internalformat, GLuint texture) { void TexBuffer_State(GLenum target, GLenum internalformat, GLuint buffer) {
// TODO: implement // ======================= Converting ================================
THROW_UNIMPL_EXCEPTION; 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) { GLboolean IsTexture_State(GLuint texture) {
@@ -660,7 +701,7 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
break; break;
} }
@@ -673,7 +714,7 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break; break;
} }
@@ -686,7 +727,7 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break; break;
} }
@@ -750,7 +791,7 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x();
break; break;
} }
@@ -763,7 +804,7 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y();
break; break;
} }
@@ -776,7 +817,7 @@ namespace MobileGL {
if (params) { if (params) {
switch (textureObject->GetStorageType()) { switch (textureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { 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(); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z();
break; break;
} }
@@ -1017,8 +1058,8 @@ namespace MobileGL {
TexImage1D_State(target, level, internalFormat, width, border, format, type, pixels); TexImage1D_State(target, level, internalFormat, width, border, format, type, pixels);
} }
void TexBuffer(GLenum target, GLenum internalformat, GLuint texture) { void TexBuffer(GLenum target, GLenum internalformat, GLuint buffer) {
TexBuffer_State(target, internalformat, texture); TexBuffer_State(target, internalformat, buffer);
} }
GLboolean IsTexture(GLuint texture) { GLboolean IsTexture(GLuint texture) {
@@ -52,8 +52,8 @@ namespace MobileGL {
IntVec3 FramebufferAttachment::GetSize() const { IntVec3 FramebufferAttachment::GetSize() const {
if (IsTexture()) { if (IsTexture()) {
// TODO: get correct upload target // 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"); 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::TextureMipmapObject*>(m_texture.get()); auto textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(m_texture.get());
return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel);
} else if (IsRenderbuffer()) { } else if (IsRenderbuffer()) {
// TODO // TODO
@@ -38,6 +38,7 @@ namespace MobileGL {
CubeMapNegativeY, CubeMapNegativeY,
CubeMapPositiveZ, CubeMapPositiveZ,
CubeMapNegativeZ, CubeMapNegativeZ,
TextureBuffer,
ProxyCubeMap, ProxyCubeMap,
CubeMapArray, CubeMapArray,
ProxyCubeMapArray, ProxyCubeMapArray,
@@ -69,9 +69,9 @@ namespace MobileGL {
UintVec2 m_levelRange = {0, 1000}; UintVec2 m_levelRange = {0, 1000};
}; };
class TextureMipmapObject : public TextureObjectBase { class TextureObjectMipmap : public TextureObjectBase {
public: public:
TextureMipmapObject(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {}
TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; } TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; }
@@ -85,10 +85,10 @@ namespace MobileGL {
virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0;
}; };
class TextureObjectWithOneMipmap : public TextureMipmapObject { class TextureObjectWithOneMipmap : public TextureObjectMipmap {
public: public:
TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex) TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex)
: TextureMipmapObject(target, externalIndex) {} : TextureObjectMipmap(target, externalIndex) {}
virtual ~TextureObjectWithOneMipmap() = default; virtual ~TextureObjectWithOneMipmap() = default;
Uint GetMipmapLevelCount() const override; Uint GetMipmapLevelCount() const override;
@@ -4,7 +4,7 @@ namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
TextureObject2DCube::TextureObject2DCube(Uint externalIndex) TextureObject2DCube::TextureObject2DCube(Uint externalIndex)
: TextureMipmapObject(TextureTarget::TextureCubeMap, externalIndex) {} : TextureObjectMipmap(TextureTarget::TextureCubeMap, externalIndex) {}
Uint TextureObject2DCube::GetMipmapLevelCount() const { Uint TextureObject2DCube::GetMipmapLevelCount() const {
return m_textureStorage.GetLevelCount(); return m_textureStorage.GetLevelCount();
@@ -4,7 +4,7 @@
namespace MobileGL { namespace MobileGL {
namespace MG_State { namespace MG_State {
namespace GLState { namespace GLState {
class TextureObject2DCube : public TextureMipmapObject { class TextureObject2DCube : public TextureObjectMipmap {
public: public:
explicit TextureObject2DCube(Uint externalIndex); 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, STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject2DMultisample, TextureTarget::Texture2DMultisample,
{TextureUploadTarget::Texture2DMultisample}); {TextureUploadTarget::Texture2DMultisample});
STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer, // STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer,
{TextureUploadTarget::Unknown}); // {TextureUploadTarget::Unknown});
STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject1DArray, TextureTarget::Texture1DArray, STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject1DArray, TextureTarget::Texture1DArray,
{TextureUploadTarget::Texture1DArray}); {TextureUploadTarget::Texture1DArray});
@@ -6,6 +6,7 @@
#include "TextureObject2D.h" #include "TextureObject2D.h"
#include "TextureObject3D.h" #include "TextureObject3D.h"
#include "TextureObject2DCube.h" #include "TextureObject2DCube.h"
#include "TextureObjectBuffer.h"
#include "TextureObjectStubs.h" #include "TextureObjectStubs.h"
namespace MobileGL { namespace MobileGL {
@@ -46,6 +47,9 @@ namespace MobileGL {
case TextureTarget::Texture3D: case TextureTarget::Texture3D:
textureObject = MakeShared<TextureObject3D>(index); textureObject = MakeShared<TextureObject3D>(index);
break; break;
case TextureTarget::TextureBuffer:
textureObject = MakeShared<TextureObjectBuffer>(index);
break;
// These texture types are stubbed: // These texture types are stubbed:
case TextureTarget::TextureRectangle: case TextureTarget::TextureRectangle:
@@ -54,9 +58,6 @@ namespace MobileGL {
case TextureTarget::Texture2DMultisample: case TextureTarget::Texture2DMultisample:
textureObject = MakeShared<TextureObject2DMultisample>(index); textureObject = MakeShared<TextureObject2DMultisample>(index);
break; break;
case TextureTarget::TextureBuffer:
textureObject = MakeShared<TextureObjectBuffer>(index);
break;
case TextureTarget::Texture1DArray: case TextureTarget::Texture1DArray:
textureObject = MakeShared<TextureObject1DArray>(index); textureObject = MakeShared<TextureObject1DArray>(index);
break; break;