mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_State, MG_Impl/GLImpl): per-target default texture objects (name 0) - binding 0 binds a real per-context default object (the initial binding of every unit/target slot, rebound on delete of a bound texture), so glTexImage*/glTexParameter*/glGetTex* on it work like any texture while glIsTexture(0)/Gen/Delete keep excluding it and TexStorage* rejects it per spec; backends skip image-less defaults as cheaply as the old null slots (DirectGLES per-draw sync/bind loops, DirectVulkan sampler-fallback resolve); also accept the full advertised GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS range in glActiveTexture, allow zero-layer TexImage3DMultisample, and let glTexBuffer(buffer=0) detach - the texture section of GL CTS per-case state reset (gluStateReset) now runs clean
This commit is contained in:
@@ -226,6 +226,10 @@ namespace MobileGL::MG_State {
|
||||
return m_textureState.GetTextureObject(index);
|
||||
}
|
||||
|
||||
const SharedPtr<ITextureObject>& GLContext::GetDefaultTextureObject(TextureTarget target) const {
|
||||
return m_textureState.GetDefaultTextureObject(target);
|
||||
}
|
||||
|
||||
const SharedPtr<ITextureObject>& GLContext::CreateTextureObject(Uint index, TextureTarget target) {
|
||||
return m_textureState.CreateTextureObject(index, target);
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ namespace MobileGL {
|
||||
// Texture
|
||||
void GenTextureNames(Uint number, Vector<Uint>& textures);
|
||||
const SharedPtr<ITextureObject>& GetTextureObject(Uint index);
|
||||
// Per-target default texture object (name 0); see TextureState::GetDefaultTextureObject.
|
||||
const SharedPtr<ITextureObject>& GetDefaultTextureObject(TextureTarget target) const;
|
||||
const SharedPtr<ITextureObject>& CreateTextureObject(Uint index, TextureTarget target);
|
||||
void MarkTextureObjectForDeletion(Uint index);
|
||||
TextureUnit& GetTextureUnitObject(Int unit);
|
||||
|
||||
@@ -154,6 +154,17 @@ namespace MobileGL::MG_State::GLState {
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
// The per-target default texture objects (name 0) sit permanently in every texture unit's
|
||||
// binding slots, so "nothing useful bound" is no longer a null slot. While a default texture
|
||||
// has never been given an image (its internal format is still Unknown) it can contribute
|
||||
// nothing to sampling; backends treat such a binding exactly like the old empty slot and
|
||||
// skip per-draw sync/bind work for it. Once an application defines an image on a default
|
||||
// texture it loses this shortcut and is synced like any other texture.
|
||||
inline Bool IsUndefinedDefaultTexture(const ITextureObject* texture) {
|
||||
return texture != nullptr && texture->GetExternalIndex() == 0 &&
|
||||
texture->GetFormat() == TextureInternalFormat::Unknown;
|
||||
}
|
||||
|
||||
class TextureObjectWithOneMipmap : public TextureObjectMipmap {
|
||||
public:
|
||||
TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex)
|
||||
|
||||
@@ -18,9 +18,51 @@
|
||||
#include "TextureObjectStubs.h"
|
||||
|
||||
namespace MobileGL::MG_State::GLState {
|
||||
static SharedPtr<ITextureObject> MakeTextureObjectForTarget(Uint index, TextureTarget target) {
|
||||
switch (target) {
|
||||
case TextureTarget::Texture1D:
|
||||
return MakeShared<TextureObject1D>(index);
|
||||
case TextureTarget::TextureCubeMap:
|
||||
return MakeShared<TextureObject2DCube>(index);
|
||||
case TextureTarget::Texture2D:
|
||||
return MakeShared<TextureObject2D>(index);
|
||||
case TextureTarget::Texture3D:
|
||||
return MakeShared<TextureObject3D>(index);
|
||||
case TextureTarget::TextureBuffer:
|
||||
return MakeShared<TextureObjectBuffer>(index);
|
||||
|
||||
// These texture types are still stubbed:
|
||||
case TextureTarget::TextureRectangle:
|
||||
return MakeShared<TextureObjectRectangle>(index);
|
||||
case TextureTarget::Texture2DMultisample:
|
||||
return MakeShared<TextureObject2DMultisample>(index);
|
||||
case TextureTarget::Texture1DArray:
|
||||
return MakeShared<TextureObject1DArray>(index);
|
||||
case TextureTarget::Texture2DArray:
|
||||
return MakeShared<TextureObject2DArray>(index);
|
||||
case TextureTarget::TextureCubeMapArray:
|
||||
return MakeShared<TextureObjectCubeMapArray>(index);
|
||||
case TextureTarget::Texture2DMultisampleArray:
|
||||
return MakeShared<TextureObject2DMultisampleArray>(index);
|
||||
default:
|
||||
MOBILEGL_ASSERT(false, "Unimplemented texture type when creating texture object!: %d", (int)target);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
TextureState::TextureState() : m_indexGenerator(1024, 1) {
|
||||
// GL 3.3 core 3.8: each target owns one default texture object (name 0) per context,
|
||||
// shared across all texture units, and it is the initial binding of every unit/target
|
||||
// slot. It is created outside m_textureObjects so name-based paths (glIsTexture,
|
||||
// GenTextures/DeleteTextures, by-name DSA lookups) never see it.
|
||||
for (int i = 0; i < (int)TextureTarget::TextureTargetCount; ++i) {
|
||||
m_defaultTextureObjects[i] = MakeTextureObjectForTarget(0, static_cast<TextureTarget>(i));
|
||||
}
|
||||
for (int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) {
|
||||
m_textureUnits[i] = TextureUnit();
|
||||
for (auto& bindingSlot : m_textureUnits[i].GetAllBindingSlots()) {
|
||||
bindingSlot.Bind(m_defaultTextureObjects[(int)bindingSlot.GetTarget()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +75,12 @@ namespace MobileGL::MG_State::GLState {
|
||||
return nullTextureObject;
|
||||
}
|
||||
|
||||
const SharedPtr<ITextureObject>& TextureState::GetDefaultTextureObject(TextureTarget target) const {
|
||||
MOBILEGL_ASSERT(target > TextureTarget::Unknown && target < TextureTarget::TextureTargetCount,
|
||||
"GetDefaultTextureObject: invalid texture target %d", (int)target);
|
||||
return m_defaultTextureObjects[(int)target];
|
||||
}
|
||||
|
||||
void TextureState::GenerateNames(Uint number, Vector<Uint>& textures) {
|
||||
textures.resize(number);
|
||||
m_indexGenerator.Generate(number, textures.data());
|
||||
@@ -40,48 +88,11 @@ namespace MobileGL::MG_State::GLState {
|
||||
|
||||
const SharedPtr<ITextureObject>& TextureState::CreateTextureObject(Uint index, TextureTarget target) {
|
||||
auto& textureObject = m_textureObjects[index];
|
||||
switch (target) {
|
||||
case TextureTarget::Texture1D:
|
||||
textureObject = MakeShared<TextureObject1D>(index);
|
||||
break;
|
||||
case TextureTarget::TextureCubeMap:
|
||||
textureObject = MakeShared<TextureObject2DCube>(index);
|
||||
break;
|
||||
case TextureTarget::Texture2D:
|
||||
textureObject = MakeShared<TextureObject2D>(index);
|
||||
break;
|
||||
case TextureTarget::Texture3D:
|
||||
textureObject = MakeShared<TextureObject3D>(index);
|
||||
break;
|
||||
case TextureTarget::TextureBuffer:
|
||||
textureObject = MakeShared<TextureObjectBuffer>(index);
|
||||
break;
|
||||
|
||||
// These texture types are still stubbed:
|
||||
case TextureTarget::TextureRectangle:
|
||||
textureObject = MakeShared<TextureObjectRectangle>(index);
|
||||
break;
|
||||
case TextureTarget::Texture2DMultisample:
|
||||
textureObject = MakeShared<TextureObject2DMultisample>(index);
|
||||
break;
|
||||
case TextureTarget::Texture1DArray:
|
||||
textureObject = MakeShared<TextureObject1DArray>(index);
|
||||
break;
|
||||
case TextureTarget::Texture2DArray:
|
||||
textureObject = MakeShared<TextureObject2DArray>(index);
|
||||
break;
|
||||
case TextureTarget::TextureCubeMapArray:
|
||||
textureObject = MakeShared<TextureObjectCubeMapArray>(index);
|
||||
break;
|
||||
case TextureTarget::Texture2DMultisampleArray:
|
||||
textureObject = MakeShared<TextureObject2DMultisampleArray>(index);
|
||||
break;
|
||||
default:
|
||||
MOBILEGL_ASSERT(false, "Unimplemented texture type when creating texture object!: %d", (int)target);
|
||||
textureObject = MakeTextureObjectForTarget(index, target);
|
||||
if (!textureObject) {
|
||||
static SharedPtr<ITextureObject> nullTextureObject = nullptr;
|
||||
return nullTextureObject;
|
||||
}
|
||||
|
||||
return textureObject;
|
||||
}
|
||||
|
||||
@@ -94,7 +105,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
auto& bindingSlots = m_textureUnits[unit].GetAllBindingSlots();
|
||||
for (auto& bindingSlot : bindingSlots) {
|
||||
if (bindingSlot.GetBoundObject() == it->second) {
|
||||
bindingSlot.Bind(nullptr);
|
||||
// GL 3.3 core 3.8.1: deleting a bound texture rebinds zero, i.e. the
|
||||
// target's default texture object, on every unit it was bound to.
|
||||
bindingSlot.Bind(m_defaultTextureObjects[(int)bindingSlot.GetTarget()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,12 @@ namespace MobileGL::MG_State::GLState {
|
||||
void GenerateNames(Uint number, Vector<Uint>& textures);
|
||||
const SharedPtr<ITextureObject>& CreateTextureObject(Uint index, TextureTarget target);
|
||||
const SharedPtr<ITextureObject>& GetTextureObject(Uint index);
|
||||
// The context's default texture object (name 0) for `target`. GL 3.3 core 3.8: texture
|
||||
// zero names a real, per-target texture object shared by every texture unit; binding 0
|
||||
// binds it, and image/parameter calls on it must work like on any texture. It is not a
|
||||
// GenTextures name: it lives outside m_textureObjects (so glIsTexture(0) stays GL_FALSE
|
||||
// and by-name lookups keep failing for 0) and can never be deleted.
|
||||
const SharedPtr<ITextureObject>& GetDefaultTextureObject(TextureTarget target) const;
|
||||
TextureUnit& GetUnitObject(Int unit);
|
||||
ImageTextureBinding& GetImageTextureBinding(Int unit);
|
||||
const ImageTextureBinding& GetImageTextureBinding(Int unit) const;
|
||||
@@ -83,5 +89,8 @@ namespace MobileGL::MG_State::GLState {
|
||||
Array<ImageTextureBinding, MAX_TEXTURE_IMAGE_UNITS> m_imageTextureBindings;
|
||||
IndexGenerator<Uint> m_indexGenerator;
|
||||
UnorderedMap<GLuint, SharedPtr<ITextureObject>> m_textureObjects;
|
||||
// One default texture object (external name 0) per target, created with the context and
|
||||
// immortal for its lifetime; the initial binding of every unit/target slot.
|
||||
Array<SharedPtr<ITextureObject>, (int)TextureTarget::TextureTargetCount> m_defaultTextureObjects;
|
||||
};
|
||||
} // namespace MobileGL::MG_State::GLState
|
||||
|
||||
Reference in New Issue
Block a user