diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a6d3a95..ae5bf6c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,9 @@ set(SOURCE_FILES MobileGL/MG_Util/Debug/Log.cpp + MobileGL/MG_Util/Math/VectorTypes.cpp MobileGL/MG_Util/Metrics/TextureMetrics.cpp + MobileGL/MG_Util/Metrics/BufferMetrics.cpp MobileGL/MG_Util/Converters/GLToStr/GLEnumConverter.cpp diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 5f9aab62..261be744 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -151,6 +151,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // Do real sync for (auto& bufferObject : buffersToSync) { + if (!(bufferObject->GetChangeBits() & BufferChangeBits::DirtyBit)) continue; + const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject); SharedPtr backendBufferObject; if (backendBufferIt == g_backendBufferObjects.end()) { @@ -778,8 +780,8 @@ namespace MobileGL::MG_Backend::DirectGLES { errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); - MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, - MG_Util::ConvertGLEnumToString(filter).c_str()); + MGLOG_D("ES %s(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)", __func__, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, + dstX1, dstY1, mask, MG_Util::ConvertGLEnumToString(filter).c_str()); MG_External::GLES::glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); @@ -825,7 +827,7 @@ namespace MobileGL::MG_Backend::DirectGLES { void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG - DebugImpl::OpenGLScopeMarker marker(__func__); + DebugImpl::OpenGLScopeMarker marker(__func__); #endif DebugImpl::ErrorLopper errorLopper; MGLOG_D("%s: Backend", __func__); @@ -842,25 +844,24 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); - if (!UpdateTextureBindingAtTarget(target)) - return; + if (!UpdateTextureBindingAtTarget(target)) return; -// GLint realInternalFormat; -// MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &realInternalFormat); -// errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { -// MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); -// }); -// internalformat = (GLenum)realInternalFormat; + // GLint realInternalFormat; + // MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, + // &realInternalFormat); errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { + // MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); + // }); + // internalformat = (GLenum)realInternalFormat; auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); GLenum format = GL_DEPTH_COMPONENT; GLenum type = GL_UNSIGNED_INT; TextureImpl::GenerateTextureFormatInfo(mglInternalFormat, &internalformat, &format, &type); - MOBILEGL_ASSERT(format != GL_NONE && type != GL_NONE, "%s: cannot GenerateTextureFormatInfo(%s): out internalformat=%s, format=%s, type=%s", + MOBILEGL_ASSERT(format != GL_NONE && type != GL_NONE, + "%s: cannot GenerateTextureFormatInfo(%s): out internalformat=%s, format=%s, type=%s", MG_Util::ConvertTextureInternalFormatToString(mglInternalFormat).c_str(), MG_Util::ConvertGLEnumToString(internalformat).c_str(), - MG_Util::ConvertGLEnumToString(format).c_str(), - MG_Util::ConvertGLEnumToString(type).c_str()); + MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str()); TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); bool isDepthFormat = @@ -938,8 +939,7 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); - if (!UpdateTextureBindingAtTarget(target)) - return; + if (!UpdateTextureBindingAtTarget(target)) return; BindCurrentFBO(FramebufferTarget::Read); errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) { diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index ab6c263d..8acecd7e 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -7,24 +7,24 @@ // End of Source File Header #include "Managers.h" -#include "MG_Backend/Backends.h" -#include "MG_Util/Debug/Log.h" #include "Utils.h" #include "DirectGLES.h" -#include "MG_State/GLState/TextureState/TextureObjectBuffer.h" #include #include -#include #include #include -#include #include +#include +#include +#include #include #include #include namespace MobileGL::MG_Backend::DirectGLES { + constexpr Bool PREFER_MAP_BUFFER_RANGE_FOR_BUFFER_SYNC = true; + namespace BufferImpl { BackendBufferObject::BackendBufferObject() { #ifdef TRACY_ENABLE @@ -58,8 +58,10 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("Syncing buffer object with backend ID %u to backend for state ID %u", m_backendBufferId, stateBufferObject->GetExternalIndex()); + // Decide sync method + // glBufferData Bool needsRegeneration = - !m_isInitialized || bufferSize > m_prevBufferSize || bufferSize < m_prevBufferSize / 2; + !m_isInitialized || (stateBufferObject->GetChangeBits() & BufferChangeBits::PreferReallocationBit); if (needsRegeneration) { MGLOG_D("Buffer size changed significantly or not initialized, regenerating buffer with ID: %u", @@ -67,22 +69,33 @@ namespace MobileGL::MG_Backend::DirectGLES { SyncToBackend_glBufferData(stateBufferObject); m_isInitialized = true; m_prevBufferSize = bufferSize; + stateBufferObject->ClearDirty(); return; } - switch (stateBufferObject->GetUsage()) { - case BufferUsage::StaticDraw: - SyncToBackend_glBufferSubData(stateBufferObject); - break; - case BufferUsage::DynamicDraw: - case BufferUsage::StreamDraw: - SyncToBackend_glMapBufferRange(stateBufferObject); - break; - default: - SyncToBackend_glBufferSubData(stateBufferObject); - break; + // glMapBufferRange or glBufferSubData + Bool useInvalidationMap = !(stateBufferObject->GetChangeBits() & BufferChangeBits::ForbidInvalidationBit); + Bool useUnsynchronizedMap = + !(stateBufferObject->GetChangeBits() & BufferChangeBits::ForbidUnsynchronizationBit); + Bool useMapBufferRange = useInvalidationMap || useUnsynchronizedMap; + + if (!useMapBufferRange && PREFER_MAP_BUFFER_RANGE_FOR_BUFFER_SYNC) { + auto usage = stateBufferObject->GetUsage(); + if (usage == BufferUsage::DynamicDraw || usage == BufferUsage::StreamDraw || + usage == BufferUsage::StreamCopy || usage == BufferUsage::DynamicCopy) { + useMapBufferRange = true; + } } + if (useMapBufferRange) { + MGLOG_D("Using glMapBufferRange to sync buffer with ID: %u", m_backendBufferId); + SyncToBackend_glMapBufferRange(stateBufferObject, useInvalidationMap, useUnsynchronizedMap); + } else { + MGLOG_D("Using glBufferSubData to sync buffer with ID: %u", m_backendBufferId); + SyncToBackend_glBufferSubData(stateBufferObject); + } + + // Clear dirty state stateBufferObject->ClearDirty(); m_prevBufferSize = bufferSize; } @@ -102,8 +115,6 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId); MG_External::GLES::glBufferData(TempBufferTarget, size, data, usage); - - stateBufferObject->ClearDirty(); } void BackendBufferObject::SyncToBackend_glBufferSubData( @@ -117,19 +128,21 @@ namespace MobileGL::MG_Backend::DirectGLES { const void* data = stateBufferObject->GetDataReadOnly()->data(); // dirty range: [range.start, range.end) - const auto& range = stateBufferObject->GetDirtyRange(); - if (range.end == 0) { + auto ranges = stateBufferObject->GetDirtyRanges(); + if (ranges.empty()) { MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId); return; } - MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId); - MG_External::GLES::glBufferSubData(TempBufferTarget, range.start, range.end - range.start, - reinterpret_cast(data) + range.start); + for (const auto& range : ranges) { + MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId); + MG_External::GLES::glBufferSubData(TempBufferTarget, range.start, range.end - range.start, + reinterpret_cast(data) + range.start); + } } void BackendBufferObject::SyncToBackend_glMapBufferRange( - SharedPtr& stateBufferObject, Bool invalidate) { + SharedPtr& stateBufferObject, Bool invalidate, Bool unsynchronized) { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif @@ -137,19 +150,27 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("Syncing buffer map (glMapBuffer) for object with ID : %u", m_backendBufferId); MGLOG_D("Mapping buffer with ID: %u", m_backendBufferId); - const auto& range = stateBufferObject->GetDirtyRange(); - if (range.end == 0) { + auto ranges = stateBufferObject->GetDirtyRanges(); + if (ranges.empty()) { MGLOG_D("No dirty range to sync for buffer with ID: %u", m_backendBufferId); return; } + SizeT minStart = ranges.GetOverallMinStart(); + SizeT maxEnd = ranges.GetOverallMaxEnd(); MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId); - void* mappedData = - MG_External::GLES::glMapBufferRange(TempBufferTarget, range.start, range.end - range.start, - (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : 0) | GL_MAP_WRITE_BIT); + void* mappedData = MG_External::GLES::glMapBufferRange( + TempBufferTarget, minStart, maxEnd - minStart, + (invalidate ? GL_MAP_INVALIDATE_RANGE_BIT : 0) | (unsynchronized ? GL_MAP_UNSYNCHRONIZED_BIT : 0) | + GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); const void* data = stateBufferObject->GetDataReadOnly()->data(); if (mappedData) { - Memcpy(mappedData, ((const char*)(data) + range.start), range.end - range.start); MGLOG_D("Mapped buffer data successfully for object with ID: %u", m_backendBufferId); + Memcpy(mappedData, reinterpret_cast(data) + minStart, maxEnd - minStart); + // Explicitly flush the dirty ranges + for (const auto& range : ranges) { + MG_External::GLES::glFlushMappedBufferRange(TempBufferTarget, range.start - minStart, + range.end - range.start); + } MG_External::GLES::glUnmapBuffer(TempBufferTarget); } else { MGLOG_E("Failed to map buffer with ID: %u", m_backendBufferId); @@ -328,7 +349,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // 4. Mipmap levels changed if (!stateTextureObject->IsComplete()) { - MGLOG_D("Texture object with ID: %u is not complete, skipping sync.", stateTextureObject->GetExternalIndex()); + MGLOG_D("Texture object with ID: %u is not complete, skipping sync.", + stateTextureObject->GetExternalIndex()); return; } @@ -376,39 +398,42 @@ namespace MobileGL::MG_Backend::DirectGLES { 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, levelDirty = %s", __func__, - MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level, - levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData, levelDirty ? "true" : "false"); + MGLOG_D( + "%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p, levelDirty = %s", + __func__, MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level, + levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData, + levelDirty ? "true" : "false"); errorLopper.Clear(); MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); auto textureTarget = stateTextureObject->GetTarget(); // TODO: handle more texture types switch (textureTarget) { - case TextureTarget::Texture2D: - case TextureTarget::TextureCubeMap: - { - MG_External::GLES::glTexImage2D(glUploadTarget, static_cast(level), glInternalFormat, - static_cast(levelTexelSize.x()), - static_cast(levelTexelSize.y()), 0, glFormat, - glType, pData); - break; - } - case TextureTarget::Texture3D: { - MG_External::GLES::glTexImage3D(glUploadTarget, static_cast(level), glInternalFormat, - static_cast(levelTexelSize.x()), - static_cast(levelTexelSize.y()), - static_cast(levelTexelSize.z()), - 0, glFormat, - glType, pData); - break; - } - default: { - MGLOG_E("Unhandled texture target %s", MG_Util::ConvertTextureTargetToString(textureTarget).c_str()); - } + case TextureTarget::Texture2D: + case TextureTarget::TextureCubeMap: { + MG_External::GLES::glTexImage2D( + glUploadTarget, static_cast(level), glInternalFormat, + static_cast(levelTexelSize.x()), static_cast(levelTexelSize.y()), + 0, glFormat, glType, pData); + break; } - errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, glUploadTarget, glInternalFormat, glFormat, glType, pData](GLenum err) { - MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, type=%s, pixels=%p", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(), + case TextureTarget::Texture3D: { + MG_External::GLES::glTexImage3D( + glUploadTarget, static_cast(level), glInternalFormat, + static_cast(levelTexelSize.x()), static_cast(levelTexelSize.y()), + static_cast(levelTexelSize.z()), 0, glFormat, glType, pData); + break; + } + default: { + MGLOG_E("Unhandled texture target %s", + MG_Util::ConvertTextureTargetToString(textureTarget).c_str()); + } + } + errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__, glUploadTarget, + glInternalFormat, glFormat, glType, pData](GLenum err) { + MGLOG_D("%s(%s:%d) ES error: %s. glTexImage*: target=%s, internalformat=%s, format=%s, " + "type=%s, pixels=%p", + func, file, line, MG_Util::ConvertGLEnumToString(err).c_str(), MG_Util::ConvertGLEnumToString(glUploadTarget).c_str(), MG_Util::ConvertGLEnumToString(glInternalFormat).c_str(), MG_Util::ConvertGLEnumToString(glFormat).c_str(), @@ -493,8 +518,8 @@ namespace MobileGL::MG_Backend::DirectGLES { auto backendId = backendBufferObject->GetBackendBufferId(); GLenum glInternalFormat, glType, glFormat; - TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, - &glFormat, &glType); + TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, &glFormat, + &glType); MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId); break; @@ -1129,8 +1154,7 @@ namespace MobileGL::MG_Backend::DirectGLES { Int width = static_cast(stateRBOObject->GetWidth()); Int height = static_cast(stateRBOObject->GetHeight()); GLenum glInternalFormat, glType, glFormat; - TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, - &glFormat, &glType); + TextureImpl::GenerateTextureFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType); MG_External::GLES::glRenderbufferStorage(GL_RENDERBUFFER, glInternalFormat, static_cast(width), static_cast(height)); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index c3ac25eb..506e0cb8 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -28,7 +28,7 @@ namespace MobileGL::MG_Backend::DirectGLES { void SyncToBackend_glBufferData(SharedPtr& stateBufferObject); void SyncToBackend_glBufferSubData(SharedPtr& stateBufferObject); void SyncToBackend_glMapBufferRange(SharedPtr& stateBufferObject, - Bool invalidate = true); + Bool invalidate = true, Bool unsynchronized = true); Uint m_backendBufferId = 0; SizeT m_prevBufferSize = 0; @@ -58,12 +58,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace TextureImpl { inline Bool IsSupportedTextureTarget(TextureTarget target) { - if (target == TextureTarget::Texture1D || - target == TextureTarget::TextureRectangle || - target == TextureTarget::Texture2DMultisampleArray || - target == TextureTarget::Texture1DArray || - target == TextureTarget::Texture2DMultisample || - target == TextureTarget::Texture2DArray) + if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle || + target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray || + target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray) return false; return true; } diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index f8cb2fee..65435cb8 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -74,13 +74,10 @@ namespace MobileGL::MG_Backend::DirectGLES { ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif using namespace MobileGL::MG_Util::TextureFormatProcessor; - auto options = - (MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None : PixelFormatNormalizeOptionBit::NoNorm16; - NormalizePixelFormat( - MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), - options, - outInternalFormat, - outFormat, outType); + auto options = (MG_External::GLES::g_glesCaps.hasNorm16Texture) ? PixelFormatNormalizeOptionBit::None + : PixelFormatNormalizeOptionBit::NoNorm16; + NormalizePixelFormat(MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), options, + outInternalFormat, outFormat, outType); } } // namespace TextureImpl diff --git a/MobileGL/MG_Impl/EGLImpl/EGLWrapper/EGLWrapper.cpp b/MobileGL/MG_Impl/EGLImpl/EGLWrapper/EGLWrapper.cpp index 7ea342de..d187c756 100644 --- a/MobileGL/MG_Impl/EGLImpl/EGLWrapper/EGLWrapper.cpp +++ b/MobileGL/MG_Impl/EGLImpl/EGLWrapper/EGLWrapper.cpp @@ -88,7 +88,7 @@ namespace MobileGL { return MG_External::EGL::eglQuerySurface(display, surface, attribute, value); } - char const * QueryString(EGLDisplay display, EGLint name) { + char const* QueryString(EGLDisplay display, EGLint name) { return MG_External::EGL::eglQueryString(display, name); } @@ -122,7 +122,7 @@ namespace MobileGL { } EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, - const EGLint* attrib_list) { + const EGLint* attrib_list) { return MG_External::EGL::eglCreatePixmapSurface(dpy, config, pixmap, attrib_list); } @@ -170,51 +170,45 @@ namespace MobileGL { return (__eglMustCastToProperFunctionPointerType)proc; } - EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list) { + EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list) { return MG_External::EGL::eglCreateSync(dpy, type, attrib_list); } - EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync) { return MG_External::EGL::eglDestroySync(dpy, sync); } - EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) { return MG_External::EGL::eglClientWaitSync(dpy, sync, flags, timeout); } - - EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value) { + EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value) { return MG_External::EGL::eglGetSyncAttrib(dpy, sync, attribute, value); } - - EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list) { + EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, + const EGLAttrib* attrib_list) { return MG_External::EGL::eglCreateImage(dpy, ctx, target, buffer, attrib_list); } - EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image) { return MG_External::EGL::eglDestroyImage(dpy, image); } - - EGLDisplay GetPlatformDisplay(EGLenum platform, void * native_display, const EGLAttrib * attrib_list) { + EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list) { return MG_External::EGL::eglGetPlatformDisplay(platform, native_display, attrib_list); } - - EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list) { + EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window, + const EGLAttrib* attrib_list) { return MG_External::EGL::eglCreatePlatformWindowSurface(dpy, config, native_window, attrib_list); } - - EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list) { + EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap, + const EGLAttrib* attrib_list) { return MG_External::EGL::eglCreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list); } - EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) { return MG_External::EGL::eglWaitSync(dpy, sync, flags); } diff --git a/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.cpp b/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.cpp index bcd93d6a..d3cc5508 100644 --- a/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.cpp +++ b/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.cpp @@ -98,7 +98,7 @@ namespace MobileGL { return EGL_TRUE; } - char const * QueryString(EGLDisplay display, EGLint name) { + char const* QueryString(EGLDisplay display, EGLint name) { return ""; } @@ -132,7 +132,7 @@ namespace MobileGL { } EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, - const EGLint* attrib_list) { + const EGLint* attrib_list) { return (EGLSurface)1; } diff --git a/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.h b/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.h index a72edbf4..c1f89733 100644 --- a/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.h +++ b/MobileGL/MG_Impl/EGLImpl/Temporary/TemporaryEGLImpl.h @@ -29,7 +29,7 @@ namespace MobileGL { EGLBoolean BindAPI(EGLenum api); EGLSurface GetCurrentSurface(EGLint readdraw); EGLBoolean QuerySurface(EGLDisplay display, EGLSurface surface, EGLint attribute, EGLint* value); - char const * QueryString(EGLDisplay display, EGLint name); + char const* QueryString(EGLDisplay display, EGLint name); EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval); EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface draw); EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list); @@ -39,7 +39,7 @@ namespace MobileGL { EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint* attrib_list); EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, - const EGLint* attrib_list); + const EGLint* attrib_list); EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config); EGLDisplay GetCurrentDisplay(void); EGLenum QueryAPI(void); @@ -49,15 +49,18 @@ namespace MobileGL { EGLBoolean WaitGL(void); EGLBoolean WaitNative(EGLint engine); __eglMustCastToProperFunctionPointerType GetProcAddress(const char* name); - EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list); + EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list); EGLBoolean DestroySync(EGLDisplay dpy, EGLSync sync); EGLint ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); - EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value); - EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list); + EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib* value); + EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, + const EGLAttrib* attrib_list); EGLBoolean DestroyImage(EGLDisplay dpy, EGLImage image); - EGLDisplay GetPlatformDisplay(EGLenum platform, void * native_display, const EGLAttrib * attrib_list); - EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list); - EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list); + EGLDisplay GetPlatformDisplay(EGLenum platform, void* native_display, const EGLAttrib* attrib_list); + EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void* native_window, + const EGLAttrib* attrib_list); + EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void* native_pixmap, + const EGLAttrib* attrib_list); EGLBoolean WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags); } // namespace MG_Impl::EGLImpl } // namespace MobileGL diff --git a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp index 3e06d5a6..a6c92001 100644 --- a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp @@ -525,8 +525,7 @@ namespace MobileGL { auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex); point.Bind(bufferObject); point.SetRange(Range1D(0, bufferObject->GetSize())); - MGLOG_D("%s: set range (0, %d)", __func__, - bufferObject->GetSize()); + MGLOG_D("%s: set range (0, %d)", __func__, bufferObject->GetSize()); } void BindBufferRange_State(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { @@ -575,6 +574,7 @@ namespace MobileGL { return MapBuffer_State(target, access); } + // FIXME: this should be a "backend" function void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { CopyBufferSubData_State(readTarget, writeTarget, readOffset, writeOffset, size); diff --git a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h index 981de9b9..fe1f0339 100644 --- a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h +++ b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.h @@ -12,16 +12,22 @@ namespace MobileGL { namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */ - void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride); + void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, + GLsizei stride); void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride); - void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices, GLint basevertex); + void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const void* indices, GLint basevertex); void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices); - void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); - void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex); - void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLuint baseinstance); + void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLint basevertex, GLuint baseinstance); + void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLint basevertex); + void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLuint baseinstance); void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount); void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect); - void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); + void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, + GLuint baseinstance); void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); void DrawArraysIndirect(GLenum mode, const void* indirect); void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex); diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index b907e57d..e538ab9e 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -516,15 +516,15 @@ namespace MobileGL { void Uniform_State(MG_State::GLState::ProgramObject& programObject, GLuint location, T* value, SizeT byteOffsetInsideUniform = 0) { if (!programObject.IsUniformOpaqueAtLocation(location)) { - MGLOG_D("%s: program = %d, location = %d, maxLocation = %d", __func__, - programObject.GetExternalIndex(), location, programObject.GetMaxUniformLocation()); + MGLOG_D("%s: program = %d, location = %d, maxLocation = %d", __func__, programObject.GetExternalIndex(), + location, programObject.GetMaxUniformLocation()); auto size = programObject.GetUniformSizesInBytes(location); auto offset = programObject.GetUniformOffset(location); MOBILEGL_ASSERT(size >= ItemCount * sizeof(T), "Uniform size mismatch, expected at least %zu bytes, got %zu bytes.", ItemCount * sizeof(T), size); - MGLOG_D("%s: program = %d, location = %d, byteOffset = %d", __func__, - programObject.GetExternalIndex(), location, offset + byteOffsetInsideUniform); + MGLOG_D("%s: program = %d, location = %d, byteOffset = %d", __func__, programObject.GetExternalIndex(), + location, offset + byteOffsetInsideUniform); Memcpy((char*)programObject.MapUBO() + offset + byteOffsetInsideUniform, value, ItemCount * sizeof(T)); } else { auto* ttype = programObject.GetUniformTType(location); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 137a2c66..911fca93 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -63,8 +63,7 @@ namespace MobileGL { // TextureInternalFormat textureInternalFormat = // MG_Util::ConvertGLEnumToTextureInternalFormat(format); MGLOG_D("TexSubImage2D_State: target = %s, level = %d, (%d, %d), format = %s, pixels = %p", - MG_Util::ConvertGLEnumToString(target).c_str(), level, - width, height, + MG_Util::ConvertGLEnumToString(target).c_str(), level, width, height, MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), pixels); // ===================== Error Checking ============================== if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; @@ -502,14 +501,18 @@ namespace MobileGL { GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) { MGLOG_D( "%s called with target: %s, level: %d, internalformat: %s, width: %d, height: %d, depth: %d, " - "border: %d, format: %s, type: %s (%u), pixels: %p", __func__, - MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)).c_str(), + "border: %d, format: %s, type: %s (%u), pixels: %p", + __func__, + MG_Util::ConvertTextureUploadTargetToString(MG_Util::ConvertGLEnumToTextureUploadTarget(target)) + .c_str(), level, MG_Util::ConvertTextureInternalFormatToString( - MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)).c_str(), + MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)) + .c_str(), width, height, depth, border, MG_Util::ConvertTextureInputFormatToString(MG_Util::ConvertGLEnumToTextureInputFormat(format)).c_str(), - MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)).c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(MG_Util::ConvertGLEnumToTexturePixelDataType(type)) + .c_str(), type, pixels); // ======================= Converting ================================ TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); @@ -580,13 +583,13 @@ namespace MobileGL { reinterpret_cast(pixels); } - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); auto textureMipmapObject = static_cast(textureObject.get()); // Allocate in TextureObject - textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, depth}, internalBytes}); + textureMipmapObject->AllocateStorage(textureUploadingTarget, level, + {{width, height, depth}, internalBytes}); if (!originalPixels) { MGLOG_D("%s: No input pixel and no PBO bound, no pixel transfer", __func__); @@ -601,8 +604,8 @@ namespace MobileGL { if (processedPixels && imageSize > 0) { if (imageSize != internalBytes) { MGLOG_W("%s: Processed pixel data size (%zu) does not match expected size (%zu). " - "This may indicate an alignment or processing issue.", __func__, - imageSize, internalBytes); + "This may indicate an alignment or processing issue.", + __func__, imageSize, internalBytes); } const SizeT copySize = std::min(imageSize, internalBytes); @@ -623,20 +626,16 @@ namespace MobileGL { TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); - MGLOG_D( - "%s called with target: %s (%s), level: %d, internalformat: %s (%s), width: %d, height: %d, " - "border: %d, format: %s (%s), type: %s (%s), pixels: %p", __func__, - MG_Util::ConvertTextureUploadTargetToString(textureUploadingTarget).c_str(), - MG_Util::ConvertGLEnumToString(target).c_str(), - level, + MGLOG_D("%s called with target: %s (%s), level: %d, internalformat: %s (%s), width: %d, height: %d, " + "border: %d, format: %s (%s), type: %s (%s), pixels: %p", + __func__, MG_Util::ConvertTextureUploadTargetToString(textureUploadingTarget).c_str(), + MG_Util::ConvertGLEnumToString(target).c_str(), level, MG_Util::ConvertTextureInternalFormatToString(textureInternalFormat).c_str(), - MG_Util::ConvertGLEnumToString(internalformat).c_str(), - width, height, border, + MG_Util::ConvertGLEnumToString(internalformat).c_str(), width, height, border, MG_Util::ConvertTextureInputFormatToString(textureInputFormat).c_str(), MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertTexturePixelDataTypeToString(texturePixelDataType).c_str(), - MG_Util::ConvertGLEnumToString(type).c_str(), - pixels); + MG_Util::ConvertGLEnumToString(type).c_str(), pixels); // ===================== Error Checking ============================== if (!TextureImpl::ValidateTexturePixelDataType(texturePixelDataType)) return; if (!TextureImpl::ValidateTextureInputFormat(textureInputFormat)) return; @@ -661,7 +660,8 @@ namespace MobileGL { // indicated by type. // ======================= Processing ================================ - textureInternalFormat = MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType); + textureInternalFormat = + MG_Util::ConvertInternalFormatToSized(textureInternalFormat, textureInputFormat, texturePixelDataType); SharedPtr textureObject = nullptr; Bool isProxy = TextureImpl::IsProxyTextureTarget(textureUploadingTarget); if (isProxy) { @@ -1227,11 +1227,12 @@ namespace MobileGL { } void CopyTexImage2D_State(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, - GLsizei height, GLint border) { + GLsizei height, GLint border) { GLenum outInternalFormat, format, type; - MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format, &type); + MG_Util::TextureFormatProcessor::NormalizePixelFormat(internalformat, 0, &outInternalFormat, &format, + &type); const auto pixelUnpackBufferObject = - MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); + MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); TexImage2D_State(target, level, outInternalFormat, width, height, border, format, type, nullptr); MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).Bind(pixelUnpackBufferObject); } diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h index a2f88891..97b4047d 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h @@ -20,10 +20,10 @@ namespace MobileGL { const GLvoid* pixels); void TexParameterf(GLenum target, GLenum pname, GLfloat param); void TexParameteri(GLenum target, GLenum pname, GLint param); - void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params); - void TexParameteriv(GLenum target, GLenum pname, const GLint * params); - void TexParameterIiv(GLenum target, GLenum pname, const GLint * params); - void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params); + void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params); + void TexParameteriv(GLenum target, GLenum pname, const GLint* params); + void TexParameterIiv(GLenum target, GLenum pname, const GLint* params); + void TexParameterIuiv(GLenum target, GLenum pname, const GLuint* params); void TexImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp index 0e49813f..e2e86f49 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp @@ -170,7 +170,8 @@ namespace MobileGL::MG_Impl::GLImpl { } return true; } - Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat, + Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, + TextureInternalFormat internalFormat, TexturePixelDataType type) { if (type == TexturePixelDataType::UnsignedByte332 || type == TexturePixelDataType::UnsignedByte233Rev || type == TexturePixelDataType::UnsignedShort565 || type == TexturePixelDataType::UnsignedShort565Rev || @@ -178,7 +179,8 @@ namespace MobileGL::MG_Impl::GLImpl { if (format != TextureInputFormat::RGB) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput", + MakeShared("MG_Impl/GLImpl", + "ValidateTextureInternalFormatCompatibleWithInput", "Invalid format for the given type")); return false; } @@ -193,7 +195,8 @@ namespace MobileGL::MG_Impl::GLImpl { if (format != TextureInputFormat::RGBA && format != TextureInputFormat::BGRA) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput", + MakeShared("MG_Impl/GLImpl", + "ValidateTextureInternalFormatCompatibleWithInput", "Invalid format for the given type")); return false; } @@ -206,7 +209,8 @@ namespace MobileGL::MG_Impl::GLImpl { if (format != TextureInputFormat::DepthComponent) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", "ValidateTextureInternalFormatCompatibleWithInput", + MakeShared("MG_Impl/GLImpl", + "ValidateTextureInternalFormatCompatibleWithInput", "Invalid format for depth component internal format")); return false; } diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h index f1caac2e..2ee4f0a4 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h @@ -23,7 +23,8 @@ namespace MobileGL::MG_Impl::GLImpl { Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth); Bool ValidateTextureInternalFormat(TextureInternalFormat format); Bool ValidateTextureBorderNumber(Int border); - Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, TextureInternalFormat internalFormat, + Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format, + TextureInternalFormat internalFormat, TexturePixelDataType type); Bool ValidateTextureLevelWithUploadTarget(TextureUploadTarget target, Int level); Bool ValidateTextureObject(SharedPtr textureObject); diff --git a/MobileGL/MG_Impl/GetProcAddress.cpp b/MobileGL/MG_Impl/GetProcAddress.cpp index 559856ab..a9f6f699 100644 --- a/MobileGL/MG_Impl/GetProcAddress.cpp +++ b/MobileGL/MG_Impl/GetProcAddress.cpp @@ -7,9 +7,9 @@ // End of Source File Header #include "GetProcAddress.h" -#define GETPROC(name, var) \ - if (strcmp(#name, var) == 0) { \ - return (void*)name; \ +#define GETPROC(name, var) \ + if (strcmp(#name, var) == 0) { \ + return (void*)name; \ } namespace MobileGL { diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp b/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp index 5e70ce51..6eb77b61 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp @@ -14,14 +14,18 @@ namespace MobileGL { namespace GLState { BufferObject::BufferObject(Uint externalIndex) : m_externalIndex(externalIndex), m_size(0), m_usage(BufferUsage::StaticDraw), m_isMapped(false), - m_mappingAccess(BufferMappingAccessBit::Null), m_dirtyRange({0, 0}), m_mappedRange({0, 0}), - m_dataPtr(MakeShared()) {} + m_mappingAccess(BufferMappingAccessBit::Null), + m_change(BufferChangeBits::DirtyBit | BufferChangeBits::PreferReallocationBit), m_mappedRange({0, 0}), + m_dataPtr(MakeShared()) { + m_change.DirtyRanges.reserve(BufferChange::DEFAULT_RESERVED_DIRTY_RANGES_COUNT); + } void BufferObject::Resize(SizeT size) { m_size = size; m_dataPtr->reserve(std::bit_ceil(size)); // power-of-2 reserve m_dataPtr->resize(size); - m_dirtyRange = {0, 0}; + m_change.Bits |= BufferChangeBits::DirtyBit; + m_change.Bits |= BufferChangeBits::PreferReallocationBit; } void BufferObject::UploadData(DataPtr data, SizeT atOffset) { @@ -30,7 +34,14 @@ namespace MobileGL { data.size, m_size); MOBILEGL_ASSERT(!m_isMapped, "Cannot upload data while buffer is mapped."); Memcpy(m_dataPtr->data() + atOffset, data.data, data.size); - m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size); + m_change.DirtyRanges.Add({atOffset, atOffset + data.size}); + m_change.Bits |= BufferChangeBits::DirtyBit; + m_change.Bits |= BufferChangeBits::ForbidInvalidationBit; + m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit; + // This function may be called by `glBufferData`, but we still set the forbid bits above, + // because when `PreferReallocationBit` is set, those bits are ignored anyway. + // The bits can fit the `glBufferSubData` semantics + // (though `glBufferSubData` calls `UploadSubData` instead). } void BufferObject::SetUsage(BufferUsage usage) { @@ -44,7 +55,8 @@ namespace MobileGL { if (!(m_mappingAccess & BufferMappingAccessBit::FlushExplicit)) { // if we didn't flush explicitly Memcpy(m_dataPtr->data() + m_mappedRange.start, m_stagingData.data(), m_mappedRange.end - m_mappedRange.start); - m_dirtyRange.UnionUpdate(m_mappedRange.start, m_mappedRange.end); + m_change.DirtyRanges.Add({m_mappedRange.start, m_mappedRange.end}); + m_change.Bits |= BufferChangeBits::DirtyBit; } m_stagingData.clear(); @@ -69,7 +81,8 @@ namespace MobileGL { "Flush range out of bounds: mappedRange.end (%zu) < end (%zu)", m_mappedRange.end, end); Memcpy(m_dataPtr->data() + start, m_stagingData.data() + offset, length); - m_dirtyRange.UnionUpdate(start, end); + m_change.DirtyRanges.Add({start, end}); + m_change.Bits |= BufferChangeBits::DirtyBit; } void BufferObject::UploadSubData(DataPtr data, SizeT atOffset) { @@ -79,7 +92,10 @@ namespace MobileGL { atOffset, data.size, m_size); Memcpy(m_dataPtr->data() + atOffset, data.data, data.size); - m_dirtyRange.UnionUpdate(atOffset, atOffset + data.size); + m_change.DirtyRanges.Add({atOffset, atOffset + data.size}); + m_change.Bits |= BufferChangeBits::DirtyBit; + m_change.Bits |= BufferChangeBits::ForbidInvalidationBit; + m_change.Bits |= BufferChangeBits::ForbidUnsynchronizationBit; } void BufferObject::CopyDataFrom(const SharedPtr& src, SizeT srcOffset, SizeT dstOffset, @@ -95,7 +111,8 @@ namespace MobileGL { const Uint8* srcData = src->m_dataPtr->data() + srcOffset; Memcpy(m_dataPtr->data() + dstOffset, srcData, size); - m_dirtyRange.UnionUpdate(dstOffset, dstOffset + size); + m_change.DirtyRanges.Add({dstOffset, dstOffset + size}); + m_change.Bits |= BufferChangeBits::DirtyBit; } void* BufferObject::AcquireMemory(Bool markMapped, Bool read, Bool write) { @@ -144,6 +161,14 @@ namespace MobileGL { m_ownsStagingData = false; return m_dataPtr->data() + range.start; } + + m_change.Bits |= !(access & BufferMappingAccessBit::InvalidateBuffer || + access & BufferMappingAccessBit::InvalidateRange) + ? BufferChangeBits::ForbidInvalidationBit + : BufferChangeBits::None; + m_change.Bits |= !(access & BufferMappingAccessBit::Unsynchronized) + ? BufferChangeBits::ForbidUnsynchronizationBit + : BufferChangeBits::None; } const SharedPtr BufferObject::GetDataReadOnly() const { @@ -151,7 +176,8 @@ namespace MobileGL { } void BufferObject::ClearDirty() { - m_dirtyRange = {0, 0}; + m_change.DirtyRanges.clear(); + m_change.Bits = BufferChangeBits::None; } SizeT BufferObject::GetSize() const { @@ -162,8 +188,12 @@ namespace MobileGL { return m_usage; } - Range1D BufferObject::GetDirtyRange() const { - return m_dirtyRange; + const VecRange1D& BufferObject::GetDirtyRanges() const { + return m_change.DirtyRanges; + } + + Flags BufferObject::GetChangeBits() const { + return m_change.Bits; } Bool BufferObject::IsMapped() const { diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.h b/MobileGL/MG_State/GLState/BufferState/BufferObject.h index 69bf74c9..99caf195 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferObject.h +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.h @@ -9,6 +9,7 @@ #pragma once #include "MG_Util/Types.h" #include +#include namespace MobileGL { enum class BufferTarget { @@ -55,6 +56,23 @@ namespace MobileGL { Coherent = 0x80 }; + enum class BufferChangeBits : Uint8 { + None = 0, + DirtyBit = 1 << 0, // When not set, bits below are ignored and nothing should be synced to backend + PreferReallocationBit = + 1 << 1, // <=> `glBufferData`; When set, ForbidInvalidationBit and ForbidUnsynchronizationBit are ignored + ForbidInvalidationBit = 1 << 2, // Indidate that invalidation flags were not used during mapping, else we're + // allowed to act as `GL_MAP_INVALIDATE_*` in backend + ForbidUnsynchronizationBit = 1 << 3, // (the same description as above, but for unsynchronization) + }; + + struct BufferChange { + static constexpr int DEFAULT_RESERVED_DIRTY_RANGES_COUNT = 50; + + Flags Bits = BufferChangeBits::None; + VecRange1D DirtyRanges; + }; + namespace MG_State { namespace GLState { class BufferObject { @@ -77,11 +95,12 @@ namespace MobileGL { Bool IsMapped() const; SizeT GetSize() const; BufferUsage GetUsage() const; - Range1D GetDirtyRange() const; Range1D GetMappedRange() const; const SharedPtr GetDataReadOnly() const; Flags GetMappingAccess() const; Uint GetExternalIndex() const; + const VecRange1D& GetDirtyRanges() const; + Flags GetChangeBits() const; private: const Uint m_externalIndex = 0; @@ -90,7 +109,7 @@ namespace MobileGL { SharedPtr m_dataPtr; Bool m_isMapped; Flags m_mappingAccess; - Range1D m_dirtyRange; + BufferChange m_change; Range1D m_mappedRange; Vector m_stagingData; Bool m_ownsStagingData; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 09240926..53112caf 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -453,7 +453,7 @@ namespace MobileGL { MGLOG_D("ProgramObject %u: GenerateBinary - generated %zu SPIR-V modules", m_externalIndex, m_generatedSpirv.size()); - for (auto& spv: m_generatedSpirv) { + for (auto& spv : m_generatedSpirv) { auto success = ShaderCompiler::SanitizeAndOptimizeBinary(spv, spv); MOBILEGL_ASSERT(success, "SanitizeBinary failed"); } diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp index bcd0ed7b..62875667 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp @@ -42,7 +42,8 @@ namespace MobileGL { } else { m_compileStatus = false; m_infoLog = result.error().log; - MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting m_compileStatus = false as a result.", + MGLOG_D("ShaderObject::Compile: Shader %d compilation failed.\nSource:\n%s\nInfoLog:\n%s\nSetting " + "m_compileStatus = false as a result.", m_externalIndex, m_source.c_str(), m_infoLog.c_str()); } } diff --git a/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h b/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h index 683f3dcf..5976986d 100644 --- a/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h +++ b/MobileGL/MG_State/GLState/TextureState/MipmapStorage.h @@ -25,6 +25,7 @@ namespace MobileGL { SizeT GetByteSize(Uint level) const; void MarkDirty(Uint level, bool dirty); bool IsDirty(Uint level) const; + protected: Vector m_texelSizes; Vector> m_data; diff --git a/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h b/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h index 2d5a0627..c0fc19dd 100644 --- a/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h +++ b/MobileGL/MG_State/GLState/TextureState/MipmapUploadTargetArray.h @@ -19,7 +19,9 @@ namespace MobileGL { template class MipmapUploadTargetArray { public: - MipmapUploadTargetArray() { static_assert(TargetCount > 0, "Upload target count must be greater than zero"); } + MipmapUploadTargetArray() { + static_assert(TargetCount > 0, "Upload target count must be greater than zero"); + } void AllocateLevel(Uint targetIndex, Uint level, MipmapInput input) { MOBILEGL_ASSERT(targetIndex < TargetCount, "AllocateLevel: target invalid"); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index 960835d7..dab1b41c 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -81,7 +81,8 @@ namespace MobileGL { class TextureObjectMipmap : public TextureObjectBase { public: - TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} + TextureObjectMipmap(TextureTarget target, Uint externalIndex) + : TextureObjectBase(target, externalIndex) {} TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h index cf8c3e00..f5d7928e 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h @@ -18,7 +18,8 @@ namespace MobileGL { TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; } explicit TextureObjectBuffer(Uint externalIndex); const Vector& GetUploadTargets() const override { return m_uploadTargets; } - BindingSlot& GetBufferBindingSlot(TextureUploadTarget target = TextureUploadTarget::TextureBuffer); + BindingSlot& GetBufferBindingSlot( + TextureUploadTarget target = TextureUploadTarget::TextureBuffer); protected: Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; diff --git a/MobileGL/MG_Test/Program/ProgramTest.cpp b/MobileGL/MG_Test/Program/ProgramTest.cpp index 20b92a1d..cd183e26 100644 --- a/MobileGL/MG_Test/Program/ProgramTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramTest.cpp @@ -925,7 +925,7 @@ TEST_F(ProgramTest, CompileAndLinkWithExplicitVertexIn) { // auto& vertexSpirv = spirvs[1]; // 0 - fragment, 1 - vertex char* pSrcVertIn = nullptr; const char* needle = "layout(location = 2) in vec2 UV0;"; - for (auto spirv: spirvs) { + for (auto spirv : spirvs) { MG_Util::ShaderTranspiler::SpvcSession spvcSession(spirv); spvc_compiler_options options; spvcSession.CreateOptions(&options); diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp index 2a3be359..7e954f9d 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp @@ -457,7 +457,10 @@ namespace MobileGL { void *libGLES = nullptr, *libEGL = nullptr; static const char* LibPathPrefixes[] = { - "/opt/vc/lib/", "/usr/local/lib/", "/usr/lib/", "/usr/lib/x86_64-linux-gnu/", + "/opt/vc/lib/", + "/usr/local/lib/", + "/usr/lib/", + "/usr/lib/x86_64-linux-gnu/", "", // We should put this to the end of the list to avoid breaking `LD_LIBRARY_PATH` usage nullptr}; static const char* LibExts[] = {"so", "so.1", "so.2", "dylib", "dll", nullptr}; @@ -531,8 +534,10 @@ namespace MobileGL { } MGLOG_I("OpenGL ES capabilities:"); - MG_External::GLES::glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment); - MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment); + MG_External::GLES::glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, + &MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment); + MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", + MG_External::GLES::g_glesCaps.uniformBufferOffsetAlignment); } void InitGLES() { diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h index 2f7b49f0..7b548b7e 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h @@ -511,16 +511,18 @@ namespace MobileGL { typedef EGLBoolean (*eglWaitClient_PTR)(); typedef EGLBoolean (*eglWaitGL_PTR)(); typedef EGLBoolean (*eglWaitNative_PTR)(EGLint engine); - typedef EGLSync (*eglCreateSync_PTR)(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list); + typedef EGLSync (*eglCreateSync_PTR)(EGLDisplay dpy, EGLenum type, const EGLAttrib* attrib_list); typedef EGLBoolean (*eglDestroySync_PTR)(EGLDisplay dpy, EGLSync sync); typedef EGLint (*eglClientWaitSync_PTR)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); - typedef EGLBoolean (*eglGetSyncAttrib_PTR)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value); - typedef EGLImage (*eglCreateImage_PTR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list); + typedef EGLBoolean (*eglGetSyncAttrib_PTR)(EGLDisplay dpy, EGLSync sync, EGLint attribute, + EGLAttrib* value); + typedef EGLImage (*eglCreateImage_PTR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLAttrib* attrib_list); typedef EGLBoolean (*eglDestroyImage_PTR)(EGLDisplay dpy, EGLImage image); - typedef EGLSurface (*eglCreatePlatformPixmapSurface_PTR)(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list); + typedef EGLSurface (*eglCreatePlatformPixmapSurface_PTR)(EGLDisplay dpy, EGLConfig config, + void* native_pixmap, const EGLAttrib* attrib_list); typedef EGLBoolean (*eglWaitSync_PTR)(EGLDisplay dpy, EGLSync sync, EGLint flags); - EGL_FUNC_DECL(eglBindAPI) EGL_FUNC_DECL(eglBindTexImage) EGL_FUNC_DECL(eglChooseConfig) diff --git a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp index 3a899ccf..e3ce180c 100644 --- a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp +++ b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp @@ -234,7 +234,8 @@ namespace MobileGL { case GL_RGBA: return TextureInternalFormat::RGBA; default: - MGLOG_D("%s: unknown internal format %s", __func__, MG_Util::ConvertGLEnumToString(internalformat).c_str()); + MGLOG_D("%s: unknown internal format %s", __func__, + MG_Util::ConvertGLEnumToString(internalformat).c_str()); return TextureInternalFormat::Unknown; } } diff --git a/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp b/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp index ae103088..6bb12ac4 100644 --- a/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp +++ b/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.cpp @@ -53,144 +53,145 @@ namespace MobileGL { } } - TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInputFormat format, TexturePixelDataType type) { + TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, + TextureInputFormat format, TexturePixelDataType type) { switch (internalformat) { - case TextureInternalFormat::R8: - case TextureInternalFormat::R8Snorm: - case TextureInternalFormat::R16: - case TextureInternalFormat::R16Snorm: - case TextureInternalFormat::RG8: - case TextureInternalFormat::RG8Snorm: - case TextureInternalFormat::RG16: - case TextureInternalFormat::RG16Snorm: - case TextureInternalFormat::R3G3B2: - case TextureInternalFormat::RGB4: - case TextureInternalFormat::RGB5: - case TextureInternalFormat::RGB8: - case TextureInternalFormat::RGB8Snorm: - case TextureInternalFormat::RGB10: - case TextureInternalFormat::RGB12: - case TextureInternalFormat::RGB16Snorm: - case TextureInternalFormat::RGBA2: - case TextureInternalFormat::RGBA4: - case TextureInternalFormat::RGB5A1: - case TextureInternalFormat::RGBA8: - case TextureInternalFormat::RGBA8Snorm: - case TextureInternalFormat::RGB10A2: - case TextureInternalFormat::RGB10A2UI: - case TextureInternalFormat::RGBA12: - case TextureInternalFormat::RGBA16: - case TextureInternalFormat::SRGB8: - case TextureInternalFormat::SRGB8Alpha8: - case TextureInternalFormat::R16F: - case TextureInternalFormat::RG16F: - case TextureInternalFormat::RGB16F: - case TextureInternalFormat::RGBA16F: - case TextureInternalFormat::R32F: - case TextureInternalFormat::RG32F: - case TextureInternalFormat::RGB32F: - case TextureInternalFormat::RGBA32F: - case TextureInternalFormat::R11FG11FB10F: - case TextureInternalFormat::RGB9E5: - case TextureInternalFormat::R8I: - case TextureInternalFormat::R8UI: - case TextureInternalFormat::R16I: - case TextureInternalFormat::R16UI: - case TextureInternalFormat::R32I: - case TextureInternalFormat::R32UI: - case TextureInternalFormat::RG8I: - case TextureInternalFormat::RG8UI: - case TextureInternalFormat::RG16I: - case TextureInternalFormat::RG16UI: - case TextureInternalFormat::RG32I: - case TextureInternalFormat::RG32UI: - case TextureInternalFormat::RGB8I: - case TextureInternalFormat::RGB8UI: - case TextureInternalFormat::RGB16I: - case TextureInternalFormat::RGB16UI: - case TextureInternalFormat::RGB32I: - case TextureInternalFormat::RGB32UI: - case TextureInternalFormat::RGBA8I: - case TextureInternalFormat::RGBA8UI: - case TextureInternalFormat::RGBA16I: - case TextureInternalFormat::RGBA16UI: - case TextureInternalFormat::RGBA32I: - case TextureInternalFormat::RGBA32UI: - case TextureInternalFormat::DepthComponent16: - case TextureInternalFormat::DepthComponent24: - case TextureInternalFormat::DepthComponent32: // not a standard format in OpenGL core profile - case TextureInternalFormat::DepthComponent32F: - case TextureInternalFormat::Depth24Stencil8: - case TextureInternalFormat::Depth32FStencil8: - return internalformat; - // probably we should assume unorm here? - case TextureInternalFormat::RGBA: { - switch (type) { - case TexturePixelDataType::UnsignedByte: - return TextureInternalFormat::RGBA8; - case TexturePixelDataType::UnsignedShort: - return TextureInternalFormat::RGBA16; - default: - MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.", - __func__, - MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), - MG_Util::ConvertTextureInputFormatToString(format).c_str(), - MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); - return internalformat; - } - } - case TextureInternalFormat::RGB: { - switch (type) { - case TexturePixelDataType::UnsignedByte: - return TextureInternalFormat::RGB8; - default: - MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.", - __func__, - MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), - MG_Util::ConvertTextureInputFormatToString(format).c_str(), - MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); - return internalformat; - } - } - case TextureInternalFormat::RG: { - switch (type) { - case TexturePixelDataType::UnsignedByte: - return TextureInternalFormat::RG8; - case TexturePixelDataType::UnsignedShort: - return TextureInternalFormat::RG16; - default: - MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.", - __func__, - MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), - MG_Util::ConvertTextureInputFormatToString(format).c_str(), - MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); - return internalformat; - } - } - case TextureInternalFormat::Red: { - switch (type) { - case TexturePixelDataType::UnsignedByte: - return TextureInternalFormat::R8; - case TexturePixelDataType::UnsignedShort: - return TextureInternalFormat::R16; - default: - MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.", - __func__, - MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), - MG_Util::ConvertTextureInputFormatToString(format).c_str(), - MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); - return internalformat; - } - } - default: { - MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning original.", - __func__, - MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), + case TextureInternalFormat::R8: + case TextureInternalFormat::R8Snorm: + case TextureInternalFormat::R16: + case TextureInternalFormat::R16Snorm: + case TextureInternalFormat::RG8: + case TextureInternalFormat::RG8Snorm: + case TextureInternalFormat::RG16: + case TextureInternalFormat::RG16Snorm: + case TextureInternalFormat::R3G3B2: + case TextureInternalFormat::RGB4: + case TextureInternalFormat::RGB5: + case TextureInternalFormat::RGB8: + case TextureInternalFormat::RGB8Snorm: + case TextureInternalFormat::RGB10: + case TextureInternalFormat::RGB12: + case TextureInternalFormat::RGB16Snorm: + case TextureInternalFormat::RGBA2: + case TextureInternalFormat::RGBA4: + case TextureInternalFormat::RGB5A1: + case TextureInternalFormat::RGBA8: + case TextureInternalFormat::RGBA8Snorm: + case TextureInternalFormat::RGB10A2: + case TextureInternalFormat::RGB10A2UI: + case TextureInternalFormat::RGBA12: + case TextureInternalFormat::RGBA16: + case TextureInternalFormat::SRGB8: + case TextureInternalFormat::SRGB8Alpha8: + case TextureInternalFormat::R16F: + case TextureInternalFormat::RG16F: + case TextureInternalFormat::RGB16F: + case TextureInternalFormat::RGBA16F: + case TextureInternalFormat::R32F: + case TextureInternalFormat::RG32F: + case TextureInternalFormat::RGB32F: + case TextureInternalFormat::RGBA32F: + case TextureInternalFormat::R11FG11FB10F: + case TextureInternalFormat::RGB9E5: + case TextureInternalFormat::R8I: + case TextureInternalFormat::R8UI: + case TextureInternalFormat::R16I: + case TextureInternalFormat::R16UI: + case TextureInternalFormat::R32I: + case TextureInternalFormat::R32UI: + case TextureInternalFormat::RG8I: + case TextureInternalFormat::RG8UI: + case TextureInternalFormat::RG16I: + case TextureInternalFormat::RG16UI: + case TextureInternalFormat::RG32I: + case TextureInternalFormat::RG32UI: + case TextureInternalFormat::RGB8I: + case TextureInternalFormat::RGB8UI: + case TextureInternalFormat::RGB16I: + case TextureInternalFormat::RGB16UI: + case TextureInternalFormat::RGB32I: + case TextureInternalFormat::RGB32UI: + case TextureInternalFormat::RGBA8I: + case TextureInternalFormat::RGBA8UI: + case TextureInternalFormat::RGBA16I: + case TextureInternalFormat::RGBA16UI: + case TextureInternalFormat::RGBA32I: + case TextureInternalFormat::RGBA32UI: + case TextureInternalFormat::DepthComponent16: + case TextureInternalFormat::DepthComponent24: + case TextureInternalFormat::DepthComponent32: // not a standard format in OpenGL core profile + case TextureInternalFormat::DepthComponent32F: + case TextureInternalFormat::Depth24Stencil8: + case TextureInternalFormat::Depth32FStencil8: + return internalformat; + // probably we should assume unorm here? + case TextureInternalFormat::RGBA: { + switch (type) { + case TexturePixelDataType::UnsignedByte: + return TextureInternalFormat::RGBA8; + case TexturePixelDataType::UnsignedShort: + return TextureInternalFormat::RGBA16; + default: + MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, " + "returning original.", + __func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), MG_Util::ConvertTextureInputFormatToString(format).c_str(), MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); return internalformat; } } + case TextureInternalFormat::RGB: { + switch (type) { + case TexturePixelDataType::UnsignedByte: + return TextureInternalFormat::RGB8; + default: + MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, " + "returning original.", + __func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), + MG_Util::ConvertTextureInputFormatToString(format).c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); + return internalformat; + } + } + case TextureInternalFormat::RG: { + switch (type) { + case TexturePixelDataType::UnsignedByte: + return TextureInternalFormat::RG8; + case TexturePixelDataType::UnsignedShort: + return TextureInternalFormat::RG16; + default: + MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, " + "returning original.", + __func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), + MG_Util::ConvertTextureInputFormatToString(format).c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); + return internalformat; + } + } + case TextureInternalFormat::Red: { + switch (type) { + case TexturePixelDataType::UnsignedByte: + return TextureInternalFormat::R8; + case TexturePixelDataType::UnsignedShort: + return TextureInternalFormat::R16; + default: + MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, " + "returning original.", + __func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), + MG_Util::ConvertTextureInputFormatToString(format).c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); + return internalformat; + } + } + default: { + MGLOG_W("%s: Can't infer sized internal format from internalformat=%s, format=%s, type=%s, returning " + "original.", + __func__, MG_Util::ConvertTextureInternalFormatToString(internalformat).c_str(), + MG_Util::ConvertTextureInputFormatToString(format).c_str(), + MG_Util::ConvertTexturePixelDataTypeToString(type).c_str()); + return internalformat; + } + } } } // namespace MG_Util } // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.h b/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.h index ca10139c..e04bdf66 100644 --- a/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.h +++ b/MobileGL/MG_Util/Converters/MGToMG/TextureEnumConverter.h @@ -13,6 +13,7 @@ namespace MobileGL { namespace MG_Util { TextureTarget ConvertTextureUploadTargetToTextureTarget(TextureUploadTarget target); - TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, TextureInputFormat format, TexturePixelDataType type); + TextureInternalFormat ConvertInternalFormatToSized(TextureInternalFormat internalformat, + TextureInputFormat format, TexturePixelDataType type); } // namespace MG_Util } // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_Util/Debug/Log.cpp b/MobileGL/MG_Util/Debug/Log.cpp index a0a6a88a..32ccc68a 100644 --- a/MobileGL/MG_Util/Debug/Log.cpp +++ b/MobileGL/MG_Util/Debug/Log.cpp @@ -91,9 +91,9 @@ namespace MobileGL { int n = std::vsnprintf(buffer, sizeof(buffer), fmt, args); std::string out = header + #if MOBILEGL_LOG_ENABLE_STACKTRACE - padding + + padding + #endif - std::string(buffer, n) + "\n"; + std::string(buffer, n) + "\n"; #if MOBILEGL_LOG_ENABLE_CONSOLE std::fwrite(out.c_str(), 1, out.size(), stdout); diff --git a/MobileGL/MG_Util/Math/VectorTypes.cpp b/MobileGL/MG_Util/Math/VectorTypes.cpp new file mode 100644 index 00000000..b0d43a65 --- /dev/null +++ b/MobileGL/MG_Util/Math/VectorTypes.cpp @@ -0,0 +1,134 @@ +// MobileGL - MobileGL/MG_Util/Math/VectorTypes.cpp +// Copyright (c) 2025-2026 MobileGL-Dev +// Licensed under the GNU Lesser General Public License v3.0: +// https://www.gnu.org/licenses/gpl-3.0.txt +// https://www.gnu.org/licenses/lgpl-3.0.txt +// SPDX-License-Identifier: LGPL-3.0-only +// End of Source File Header + +#include "VectorTypes.h" + +namespace MobileGL { + void VecRange1D::Add(const Range1D& newRange, Double ratio, SizeT* outMinStart, SizeT* outMaxEnd) { + if (this->empty()) { + this->push_back(newRange); + m_overallMaxEnd = newRange.end; + if (outMinStart) *outMinStart = this->front().start; + if (outMaxEnd) *outMaxEnd = m_overallMaxEnd; + return; + } + + auto it = std::lower_bound(this->begin(), this->end(), newRange.start, + [](const Range1D& a, SizeT valueStart) { return a.start < valueStart; }); + size_t pos = static_cast(std::distance(this->begin(), it)); + + auto calc_gap = [](const Range1D& a, const Range1D& b) -> SizeT { + return (b.start > a.end) ? (b.start - a.end) : 0; + }; + + auto calc_threshold = [ratio](const Range1D& a, const Range1D& b) -> SizeT { + SizeT minStart = (a.start < b.start) ? a.start : b.start; + SizeT maxEnd = (a.end > b.end) ? a.end : b.end; + SizeT span = (maxEnd > minStart) ? (maxEnd - minStart) : 0; + return static_cast(static_cast(span) * ratio); + }; + + if (pos >= this->size()) { + Range1D& last = this->back(); + SizeT gap = calc_gap(last, newRange); + SizeT threshold = calc_threshold(last, newRange); + + if (gap <= threshold) { + last.end = std::max(last.end, newRange.end); + m_overallMaxEnd = std::max(m_overallMaxEnd, last.end); + } else { + this->push_back(newRange); + m_overallMaxEnd = std::max(m_overallMaxEnd, newRange.end); + } + + if (outMinStart) *outMinStart = this->front().start; + if (outMaxEnd) *outMaxEnd = m_overallMaxEnd; + return; + } + + bool merged = false; + if (pos > 0) { + Range1D& prev = (*this)[pos - 1]; + SizeT gapPrev = calc_gap(prev, newRange); + SizeT thresholdPrev = calc_threshold(prev, newRange); + + if (gapPrev <= thresholdPrev) { + prev.end = std::max(prev.end, newRange.end); + m_overallMaxEnd = std::max(m_overallMaxEnd, prev.end); + + size_t writeIdx = pos - 1; + while (writeIdx + 1 < this->size()) { + Range1D& cur = (*this)[writeIdx]; + Range1D& nxt = (*this)[writeIdx + 1]; + SizeT gap = calc_gap(cur, nxt); + SizeT threshold = calc_threshold(cur, nxt); + if (gap <= threshold) { + // merge nxt into cur + cur.end = std::max(cur.end, nxt.end); + this->erase(this->begin() + (writeIdx + 1)); + m_overallMaxEnd = std::max(m_overallMaxEnd, cur.end); + } else { + break; + } + } + + merged = true; + } + } + + if (!merged) { + // Try to merge with the current pos interval or insert + Range1D& cur = (*this)[pos]; + SizeT gapCur = calc_gap(newRange, cur); // gap between new and cur + SizeT thresholdCur = calc_threshold(newRange, cur); + + if (gapCur <= thresholdCur) { + cur.start = std::min(cur.start, newRange.start); + cur.end = std::max(cur.end, newRange.end); + m_overallMaxEnd = std::max(m_overallMaxEnd, cur.end); + + size_t writeIdx = pos; + while (writeIdx + 1 < this->size()) { + Range1D& cur2 = (*this)[writeIdx]; + Range1D& nxt = (*this)[writeIdx + 1]; + SizeT gap = calc_gap(cur2, nxt); + SizeT threshold = calc_threshold(cur2, nxt); + if (gap <= threshold) { + cur2.end = std::max(cur2.end, nxt.end); + this->erase(this->begin() + (writeIdx + 1)); + m_overallMaxEnd = std::max(m_overallMaxEnd, cur2.end); + } else { + break; + } + } + + merged = true; + } else { + this->insert(this->begin() + pos, newRange); + m_overallMaxEnd = std::max(m_overallMaxEnd, newRange.end); + merged = true; + } + } + + if (outMinStart) { + *outMinStart = this->front().start; + } + if (outMaxEnd) { + *outMaxEnd = m_overallMaxEnd; + } + } + + SizeT VecRange1D::GetOverallMaxEnd() const { + return m_overallMaxEnd; + } + + SizeT VecRange1D::GetOverallMinStart() const { + if (this->empty()) return 0; + return this->front().start; + } +} // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_Util/Math/VectorTypes.h b/MobileGL/MG_Util/Math/VectorTypes.h index 6ec456a5..5ea2f3c3 100644 --- a/MobileGL/MG_Util/Math/VectorTypes.h +++ b/MobileGL/MG_Util/Math/VectorTypes.h @@ -11,7 +11,6 @@ #include namespace MobileGL { - template struct VecBase { Array data; @@ -247,4 +246,15 @@ namespace MobileGL { return incident - normal * (2.0f * incident.Dot(normal)); } } // namespace MG_Util + + class VecRange1D : public Vector { + public: + void Add(const Range1D& newRange, Double ratio = 0.07, SizeT* outMinStart = nullptr, + SizeT* outMaxEnd = nullptr); + SizeT GetOverallMaxEnd() const; + SizeT GetOverallMinStart() const; + + private: + SizeT m_overallMaxEnd; + }; } // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp index 534160a4..09246fd9 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp @@ -227,13 +227,12 @@ namespace MobileGL { return allSpirv; } - bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector& inputBinary, Vector& outputBinary) { + bool ShaderCompiler::SanitizeAndOptimizeBinary(const Vector& inputBinary, + Vector& outputBinary) { using namespace spvtools; Optimizer optimizer(SPV_ENV_UNIVERSAL_1_5); - optimizer - .RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass()) - ; + optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass()); return optimizer.Run(inputBinary.data(), inputBinary.size(), &outputBinary); } diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.h b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.h index 497832ee..2908a283 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.h +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.h @@ -20,7 +20,8 @@ namespace MobileGL { static Result> CompileShader(const ShaderAttrib& attrib); static Result> LinkProgram(const ProgramAttrib& attrib); static Result>> GetSpirvBinaryFromProgram(const ProgramBinaryAttrib& attrib); - static bool SanitizeAndOptimizeBinary(const Vector& inputBinary, Vector& outputBinary); + static bool SanitizeAndOptimizeBinary(const Vector& inputBinary, + Vector& outputBinary); static Result DecompileShader(SpvcSession& session); }; } // namespace ShaderTranspiler diff --git a/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp b/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp index 89169c94..11ef6188 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp @@ -1,4 +1,4 @@ -// MobileGL - MobileGL/MG_Util/ShaderTranspiler/FloatEqualsZeroEliminationPass.cpp +// MobileGL - MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.cpp // Copyright (c) 2025-2026 MobileGL-Dev // Licensed under the GNU Lesser General Public License v3.0: // https://www.gnu.org/licenses/gpl-3.0.txt @@ -39,7 +39,7 @@ namespace MobileGL { // 3. iterate all function -> basic block -> insn for (auto& func : *get_module()) { for (auto& bb : func) { - for (auto itInst = bb.begin(); itInst != bb.end(); ) { + for (auto itInst = bb.begin(); itInst != bb.end();) { auto& inst = *itInst; bool shouldSkip = true; @@ -48,14 +48,14 @@ namespace MobileGL { // `OpFOrdNotEqual` or `OpFUnordNotEqual`, // simply skip if irrelevant switch (inst.opcode()) { - case spv::Op::OpFOrdEqual: - case spv::Op::OpFUnordEqual: - case spv::Op::OpFOrdNotEqual: - case spv::Op::OpFUnordNotEqual: - shouldSkip = false; - break; - default: - break; + case spv::Op::OpFOrdEqual: + case spv::Op::OpFUnordEqual: + case spv::Op::OpFOrdNotEqual: + case spv::Op::OpFUnordNotEqual: + shouldSkip = false; + break; + default: + break; } if (shouldSkip) { @@ -96,18 +96,13 @@ namespace MobileGL { // 2. Create constant ID for `Epsilon` const analysis::Constant* eps_const = const_mgr->GetConstant( - type_mgr->GetType(float_type_id), - {*(reinterpret_cast(&K_EPSILON))} - ); + type_mgr->GetType(float_type_id), {*(reinterpret_cast(&K_EPSILON))}); uint32_t eps_id = const_mgr->GetDefiningInstruction(eps_const)->result_id(); // 3. Build Abs(x) inst // OpExtInst %float_type %glsl_import Abs %x InstructionBuilder builder( - context(), - &inst, - IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping - ); + context(), &inst, IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); std::vector abs_operands; abs_operands.push_back({SPV_OPERAND_TYPE_ID, {glsl_std_450_id}}); @@ -117,12 +112,7 @@ namespace MobileGL { // In GLSL.std.450, `FAbs`'s OpCode == 4 // Ref: https://registry.khronos.org/SPIR-V/specs/1.0/GLSL.std.450.html Instruction* abs_inst = builder.AddInstruction(MakeUnique( - context(), - spv::Op::OpExtInst, - float_type_id, - context()->TakeNextId(), - abs_operands - )); + context(), spv::Op::OpExtInst, float_type_id, context()->TakeNextId(), abs_operands)); // 4. build Abs(x) < Epsilon // OpFOrdLessThan %bool_type %abs_val %eps @@ -130,14 +120,11 @@ namespace MobileGL { less_operands.push_back({SPV_OPERAND_TYPE_ID, {abs_inst->result_id()}}); less_operands.push_back({SPV_OPERAND_TYPE_ID, {eps_id}}); - bool isEqualOp = (inst.opcode() == spv::Op::OpFOrdEqual || inst.opcode() == spv::Op::OpFUnordEqual); + bool isEqualOp = + (inst.opcode() == spv::Op::OpFOrdEqual || inst.opcode() == spv::Op::OpFUnordEqual); Instruction* less_than_inst = builder.AddInstruction(MakeUnique( - context(), - isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual, - bool_type_id, - context()->TakeNextId(), - less_operands - )); + context(), isEqualOp ? spv::Op::OpFOrdLessThan : spv::Op::OpFOrdGreaterThanEqual, + bool_type_id, context()->TakeNextId(), less_operands)); // 5. Replaces all uses of old insn with new one context()->ReplaceAllUsesWith(inst.result_id(), less_than_inst->result_id()); @@ -161,5 +148,5 @@ namespace MobileGL { return spvtools::Optimizer::PassToken(MakeUnique()); } } // namespace ShaderTranspiler - } -} \ No newline at end of file + } // namespace MG_Util +} // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.h b/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.h index 57d8c56a..8e6ab37d 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.h +++ b/MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.h @@ -1,4 +1,4 @@ -// MobileGL - MobileGL/MG_Util/ShaderTranspiler/FloatEqualsZeroEliminationPass.h +// MobileGL - MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/EliminateFloatEqualsZeroPass.h // Copyright (c) 2025-2026 MobileGL-Dev // Licensed under the GNU Lesser General Public License v3.0: // https://www.gnu.org/licenses/gpl-3.0.txt @@ -15,16 +15,16 @@ namespace MobileGL { namespace MG_Util { namespace ShaderTranspiler { - class EliminateFloatEqualsZeroPass: public spvtools::opt::Pass { + class EliminateFloatEqualsZeroPass : public spvtools::opt::Pass { public: const char* name() const override { return "float-equals-zero-elimination"; } Status Process() override; static spvtools::Optimizer::PassToken CreateEliminateFloatEqualsZeroPass(); + private: const float K_EPSILON = 0.0001f; }; } // namespace ShaderTranspiler } // namespace MG_Util } // namespace MobileGL - diff --git a/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp b/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp index 7439e9ed..6092914f 100644 --- a/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp +++ b/MobileGL/MG_Util/Texture/PixelStoreProcessor.cpp @@ -108,8 +108,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor { const Int copyHeight = height; const Int copyDepth = depth; - MGLOG_D("%s: start at: (%d, %d, %d), copy size: (%d, %d, %d), i/o row stride: (%d, %dx%d)", __func__, - startX, startY, startZ, copyWidth, copyHeight, copyDepth, inputRowStride, width, pixelSize); + MGLOG_D("%s: start at: (%d, %d, %d), copy size: (%d, %d, %d), i/o row stride: (%d, %dx%d)", __func__, startX, + startY, startZ, copyWidth, copyHeight, copyDepth, inputRowStride, width, pixelSize); if (copyWidth <= 0 || copyHeight <= 0 || copyDepth <= 0) { outSize = 0; @@ -152,14 +152,14 @@ namespace MobileGL::MG_Util::PixelStoreProcessor { if (textureInputFormat == TextureInputFormat::BGRA && targetInternalFormat == TextureInternalFormat::RGBA8) { MGLOG_D("%s: Swizzle (BGRA)", __func__); -// MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst)); + // MGLOG_D("%s: pixel0 before = %x", __func__, *((Uint32*)layerDst)); ProcessColorSwizzle(layerDst, static_cast(copyWidth), {TextureSwizzleParam::Green, TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha, TextureSwizzleParam::Red}); -// MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst)); + // MGLOG_D("%s: pixel0 after = %x", __func__, *((Uint32*)layerDst)); } -// else -// MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst)); + // else + // MGLOG_D("%s: pixel0 = %x", __func__, *((Uint32*)layerDst)); layerSrc += inputRowStride; layerDst += outputRowStride; diff --git a/MobileGL/MG_Util/Texture/PixelStoreProcessor.h b/MobileGL/MG_Util/Texture/PixelStoreProcessor.h index 8821d40c..d5fcbca2 100644 --- a/MobileGL/MG_Util/Texture/PixelStoreProcessor.h +++ b/MobileGL/MG_Util/Texture/PixelStoreProcessor.h @@ -14,7 +14,8 @@ namespace MobileGL::MG_Util::PixelStoreProcessor { void* ProcessTexturePixelsDataUnpack(const void* inputPixels, const PixelStoreParameters& params, - TextureInternalFormat targetInternalFormat, TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType, + TextureInternalFormat targetInternalFormat, + TextureInputFormat textureInputFormat, TexturePixelDataType inputDataType, IntVec3 dimension, Bool isBitmap, SizeT& outSize); void* ProcessTexturePixelsDataPack(const void* inputPixels, const PixelStoreParameters& params, SizeT pixelSize, IntVec3 dimension, Bool isBitmap, SizeT& outSize); diff --git a/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp b/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp index 94edc4d5..4d8eea60 100644 --- a/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp +++ b/MobileGL/MG_Util/Texture/TextureFormatProcessor.cpp @@ -10,335 +10,338 @@ #include "MG_Util/Converters/GLToStr/GLEnumConverter.h" namespace MobileGL::MG_Util::TextureFormatProcessor { - void NormalizePixelFormat(GLenum internalFormat, Flags options, GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType) { + void NormalizePixelFormat(GLenum internalFormat, Flags options, + GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType) { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif // internal format if (outInternalFormat) { switch (internalFormat) { - case GL_DEPTH_COMPONENT32: - *outInternalFormat = GL_DEPTH_COMPONENT; + case GL_DEPTH_COMPONENT32: + *outInternalFormat = GL_DEPTH_COMPONENT; + break; + case GL_RGBA16: + if (options & PixelFormatNormalizeOptionBit::NoNorm16) { + *outInternalFormat = GL_RGBA32F; break; - case GL_RGBA16: - if (options & PixelFormatNormalizeOptionBit::NoNorm16) { - *outInternalFormat = GL_RGBA32F; - break; - } - case GL_RGB16: - if (options & PixelFormatNormalizeOptionBit::NoNorm16) { - *outInternalFormat = GL_RGB32F; - break; - } - case GL_RG16: - if (options & PixelFormatNormalizeOptionBit::NoNorm16) { - *outInternalFormat = GL_RG32F; - break; - } - case GL_R16: - if (options & PixelFormatNormalizeOptionBit::NoNorm16) { - *outInternalFormat = GL_R32F; - break; - } - default: - *outInternalFormat = internalFormat; + } + case GL_RGB16: + if (options & PixelFormatNormalizeOptionBit::NoNorm16) { + *outInternalFormat = GL_RGB32F; break; + } + case GL_RG16: + if (options & PixelFormatNormalizeOptionBit::NoNorm16) { + *outInternalFormat = GL_RG32F; + break; + } + case GL_R16: + if (options & PixelFormatNormalizeOptionBit::NoNorm16) { + *outInternalFormat = GL_R32F; + break; + } + default: + *outInternalFormat = internalFormat; + break; } } // format if (outFormat) { switch (internalFormat) { - // Color Unsigned Normalized - case GL_RGBA: - case GL_RGBA16: - case GL_RGBA8: + // Color Unsigned Normalized + case GL_RGBA: + case GL_RGBA16: + case GL_RGBA8: + *outFormat = GL_RGBA; + break; + + case GL_RGB: + case GL_RGB16: + case GL_RGB8: + *outFormat = GL_RGB; + break; + + case GL_RG: + case GL_RG16: + case GL_RG8: + *outFormat = GL_RG; + break; + + case GL_RED: + case GL_R16: + case GL_R8: + *outFormat = GL_RED; + break; + + // Color Signed Normalized + case GL_RGBA_SNORM: + case GL_RGBA16_SNORM: + case GL_RGBA8_SNORM: + *outFormat = GL_RGBA; + break; + + case GL_RGB_SNORM: + case GL_RGB16_SNORM: + case GL_RGB8_SNORM: + *outFormat = GL_RGB; + break; + + case GL_RG_SNORM: + case GL_RG16_SNORM: + case GL_RG8_SNORM: + *outFormat = GL_RG; + break; + + case GL_RED_SNORM: + case GL_R16_SNORM: + case GL_R8_SNORM: + *outFormat = GL_RED; + break; + + // Color Integer + case GL_RGBA32UI: + case GL_RGBA16UI: + case GL_RGBA8UI: + case GL_RGBA32I: + case GL_RGBA16I: + case GL_RGBA8I: + *outFormat = GL_RGBA_INTEGER; + break; + case GL_RGB32UI: + case GL_RGB16UI: + case GL_RGB8UI: + case GL_RGB32I: + case GL_RGB16I: + case GL_RGB8I: + *outFormat = GL_RGB_INTEGER; + break; + case GL_RG32UI: + case GL_RG16UI: + case GL_RG8UI: + case GL_RG32I: + case GL_RG16I: + case GL_RG8I: + *outFormat = GL_RG_INTEGER; + break; + case GL_R32UI: + case GL_R16UI: + case GL_R8UI: + case GL_R32I: + case GL_R16I: + case GL_R8I: + *outFormat = GL_RED_INTEGER; + break; + + // Color Float + case GL_RGBA32F: + case GL_RGBA16F: + *outFormat = GL_RGBA; + break; + case GL_RGB32F: + case GL_RGB16F: + *outFormat = GL_RGB; + break; + case GL_RG32F: + case GL_RG16F: + *outFormat = GL_RG; + break; + case GL_R32F: + case GL_R16F: + *outFormat = GL_RED; + break; + + // Color sRGB + case GL_SRGB: + case GL_SRGB8: + *outFormat = GL_RGB; + break; + + // Color sized other + case GL_RGB9_E5: + case GL_R11F_G11F_B10F: + *outFormat = GL_RGB; + break; + case GL_RGB10_A2: + case GL_RGB5_A1: + *outFormat = GL_RGBA; + break; + + // Depth + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + case GL_DEPTH_COMPONENT32F: + case GL_DEPTH_COMPONENT: + *outFormat = GL_DEPTH_COMPONENT; + break; + + // Depth Stencil + case GL_DEPTH32F_STENCIL8: + case GL_DEPTH_STENCIL: + *outFormat = GL_DEPTH_STENCIL; + break; + + default: + MGLOG_E("NormalizePixelFormat: outFormat: unhandled internalFormat: %s", + MG_Util::ConvertGLEnumToString(internalFormat).c_str()); + // Fallback handling for other formats + // Try to infer format from internal format name + if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGBA") != nullptr) { *outFormat = GL_RGBA; - break; - - case GL_RGB: - case GL_RGB16: - case GL_RGB8: + } else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGB") != nullptr) { *outFormat = GL_RGB; - break; - - case GL_RG: - case GL_RG16: - case GL_RG8: + } else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RG") != nullptr) { *outFormat = GL_RG; - break; - - case GL_RED: - case GL_R16: - case GL_R8: + } else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RED") != nullptr) { *outFormat = GL_RED; - break; - - // Color Signed Normalized - case GL_RGBA_SNORM: - case GL_RGBA16_SNORM: - case GL_RGBA8_SNORM: - *outFormat = GL_RGBA; - break; - - case GL_RGB_SNORM: - case GL_RGB16_SNORM: - case GL_RGB8_SNORM: - *outFormat = GL_RGB; - break; - - case GL_RG_SNORM: - case GL_RG16_SNORM: - case GL_RG8_SNORM: - *outFormat = GL_RG; - break; - - case GL_RED_SNORM: - case GL_R16_SNORM: - case GL_R8_SNORM: - *outFormat = GL_RED; - break; - - // Color Integer - case GL_RGBA32UI: - case GL_RGBA16UI: - case GL_RGBA8UI: - case GL_RGBA32I: - case GL_RGBA16I: - case GL_RGBA8I: - *outFormat = GL_RGBA_INTEGER; - break; - case GL_RGB32UI: - case GL_RGB16UI: - case GL_RGB8UI: - case GL_RGB32I: - case GL_RGB16I: - case GL_RGB8I: - *outFormat = GL_RGB_INTEGER; - break; - case GL_RG32UI: - case GL_RG16UI: - case GL_RG8UI: - case GL_RG32I: - case GL_RG16I: - case GL_RG8I: - *outFormat = GL_RG_INTEGER; - break; - case GL_R32UI: - case GL_R16UI: - case GL_R8UI: - case GL_R32I: - case GL_R16I: - case GL_R8I: - *outFormat = GL_RED_INTEGER; - break; - - // Color Float - case GL_RGBA32F: - case GL_RGBA16F: - *outFormat = GL_RGBA; - break; - case GL_RGB32F: - case GL_RGB16F: - *outFormat = GL_RGB; - break; - case GL_RG32F: - case GL_RG16F: - *outFormat = GL_RG; - break; - case GL_R32F: - case GL_R16F: - *outFormat = GL_RED; - break; - - // Color sRGB - case GL_SRGB: - case GL_SRGB8: - *outFormat = GL_RGB; - break; - - // Color sized other - case GL_RGB9_E5: - case GL_R11F_G11F_B10F: - *outFormat = GL_RGB; - break; - case GL_RGB10_A2: - case GL_RGB5_A1: - *outFormat = GL_RGBA; - break; - - // Depth - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - case GL_DEPTH_COMPONENT32F: - case GL_DEPTH_COMPONENT: - *outFormat = GL_DEPTH_COMPONENT; - break; - - // Depth Stencil - case GL_DEPTH32F_STENCIL8: - case GL_DEPTH_STENCIL: - *outFormat = GL_DEPTH_STENCIL; - break; - - default: - MGLOG_E("NormalizePixelFormat: outFormat: unhandled internalFormat: %s", MG_Util::ConvertGLEnumToString(internalFormat).c_str()); - // Fallback handling for other formats - // Try to infer format from internal format name - if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGBA") != nullptr) { - *outFormat = GL_RGBA; - } else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RGB") != nullptr) { - *outFormat = GL_RGB; - } else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RG") != nullptr) { - *outFormat = GL_RG; - } else if (strstr(MG_Util::ConvertGLEnumToString(internalFormat).c_str(), "RED") != nullptr) { - *outFormat = GL_RED; - } else { - *outFormat = GL_RGBA; // Ultimate fallback - } - break; + } else { + *outFormat = GL_RGBA; // Ultimate fallback + } + break; } } // type if (outType) { switch (internalFormat) { - // Color Unsigned Normalized - case GL_RGBA16: - case GL_RGB16: - case GL_RG16: - case GL_R16: - if (options & PixelFormatNormalizeOptionBit::NoNorm16) { - // converted to GL_RGBA32F - *outType = GL_FLOAT; - break; - } else { - *outType = GL_UNSIGNED_SHORT; - break; - } - case GL_RGBA8: - case GL_RGB8: - case GL_RG8: - case GL_R8: - *outType = GL_UNSIGNED_BYTE; - break; - - // Color Signed Normalized - case GL_RGBA16_SNORM: - case GL_RGB16_SNORM: - case GL_RG16_SNORM: - case GL_R16_SNORM: - *outType = GL_SHORT; - break; - case GL_RGBA8_SNORM: - case GL_RGB8_SNORM: - case GL_RG8_SNORM: - case GL_R8_SNORM: - *outType = GL_BYTE; - break; - - // Color Unsigned Integer - case GL_RGBA32UI: - case GL_RGB32UI: - case GL_RG32UI: - case GL_R32UI: - *outType = GL_UNSIGNED_INT; - break; - case GL_RGBA16UI: - case GL_RGB16UI: - case GL_RG16UI: - case GL_R16UI: - *outType = GL_UNSIGNED_SHORT; - break; - case GL_RGBA8UI: - case GL_RGB8UI: - case GL_RG8UI: - case GL_R8UI: - *outType = GL_UNSIGNED_BYTE; - break; - - // Color Integer - case GL_RGBA32I: - case GL_RGB32I: - case GL_RG32I: - case GL_R32I: - *outType = GL_INT; - break; - case GL_RGBA16I: - case GL_RGB16I: - case GL_RG16I: - case GL_R16I: - *outType = GL_SHORT; - break; - case GL_RGBA8I: - case GL_RGB8I: - case GL_RG8I: - case GL_R8I: - *outType = GL_BYTE; - break; - - // Color Float - case GL_RGBA32F: - case GL_RGB32F: - case GL_RG32F: - case GL_R32F: + // Color Unsigned Normalized + case GL_RGBA16: + case GL_RGB16: + case GL_RG16: + case GL_R16: + if (options & PixelFormatNormalizeOptionBit::NoNorm16) { + // converted to GL_RGBA32F *outType = GL_FLOAT; break; - case GL_RGBA16F: - case GL_RGB16F: - case GL_RG16F: - case GL_R16F: - *outType = GL_HALF_FLOAT; - break; - - // Color sRGB - case GL_SRGB8: - *outType = GL_UNSIGNED_BYTE; - break; - - // Color sized other - case GL_RGB9_E5: - *outType = GL_UNSIGNED_INT_5_9_9_9_REV; - break; - case GL_R11F_G11F_B10F: - *outType = GL_UNSIGNED_INT_10F_11F_11F_REV; - break; - case GL_RGB10_A2: - *outType = GL_UNSIGNED_INT_2_10_10_10_REV; - break; - case GL_RGB5_A1: - *outType = GL_UNSIGNED_SHORT_5_5_5_1; - break; - - // Depth - case GL_DEPTH_COMPONENT16: + } else { *outType = GL_UNSIGNED_SHORT; break; - case GL_DEPTH_COMPONENT24: - *outType = GL_UNSIGNED_INT; - break; - case GL_DEPTH_COMPONENT32: - *outType = GL_UNSIGNED_INT; - break; - case GL_DEPTH_COMPONENT32F: - *outType = GL_FLOAT; - break; - case GL_DEPTH_COMPONENT: - *outType = GL_UNSIGNED_INT; - break; + } + case GL_RGBA8: + case GL_RGB8: + case GL_RG8: + case GL_R8: + *outType = GL_UNSIGNED_BYTE; + break; - // Depth Stencil - case GL_DEPTH32F_STENCIL8: - case GL_DEPTH_STENCIL: - *outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; - break; + // Color Signed Normalized + case GL_RGBA16_SNORM: + case GL_RGB16_SNORM: + case GL_RG16_SNORM: + case GL_R16_SNORM: + *outType = GL_SHORT; + break; + case GL_RGBA8_SNORM: + case GL_RGB8_SNORM: + case GL_RG8_SNORM: + case GL_R8_SNORM: + *outType = GL_BYTE; + break; - default: - MGLOG_E("NormalizePixelFormat: outType: unhandled internalFormat: %s", MG_Util::ConvertGLEnumToString(internalFormat).c_str()); - // Fallback handling for other formats - *outType = GL_UNSIGNED_BYTE; - break; + // Color Unsigned Integer + case GL_RGBA32UI: + case GL_RGB32UI: + case GL_RG32UI: + case GL_R32UI: + *outType = GL_UNSIGNED_INT; + break; + case GL_RGBA16UI: + case GL_RGB16UI: + case GL_RG16UI: + case GL_R16UI: + *outType = GL_UNSIGNED_SHORT; + break; + case GL_RGBA8UI: + case GL_RGB8UI: + case GL_RG8UI: + case GL_R8UI: + *outType = GL_UNSIGNED_BYTE; + break; + + // Color Integer + case GL_RGBA32I: + case GL_RGB32I: + case GL_RG32I: + case GL_R32I: + *outType = GL_INT; + break; + case GL_RGBA16I: + case GL_RGB16I: + case GL_RG16I: + case GL_R16I: + *outType = GL_SHORT; + break; + case GL_RGBA8I: + case GL_RGB8I: + case GL_RG8I: + case GL_R8I: + *outType = GL_BYTE; + break; + + // Color Float + case GL_RGBA32F: + case GL_RGB32F: + case GL_RG32F: + case GL_R32F: + *outType = GL_FLOAT; + break; + case GL_RGBA16F: + case GL_RGB16F: + case GL_RG16F: + case GL_R16F: + *outType = GL_HALF_FLOAT; + break; + + // Color sRGB + case GL_SRGB8: + *outType = GL_UNSIGNED_BYTE; + break; + + // Color sized other + case GL_RGB9_E5: + *outType = GL_UNSIGNED_INT_5_9_9_9_REV; + break; + case GL_R11F_G11F_B10F: + *outType = GL_UNSIGNED_INT_10F_11F_11F_REV; + break; + case GL_RGB10_A2: + *outType = GL_UNSIGNED_INT_2_10_10_10_REV; + break; + case GL_RGB5_A1: + *outType = GL_UNSIGNED_SHORT_5_5_5_1; + break; + + // Depth + case GL_DEPTH_COMPONENT16: + *outType = GL_UNSIGNED_SHORT; + break; + case GL_DEPTH_COMPONENT24: + *outType = GL_UNSIGNED_INT; + break; + case GL_DEPTH_COMPONENT32: + *outType = GL_UNSIGNED_INT; + break; + case GL_DEPTH_COMPONENT32F: + *outType = GL_FLOAT; + break; + case GL_DEPTH_COMPONENT: + *outType = GL_UNSIGNED_INT; + break; + + // Depth Stencil + case GL_DEPTH32F_STENCIL8: + case GL_DEPTH_STENCIL: + *outType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + break; + + default: + MGLOG_E("NormalizePixelFormat: outType: unhandled internalFormat: %s", + MG_Util::ConvertGLEnumToString(internalFormat).c_str()); + // Fallback handling for other formats + *outType = GL_UNSIGNED_BYTE; + break; } } } diff --git a/MobileGL/MG_Util/Texture/TextureFormatProcessor.h b/MobileGL/MG_Util/Texture/TextureFormatProcessor.h index fbc70c88..6027fd46 100644 --- a/MobileGL/MG_Util/Texture/TextureFormatProcessor.h +++ b/MobileGL/MG_Util/Texture/TextureFormatProcessor.h @@ -14,5 +14,6 @@ namespace MobileGL::MG_Util::TextureFormatProcessor { NoNorm16 = 1 << 0, None = 0, }; - void NormalizePixelFormat(GLenum internalFormat, Flags options, GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType); + void NormalizePixelFormat(GLenum internalFormat, Flags options, + GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType); } // namespace MobileGL::MG_Util::TextureFormatProcessor \ No newline at end of file