From 9cca0a8753647726a5c14c05965e9f3b434ea41a Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 26 Jun 2026 10:44:55 +0800 Subject: [PATCH] [Feature] (MG_Backend): print format capability tables --- MobileGL/MG_Backend/BackendObject.cpp | 127 ++++++++++++++++++ MobileGL/MG_Backend/BackendObject.h | 1 + .../DirectGLES/BackendObject_DirectGLES.cpp | 1 + .../BackendObject_DirectVulkan.cpp | 1 + 4 files changed, 130 insertions(+) diff --git a/MobileGL/MG_Backend/BackendObject.cpp b/MobileGL/MG_Backend/BackendObject.cpp index b46dc5b7..32e72ae2 100644 --- a/MobileGL/MG_Backend/BackendObject.cpp +++ b/MobileGL/MG_Backend/BackendObject.cpp @@ -7,9 +7,31 @@ // End of Source File Header #include "BackendObject.h" +#include "MG_Util/Converters/MGToStr/TextureEnumConverter.h" +#include +#include +#include +#include namespace MobileGL::MG_Backend { namespace { + constexpr FormatCapability kPrintedFormatCapabilities[] = { + FormatCapability::Creatable, + FormatCapability::Sampled, + FormatCapability::LinearFilter, + FormatCapability::GenerateMipmap, + FormatCapability::TextureGather, + FormatCapability::TextureShadow, + FormatCapability::FramebufferRenderable, + FormatCapability::FramebufferLayered, + FormatCapability::MultisampleTexture, + FormatCapability::MultisampleRenderbuffer, + FormatCapability::ColorAttachment, + FormatCapability::DepthAttachment, + FormatCapability::StencilAttachment, + FormatCapability::TextureBuffer, + }; + Bool IsReleaseCurrentRequest(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { return dpy == EGL_NO_DISPLAY && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT; } @@ -17,6 +39,94 @@ namespace MobileGL::MG_Backend { std::thread::id CurrentThreadKey() { return std::this_thread::get_id(); } + + const char* ConvertFormatCapabilityToString(FormatCapability capability) { + switch (capability) { + case FormatCapability::Creatable: + return "Creatable"; + case FormatCapability::Sampled: + return "Sampled"; + case FormatCapability::LinearFilter: + return "LinearFilter"; + case FormatCapability::GenerateMipmap: + return "GenerateMipmap"; + case FormatCapability::TextureGather: + return "TextureGather"; + case FormatCapability::TextureShadow: + return "TextureShadow"; + case FormatCapability::FramebufferRenderable: + return "FramebufferRenderable"; + case FormatCapability::FramebufferLayered: + return "FramebufferLayered"; + case FormatCapability::MultisampleTexture: + return "MultisampleTexture"; + case FormatCapability::MultisampleRenderbuffer: + return "MultisampleRenderbuffer"; + case FormatCapability::ColorAttachment: + return "ColorAttachment"; + case FormatCapability::DepthAttachment: + return "DepthAttachment"; + case FormatCapability::StencilAttachment: + return "StencilAttachment"; + case FormatCapability::TextureBuffer: + return "TextureBuffer"; + } + return "Unknown"; + } + + const char* GetFormatCapabilitySupportString(const FormatCapabilityCache& cache, + SizeT targetIndex, + SizeT formatIndex, + FormatCapability capability) { + if (HasFormatCapability(cache.FullCaps[targetIndex][formatIndex], capability)) return "Full"; + if (HasFormatCapability(cache.CaveatCaps[targetIndex][formatIndex], capability)) return "Caveat"; + return "None"; + } + + SizeT GetPrintedFormatNameWidth() { + SizeT width = 0; + for (SizeT formatIndex = 0; formatIndex < kFormatCapabilityFormatCount; ++formatIndex) { + const auto format = static_cast(formatIndex); + width = std::max(width, MG_Util::ConvertTextureInternalFormatToString(format).size()); + } + return width; + } + + SizeT GetCapabilityColumnWidth(FormatCapability capability) { + SizeT width = std::strlen(ConvertFormatCapabilityToString(capability)); + width = std::max(width, std::strlen("Caveat")); + return width; + } + + String GetFormatCapabilityTargetName(SizeT targetIndex) { + if (targetIndex == kFormatCapabilityRenderbufferTargetIndex) return "Renderbuffer"; + return MG_Util::ConvertTextureTargetToString(static_cast(targetIndex)); + } + + String BuildFormatCapabilityHeader(SizeT formatNameWidth) { + std::ostringstream line; + line << std::left << std::setw(static_cast(formatNameWidth)) << ""; + for (FormatCapability capability : kPrintedFormatCapabilities) { + line << " | " << std::left << std::setw(static_cast(GetCapabilityColumnWidth(capability))) + << ConvertFormatCapabilityToString(capability); + } + return line.str(); + } + + String BuildFormatCapabilityRow(const FormatCapabilityCache& cache, + SizeT targetIndex, + SizeT formatIndex, + SizeT formatNameWidth) { + const auto format = static_cast(formatIndex); + std::ostringstream line; + line << std::left << std::setw(static_cast(formatNameWidth)) + << MG_Util::ConvertTextureInternalFormatToString(format); + for (FormatCapability capability : kPrintedFormatCapabilities) { + line << " | " << std::left << std::setw(static_cast(GetCapabilityColumnWidth(capability))) + << GetFormatCapabilitySupportString(cache, targetIndex, formatIndex, capability); + } + return line.str(); + } } // namespace void FormatCapabilityCache::Clear() { @@ -49,6 +159,23 @@ namespace MobileGL::MG_Backend { return kFormatCapabilityRenderbufferTargetIndex; } + void PrintFormatCapabilities(const FormatCapabilityCache& cache) { + const SizeT formatNameWidth = GetPrintedFormatNameWidth(); + + MGLOG_I("Backend format capabilities:"); + for (SizeT targetIndex = 0; targetIndex < kFormatCapabilityTargetCount; ++targetIndex) { + MGLOG_I(""); + const String targetName = GetFormatCapabilityTargetName(targetIndex); + MGLOG_I("- %s", targetName.c_str()); + const String header = BuildFormatCapabilityHeader(formatNameWidth); + MGLOG_I("%s", header.c_str()); + for (SizeT formatIndex = 0; formatIndex < kFormatCapabilityFormatCount; ++formatIndex) { + const String row = BuildFormatCapabilityRow(cache, targetIndex, formatIndex, formatNameWidth); + MGLOG_I("%s", row.c_str()); + } + } + } + Bool BackendObject::InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) { const std::lock_guard lock(m_eglStateMutex); if (dpy == EGL_NO_DISPLAY) { diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index ed1d5f50..adf863fd 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -70,6 +70,7 @@ namespace MobileGL { Bool HasFormatCapability(FormatCapabilityFlags caps, FormatCapability capability); SizeT GetFormatCapabilityTargetIndex(TextureTarget target); SizeT GetRenderbufferFormatCapabilityTargetIndex(); + void PrintFormatCapabilities(const FormatCapabilityCache& cache); struct GLFunctionsTable { void (*DrawArrays)(GLenum mode, GLint first, GLsizei count); diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index 4eb63fe4..dda4500e 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -431,6 +431,7 @@ namespace MobileGL::MG_Backend::DirectGLES { DirectGLES::SetGLESCapabilities(m_GLESCapabilities); UpdateDynamicBackendParameters(); ProbeGLESFormatCapabilities(m_GLESFunctions, MutableFormatCapabilities(), m_dynamicParameters); + PrintFormatCapabilities(GetFormatCapabilities()); return true; } diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp index d863a510..e9266d5e 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp @@ -330,6 +330,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { UpdateDynamicBackendParameters(); UpdateAdvertisedExtensions(); FillVulkanFormatCapabilities(physicalDevice.handle, m_dynamicParameters, MutableFormatCapabilities()); + PrintFormatCapabilities(GetFormatCapabilities()); return true; }