mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (MG_Backend/DirectGLES): Implement ClearBuffer* in backend.
This commit is contained in:
@@ -227,7 +227,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
|
||||
BufferImpl::BackendBufferBindingProtector pixelUnpackProtector =
|
||||
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
|
||||
BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
Vector<BackendTextureBindingProtector> textureBindingProtectors;
|
||||
for (SizeT target = 0; target < TextureTargetCount; ++target) {
|
||||
@@ -411,7 +411,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
{
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedNC("BindCurrentVAO", TRACY_ZONECOLOR_BACKEND);
|
||||
ZoneScopedNC("BindCurrentVAO", TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
const auto& currentVAO = MG_State::pGLContext->GetBoundVertexArray();
|
||||
if (currentVAO) {
|
||||
@@ -440,14 +440,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
// Bind texture object
|
||||
auto target = textureObject->GetTarget();
|
||||
if (target == TextureTarget::Texture1D ||
|
||||
target == TextureTarget::TextureRectangle || target == TextureTarget::Texture2DMultisampleArray ||
|
||||
target == TextureTarget::Texture1DArray || target == TextureTarget::Texture3D ||
|
||||
target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray) {
|
||||
if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle ||
|
||||
target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray ||
|
||||
target == TextureTarget::Texture3D || target == TextureTarget::Texture2DMultisample ||
|
||||
target == TextureTarget::Texture2DArray) {
|
||||
MGLOG_D(" Texture target %s is not supported, skipping.",
|
||||
MG_Util::ConvertTextureTargetToString(target).c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject);
|
||||
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue;
|
||||
|
||||
@@ -480,7 +480,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// Global UBO
|
||||
if (currentProgram->GetUBOSize() > 0) {
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedNC("UpdateGlobalUBO", TRACY_ZONECOLOR_BACKEND);
|
||||
ZoneScopedNC("UpdateGlobalUBO", TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER,
|
||||
backendProgramIt->second->GetBackendGlobalUBOId());
|
||||
@@ -499,7 +499,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
{
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedNC("UpdateUBO", TRACY_ZONECOLOR_BACKEND);
|
||||
ZoneScopedNC("UpdateUBO", TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
// Normal UBO
|
||||
auto uboCount = currentProgram->GetActiveUniformBlocksCount();
|
||||
@@ -511,7 +511,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// Connect program ubo index to backend binding point
|
||||
auto binding = currentProgram->GetUniformBlockBinding(i);
|
||||
auto& name = currentProgram->GetUniformBlockName(i);
|
||||
GLuint backendBlkIdx = MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str());
|
||||
GLuint backendBlkIdx =
|
||||
MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str());
|
||||
MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding);
|
||||
|
||||
// Connect buffer to backend binding point
|
||||
@@ -541,7 +542,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
{
|
||||
#ifdef TRACY_ENABLE
|
||||
ZoneScopedNC("BindSamplerUnit", TRACY_ZONECOLOR_BACKEND);
|
||||
ZoneScopedNC("BindSamplerUnit", TRACY_ZONECOLOR_BACKEND);
|
||||
#endif
|
||||
// Sampler unit binding
|
||||
auto maxUniformLoc = currentProgram->GetMaxUniformLocation();
|
||||
@@ -823,7 +824,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
textureObject->SetInternalFormat(mglInternalFormat);
|
||||
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::TextureObjectMipmap*>(textureObject.get());
|
||||
textureMipmapObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0});
|
||||
}
|
||||
@@ -932,4 +933,175 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const GLubyte* GetString(GLenum name) {
|
||||
return MG_External::GLES::glGetString(name);
|
||||
}
|
||||
|
||||
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
|
||||
TextureImpl::SyncNeccessaryTextures();
|
||||
FramebufferImpl::SyncCurrentFBO();
|
||||
RenderStateImpl::SyncRenderState();
|
||||
|
||||
BindCurrentFBO(FramebufferTarget::Draw);
|
||||
|
||||
MG_External::GLES::glClearBufferfi(buffer, drawbuffer, depth, stencil);
|
||||
}
|
||||
|
||||
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
|
||||
TextureImpl::SyncNeccessaryTextures();
|
||||
FramebufferImpl::SyncCurrentFBO();
|
||||
RenderStateImpl::SyncRenderState();
|
||||
|
||||
BindCurrentFBO(FramebufferTarget::Draw);
|
||||
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
||||
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
||||
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
||||
return;
|
||||
}
|
||||
auto backendFBO = backendFBOIt->second;
|
||||
|
||||
GLint realDrawbuffer = drawbuffer;
|
||||
|
||||
if (buffer == GL_COLOR) {
|
||||
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
||||
|
||||
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
||||
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
||||
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
||||
realDrawbuffer = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
||||
return;
|
||||
}
|
||||
} else if (buffer == GL_DEPTH || buffer == GL_STENCIL) {
|
||||
if (drawbuffer != 0) {
|
||||
MGLOG_W("Depth/stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
|
||||
}
|
||||
realDrawbuffer = 0;
|
||||
}
|
||||
|
||||
MG_External::GLES::glClearBufferfv(buffer, realDrawbuffer, value);
|
||||
}
|
||||
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
|
||||
TextureImpl::SyncNeccessaryTextures();
|
||||
FramebufferImpl::SyncCurrentFBO();
|
||||
RenderStateImpl::SyncRenderState();
|
||||
|
||||
BindCurrentFBO(FramebufferTarget::Draw);
|
||||
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
||||
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
||||
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
||||
return;
|
||||
}
|
||||
auto backendFBO = backendFBOIt->second;
|
||||
|
||||
GLint realDrawbuffer = drawbuffer;
|
||||
|
||||
if (buffer == GL_COLOR) {
|
||||
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
||||
|
||||
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
||||
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
||||
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
||||
realDrawbuffer = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
||||
return;
|
||||
}
|
||||
} else if (buffer == GL_STENCIL) {
|
||||
if (drawbuffer != 0) {
|
||||
MGLOG_W("Stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
|
||||
}
|
||||
realDrawbuffer = 0;
|
||||
}
|
||||
|
||||
MG_External::GLES::glClearBufferiv(buffer, realDrawbuffer, value);
|
||||
}
|
||||
|
||||
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
|
||||
TextureImpl::SyncNeccessaryTextures();
|
||||
FramebufferImpl::SyncCurrentFBO();
|
||||
RenderStateImpl::SyncRenderState();
|
||||
|
||||
BindCurrentFBO(FramebufferTarget::Draw);
|
||||
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
||||
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
||||
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
||||
return;
|
||||
}
|
||||
auto backendFBO = backendFBOIt->second;
|
||||
|
||||
GLint realDrawbuffer = drawbuffer;
|
||||
|
||||
if (buffer == GL_COLOR) {
|
||||
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
||||
|
||||
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
||||
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
||||
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
||||
realDrawbuffer = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
MGLOG_E("ClearBufferuiv can only be used with GL_COLOR buffer, got %s",
|
||||
MG_Util::ConvertGLEnumToString(buffer).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
MG_External::GLES::glClearBufferuiv(buffer, realDrawbuffer, value);
|
||||
}
|
||||
|
||||
} // namespace MobileGL::MG_Backend::DirectGLES
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
operation Utils::CheckGLESError();
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectGLES {
|
||||
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
|
||||
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
|
||||
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
|
||||
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value);
|
||||
void Clear(GLbitfield mask);
|
||||
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
|
||||
@@ -306,8 +306,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
auto targetInternal = stateTextureObject->GetTarget();
|
||||
MGLOG_D(" Texture target for syncing is %s",
|
||||
MG_Util::ConvertTextureTargetToString(targetInternal).c_str());
|
||||
if (targetInternal == TextureTarget::Texture1D ||
|
||||
targetInternal == TextureTarget::TextureRectangle ||
|
||||
if (targetInternal == TextureTarget::Texture1D || targetInternal == TextureTarget::TextureRectangle ||
|
||||
targetInternal == TextureTarget::Texture2DMultisampleArray ||
|
||||
targetInternal == TextureTarget::Texture1DArray || targetInternal == TextureTarget::Texture3D ||
|
||||
targetInternal == TextureTarget::Texture2DMultisample ||
|
||||
@@ -334,131 +333,138 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
|
||||
});
|
||||
const auto baseSize = stateTextureObject->GetBaseSize();
|
||||
StateTextureBasicInfo currentTextureInfo = {
|
||||
stateTextureObject->GetFormat(), static_cast<SizeT>(baseSize.x()), static_cast<SizeT>(baseSize.y()),
|
||||
static_cast<SizeT>(baseSize.z()), 0, 0};
|
||||
StateTextureBasicInfo currentTextureInfo = {stateTextureObject->GetFormat(),
|
||||
static_cast<SizeT>(baseSize.x()),
|
||||
static_cast<SizeT>(baseSize.y()),
|
||||
static_cast<SizeT>(baseSize.z()),
|
||||
0,
|
||||
0};
|
||||
switch (stateTextureObject->GetStorageType()) {
|
||||
case TextureStorageType::Mipmap: {
|
||||
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(stateTextureObject.get());
|
||||
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
|
||||
currentTextureInfo.mipmapLevels = mipmapCount;
|
||||
case TextureStorageType::Mipmap: {
|
||||
auto* textureMipmapObject =
|
||||
static_cast<MG_State::GLState::TextureObjectMipmap*>(stateTextureObject.get());
|
||||
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
|
||||
currentTextureInfo.mipmapLevels = mipmapCount;
|
||||
|
||||
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
||||
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
||||
|
||||
MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(),
|
||||
baseSize.z(), mipmapCount,
|
||||
MG_Util::ConvertTextureInternalFormatToString(textureMipmapObject->GetFormat()).c_str());
|
||||
MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(),
|
||||
baseSize.z(), mipmapCount,
|
||||
MG_Util::ConvertTextureInternalFormatToString(textureMipmapObject->GetFormat()).c_str());
|
||||
|
||||
if (needsRegeneration) {
|
||||
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u",
|
||||
m_backendTextureId);
|
||||
|
||||
// Regenerate all mipmap levels
|
||||
GLenum glInternalFormat, glType, glFormat;
|
||||
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType,
|
||||
&glFormat);
|
||||
|
||||
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
|
||||
for (auto uploadTarget : uploadTargets) {
|
||||
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||
auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||
auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
|
||||
bool levelDirty = textureMipmapObject->IsStorageDirty(uploadTarget, 0);
|
||||
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||
auto* pData = (levelDirty && levelByteSize != 0)
|
||||
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
||||
: nullptr;
|
||||
MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__,
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level,
|
||||
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData);
|
||||
|
||||
errorLopper.Clear();
|
||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
|
||||
static_cast<GLsizei>(levelTexelSize.x()),
|
||||
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType,
|
||||
pData);
|
||||
|
||||
// TODO: handle more texture types
|
||||
|
||||
MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId);
|
||||
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
{ // Update all dirty mipmap levels
|
||||
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
|
||||
GLenum glInternalFormat, glType, glFormat;
|
||||
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType,
|
||||
&glFormat);
|
||||
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
|
||||
for (auto uploadTarget : uploadTargets) {
|
||||
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||
if (!textureMipmapObject->IsStorageDirty(uploadTarget, level)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto byteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
|
||||
if (byteSize == 0) {
|
||||
MGLOG_W("Mipmap level %d has no data, skipping update.", level);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line,
|
||||
MG_Util::ConvertGLEnumToString(err).c_str());
|
||||
});
|
||||
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||
MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
|
||||
static_cast<GLsizei>(texelSize.x()),
|
||||
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
|
||||
textureMipmapObject->MapMipmapData(uploadTarget, level));
|
||||
|
||||
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextureStorageType::Buffer: {
|
||||
auto* textureBufferObject = static_cast<MG_State::GLState::TextureObjectBuffer*>(stateTextureObject.get());
|
||||
auto& slot = textureBufferObject->GetBufferBindingSlot();
|
||||
auto buffer = slot.GetBoundObject();
|
||||
auto bufferIndex = buffer->GetExternalIndex();
|
||||
currentTextureInfo.bufferExternalIndex = bufferIndex;
|
||||
|
||||
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
||||
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture (tex buffer) with ID: %u",
|
||||
m_backendTextureId);
|
||||
|
||||
// Need to sync texture buffer if not synced yet
|
||||
auto& backendBuffers = BufferImpl::g_backendBufferObjects;
|
||||
SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject;
|
||||
const auto& backendBufferIt = backendBuffers.find(buffer);
|
||||
if (backendBufferIt == backendBuffers.end()) {
|
||||
backendBufferObject = MakeShared<BufferImpl::BackendBufferObject>();
|
||||
backendBuffers[buffer] = backendBufferObject;
|
||||
} else {
|
||||
backendBufferObject = backendBufferIt->second;
|
||||
}
|
||||
backendBufferObject->SyncToBackend(buffer);
|
||||
|
||||
// Bind buffer to texture
|
||||
auto backendId = backendBufferObject->GetBackendBufferId();
|
||||
if (needsRegeneration) {
|
||||
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u",
|
||||
m_backendTextureId);
|
||||
|
||||
// Regenerate all mipmap levels
|
||||
GLenum glInternalFormat, glType, glFormat;
|
||||
TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, &glType,
|
||||
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType,
|
||||
&glFormat);
|
||||
|
||||
MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
|
||||
break;
|
||||
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
|
||||
for (auto uploadTarget : uploadTargets) {
|
||||
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||
auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||
auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
|
||||
bool levelDirty = textureMipmapObject->IsStorageDirty(uploadTarget, 0);
|
||||
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||
auto* pData = (levelDirty && levelByteSize != 0)
|
||||
? textureMipmapObject->MapMipmapData(uploadTarget, level)
|
||||
: nullptr;
|
||||
MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__,
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level,
|
||||
levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData);
|
||||
|
||||
errorLopper.Clear();
|
||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
|
||||
static_cast<GLsizei>(levelTexelSize.x()),
|
||||
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat,
|
||||
glType, pData);
|
||||
|
||||
// TODO: handle more texture types
|
||||
|
||||
MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId);
|
||||
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
|
||||
}
|
||||
}
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
default: THROW_UNIMPL_EXCEPTION;
|
||||
|
||||
{ // Update all dirty mipmap levels
|
||||
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
|
||||
GLenum glInternalFormat, glType, glFormat;
|
||||
TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType,
|
||||
&glFormat);
|
||||
const auto& uploadTargets = textureMipmapObject->GetUploadTargets();
|
||||
for (auto uploadTarget : uploadTargets) {
|
||||
for (SizeT level = 0; level < mipmapCount; ++level) {
|
||||
if (!textureMipmapObject->IsStorageDirty(uploadTarget, level)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto byteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level);
|
||||
if (byteSize == 0) {
|
||||
MGLOG_W("Mipmap level %d has no data, skipping update.", level);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget);
|
||||
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) {
|
||||
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line,
|
||||
MG_Util::ConvertGLEnumToString(err).c_str());
|
||||
});
|
||||
auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level);
|
||||
MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast<GLint>(level), 0, 0,
|
||||
static_cast<GLsizei>(texelSize.x()),
|
||||
static_cast<GLsizei>(texelSize.y()), glFormat, glType,
|
||||
textureMipmapObject->MapMipmapData(uploadTarget, level));
|
||||
|
||||
textureMipmapObject->MarkStorageDirty(uploadTarget, level, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextureStorageType::Buffer: {
|
||||
auto* textureBufferObject =
|
||||
static_cast<MG_State::GLState::TextureObjectBuffer*>(stateTextureObject.get());
|
||||
auto& slot = textureBufferObject->GetBufferBindingSlot();
|
||||
auto buffer = slot.GetBoundObject();
|
||||
auto bufferIndex = buffer->GetExternalIndex();
|
||||
currentTextureInfo.bufferExternalIndex = bufferIndex;
|
||||
|
||||
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
|
||||
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture (tex buffer) "
|
||||
"with ID: %u",
|
||||
m_backendTextureId);
|
||||
|
||||
// Need to sync texture buffer if not synced yet
|
||||
auto& backendBuffers = BufferImpl::g_backendBufferObjects;
|
||||
SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject;
|
||||
const auto& backendBufferIt = backendBuffers.find(buffer);
|
||||
if (backendBufferIt == backendBuffers.end()) {
|
||||
backendBufferObject = MakeShared<BufferImpl::BackendBufferObject>();
|
||||
backendBuffers[buffer] = backendBufferObject;
|
||||
} else {
|
||||
backendBufferObject = backendBufferIt->second;
|
||||
}
|
||||
backendBufferObject->SyncToBackend(buffer);
|
||||
|
||||
// Bind buffer to texture
|
||||
auto backendId = backendBufferObject->GetBackendBufferId();
|
||||
|
||||
GLenum glInternalFormat, glType, glFormat;
|
||||
TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, &glType,
|
||||
&glFormat);
|
||||
|
||||
MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
THROW_UNIMPL_EXCEPTION;
|
||||
}
|
||||
|
||||
{ // Update built-in sampler parameters
|
||||
@@ -702,6 +708,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
}
|
||||
|
||||
FramebufferAttachmentType BackendFramebufferObject::GetCompactedAttachmentTypeAtDrawBufferIndex(Int index) {
|
||||
return m_compactedFrontendDrawBuffers[index];
|
||||
}
|
||||
|
||||
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
|
||||
g_backendFramebufferObjects;
|
||||
} // namespace FramebufferImpl
|
||||
|
||||
@@ -58,7 +58,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
|
||||
bool operator==(const StateTextureBasicInfo& other) const {
|
||||
return internalFormat == other.internalFormat && width == other.width && height == other.height &&
|
||||
depth == other.depth && mipmapLevels == other.mipmapLevels && bufferExternalIndex == other.bufferExternalIndex;
|
||||
depth == other.depth && mipmapLevels == other.mipmapLevels &&
|
||||
bufferExternalIndex == other.bufferExternalIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
|
||||
@@ -94,6 +95,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
FramebufferTarget asTarget);
|
||||
Uint GetBackendFramebufferId() { return m_backendFBOId; }
|
||||
void Bind(FramebufferTarget target);
|
||||
FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
|
||||
|
||||
private:
|
||||
Uint m_backendFBOId = 0;
|
||||
|
||||
Reference in New Issue
Block a user