mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (MG_Backend, android-plugin): show format capability tables in POST
This commit is contained in:
@@ -15,23 +15,6 @@
|
||||
|
||||
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) {
|
||||
(void)dpy;
|
||||
return draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT;
|
||||
@@ -41,40 +24,6 @@ namespace MobileGL::MG_Backend {
|
||||
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,
|
||||
@@ -94,22 +43,17 @@ namespace MobileGL::MG_Backend {
|
||||
}
|
||||
|
||||
SizeT GetCapabilityColumnWidth(FormatCapability capability) {
|
||||
SizeT width = std::strlen(ConvertFormatCapabilityToString(capability));
|
||||
SizeT width = std::strlen(GetFormatCapabilityName(capability));
|
||||
width = std::max<SizeT>(width, std::strlen("Caveat"));
|
||||
return width;
|
||||
}
|
||||
|
||||
String GetFormatCapabilityTargetName(SizeT targetIndex) {
|
||||
if (targetIndex == kFormatCapabilityRenderbufferTargetIndex) return "Renderbuffer";
|
||||
return MG_Util::ConvertTextureTargetToString(static_cast<TextureTarget>(targetIndex));
|
||||
}
|
||||
|
||||
String BuildFormatCapabilityHeader(SizeT formatNameWidth) {
|
||||
std::ostringstream line;
|
||||
line << std::left << std::setw(static_cast<Int>(formatNameWidth)) << "";
|
||||
for (FormatCapability capability : kPrintedFormatCapabilities) {
|
||||
for (FormatCapability capability : kReportedFormatCapabilities) {
|
||||
line << " | " << std::left << std::setw(static_cast<Int>(GetCapabilityColumnWidth(capability)))
|
||||
<< ConvertFormatCapabilityToString(capability);
|
||||
<< GetFormatCapabilityName(capability);
|
||||
}
|
||||
return line.str();
|
||||
}
|
||||
@@ -122,7 +66,7 @@ namespace MobileGL::MG_Backend {
|
||||
std::ostringstream line;
|
||||
line << std::left << std::setw(static_cast<Int>(formatNameWidth))
|
||||
<< MG_Util::ConvertTextureInternalFormatToString(format);
|
||||
for (FormatCapability capability : kPrintedFormatCapabilities) {
|
||||
for (FormatCapability capability : kReportedFormatCapabilities) {
|
||||
line << " | " << std::left << std::setw(static_cast<Int>(GetCapabilityColumnWidth(capability)))
|
||||
<< GetFormatCapabilitySupportString(cache, targetIndex, formatIndex, capability);
|
||||
}
|
||||
@@ -160,6 +104,50 @@ namespace MobileGL::MG_Backend {
|
||||
return kFormatCapabilityRenderbufferTargetIndex;
|
||||
}
|
||||
|
||||
const char* GetFormatCapabilityName(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";
|
||||
}
|
||||
|
||||
String GetFormatCapabilityTargetName(SizeT targetIndex) {
|
||||
if (targetIndex == kFormatCapabilityRenderbufferTargetIndex) {
|
||||
return "Renderbuffer";
|
||||
}
|
||||
if (targetIndex >= kFormatCapabilityTextureTargetCount) {
|
||||
return "Unknown";
|
||||
}
|
||||
return MG_Util::ConvertTextureTargetToString(static_cast<TextureTarget>(targetIndex));
|
||||
}
|
||||
|
||||
void PrintFormatCapabilities(const FormatCapabilityCache& cache) {
|
||||
const SizeT formatNameWidth = GetPrintedFormatNameWidth();
|
||||
|
||||
|
||||
@@ -47,6 +47,23 @@ namespace MobileGL {
|
||||
|
||||
using FormatCapabilityFlags = Flags<FormatCapability>;
|
||||
|
||||
inline constexpr Array<FormatCapability, 14> kReportedFormatCapabilities = {
|
||||
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,
|
||||
};
|
||||
|
||||
inline constexpr SizeT kFormatCapabilityTextureTargetCount =
|
||||
static_cast<SizeT>(TextureTarget::TextureTargetCount);
|
||||
inline constexpr SizeT kFormatCapabilityRenderbufferTargetIndex = kFormatCapabilityTextureTargetCount;
|
||||
@@ -70,6 +87,8 @@ namespace MobileGL {
|
||||
Bool HasFormatCapability(FormatCapabilityFlags caps, FormatCapability capability);
|
||||
SizeT GetFormatCapabilityTargetIndex(TextureTarget target);
|
||||
SizeT GetRenderbufferFormatCapabilityTargetIndex();
|
||||
const char* GetFormatCapabilityName(FormatCapability capability);
|
||||
String GetFormatCapabilityTargetName(SizeT targetIndex);
|
||||
void PrintFormatCapabilities(const FormatCapabilityCache& cache);
|
||||
|
||||
// Opaque backend fence-sync handle, created by GLFunctionsTable::FenceSync
|
||||
|
||||
@@ -150,23 +150,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
String Reason;
|
||||
};
|
||||
|
||||
constexpr FormatCapability kGLESProbeCapabilities[] = {
|
||||
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,
|
||||
};
|
||||
|
||||
GLESProbeFormatInfo BuildNativeProbeFormatInfo(GLenum requestedInternalFormat) {
|
||||
GLESProbeFormatInfo info;
|
||||
info.InternalFormat = requestedInternalFormat;
|
||||
@@ -176,9 +159,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return info;
|
||||
}
|
||||
|
||||
Flags<PixelFormatNormalizeOptionBit> GetForcedPixelFormatNormalizeOptions() {
|
||||
Flags<PixelFormatNormalizeOptionBit> GetForcedPixelFormatNormalizeOptions(
|
||||
const MG_External::GLESCapabilities& capabilities) {
|
||||
Flags<PixelFormatNormalizeOptionBit> options;
|
||||
if (g_GLESCapabilities.IsAngleRenderer) {
|
||||
if (capabilities.IsAngleRenderer) {
|
||||
options |= PixelFormatNormalizeOptionBit::NoRgb16;
|
||||
options |= PixelFormatNormalizeOptionBit::NoSnorm16;
|
||||
options |= PixelFormatNormalizeOptionBit::NoSnorm8;
|
||||
@@ -186,11 +170,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return options;
|
||||
}
|
||||
|
||||
Flags<PixelFormatNormalizeOptionBit> GetDriverPixelFormatNormalizeOptions() {
|
||||
Flags<PixelFormatNormalizeOptionBit> GetDriverPixelFormatNormalizeOptions(
|
||||
const MG_External::GLESCapabilities& capabilities) {
|
||||
Flags<PixelFormatNormalizeOptionBit> options = PixelFormatNormalizeOptionBit::NoDepthComponent32;
|
||||
options |= PixelFormatNormalizeOptionBit::NoRGBA8Snorm;
|
||||
options |= PixelFormatNormalizeOptionBit::NoRGB16Snorm;
|
||||
if (!g_GLESCapabilities.SupportsNorm16Texture) {
|
||||
if (!capabilities.SupportsNorm16Texture) {
|
||||
options |= PixelFormatNormalizeOptionBit::NoNorm16;
|
||||
}
|
||||
return options;
|
||||
@@ -241,21 +226,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return MG_Util::ConvertGLEnumToString(internalFormat);
|
||||
}
|
||||
|
||||
String GetFormatCapabilityTargetNameForLog(SizeT targetIndex) {
|
||||
if (targetIndex == GetRenderbufferFormatCapabilityTargetIndex()) {
|
||||
return "Renderbuffer";
|
||||
}
|
||||
if (targetIndex < kFormatCapabilityTextureTargetCount) {
|
||||
return MG_Util::ConvertTextureTargetToString(static_cast<TextureTarget>(targetIndex));
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void LogGLESFormatCaveat(TextureInternalFormat logicalFormat,
|
||||
SizeT targetIndex,
|
||||
const GLESProbeFormatInfo& fallbackInfo) {
|
||||
MGLOG_D("Caveat: %s %s not fully supported. Reason: %s. Fallback: %s",
|
||||
GetFormatCapabilityTargetNameForLog(targetIndex).c_str(),
|
||||
GetFormatCapabilityTargetName(targetIndex).c_str(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(logicalFormat).c_str(),
|
||||
fallbackInfo.Reason.c_str(),
|
||||
ConvertFallbackInternalFormatToString(fallbackInfo.InternalFormat).c_str());
|
||||
@@ -306,7 +281,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
SizeT formatIndex,
|
||||
FormatCapabilityFlags caps) {
|
||||
Bool added = false;
|
||||
for (FormatCapability capability : kGLESProbeCapabilities) {
|
||||
for (FormatCapability capability : kReportedFormatCapabilities) {
|
||||
if (HasFormatCapability(caps, capability) &&
|
||||
!HasFormatCapability(cache.FullCaps[targetIndex][formatIndex], capability)) {
|
||||
cache.CaveatCaps[targetIndex][formatIndex] |= capability;
|
||||
@@ -316,7 +291,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return added;
|
||||
}
|
||||
|
||||
Int GetGLESFormatMaxSamples(const DynamicBackendParameters& dynamicParameters,
|
||||
Int GetGLESFormatMaxSamples(const MG_External::GLESCapabilities& capabilities,
|
||||
TextureInternalFormat logicalFormat,
|
||||
GLenum imageFormat) {
|
||||
const Bool isDepth = MG_Util::IsDepthFormatInternalFormat(logicalFormat);
|
||||
@@ -324,12 +299,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const Bool isInteger = imageFormat == GL_RED_INTEGER || imageFormat == GL_RG_INTEGER ||
|
||||
imageFormat == GL_RGB_INTEGER || imageFormat == GL_RGBA_INTEGER;
|
||||
if (isDepth || isStencil) {
|
||||
return dynamicParameters.MaxDepthTextureSamples;
|
||||
return capabilities.MaxDepthTextureSamples;
|
||||
}
|
||||
if (isInteger) {
|
||||
return dynamicParameters.MaxIntegerSamples;
|
||||
return capabilities.MaxIntegerSamples;
|
||||
}
|
||||
return dynamicParameters.MaxColorTextureSamples;
|
||||
return capabilities.MaxColorTextureSamples;
|
||||
}
|
||||
|
||||
Bool ProbeFramebufferCompletenessForTexture(const MG_External::GLESFunctionsTable& gl,
|
||||
@@ -527,12 +502,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return sampleCounts;
|
||||
}
|
||||
|
||||
void ProbeGLESFormatCapabilities(const MG_External::GLESFunctionsTable& gl,
|
||||
FormatCapabilityCache& cache,
|
||||
const DynamicBackendParameters& dynamicParameters) {
|
||||
void PopulateFormatCapabilitiesImpl(const MG_External::GLESFunctionsTable& gl,
|
||||
const MG_External::GLESCapabilities& capabilities,
|
||||
FormatCapabilityCache& cache) {
|
||||
cache.Clear();
|
||||
const Flags<PixelFormatNormalizeOptionBit> forcedOptions = GetForcedPixelFormatNormalizeOptions();
|
||||
const Flags<PixelFormatNormalizeOptionBit> driverOptions = GetDriverPixelFormatNormalizeOptions();
|
||||
const Flags<PixelFormatNormalizeOptionBit> forcedOptions =
|
||||
GetForcedPixelFormatNormalizeOptions(capabilities);
|
||||
const Flags<PixelFormatNormalizeOptionBit> driverOptions =
|
||||
GetDriverPixelFormatNormalizeOptions(capabilities);
|
||||
|
||||
for (SizeT formatIndex = 0; formatIndex < kFormatCapabilityFormatCount; ++formatIndex) {
|
||||
const auto logicalFormat = static_cast<TextureInternalFormat>(formatIndex);
|
||||
@@ -594,7 +571,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
AddFullFormatCaps(cache, renderbufferTargetIndex, formatIndex,
|
||||
GetRenderbufferFeatureCaps(logicalFormat));
|
||||
const Int maxSamples =
|
||||
GetGLESFormatMaxSamples(dynamicParameters, logicalFormat, nativeInfo.ImageFormat);
|
||||
GetGLESFormatMaxSamples(capabilities, logicalFormat, nativeInfo.ImageFormat);
|
||||
cache.SampleCounts[renderbufferTargetIndex][formatIndex] =
|
||||
ProbeRenderbufferSampleCounts(gl, nativeInfo.InternalFormat, logicalFormat, maxSamples);
|
||||
} else {
|
||||
@@ -608,7 +585,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
LogGLESFormatCaveat(logicalFormat, renderbufferTargetIndex, fallbackInfo);
|
||||
}
|
||||
const Int maxSamples =
|
||||
GetGLESFormatMaxSamples(dynamicParameters, logicalFormat, fallbackInfo.ImageFormat);
|
||||
GetGLESFormatMaxSamples(capabilities, logicalFormat, fallbackInfo.ImageFormat);
|
||||
cache.SampleCounts[renderbufferTargetIndex][formatIndex] =
|
||||
ProbeRenderbufferSampleCounts(gl, fallbackInfo.InternalFormat, logicalFormat, maxSamples);
|
||||
}
|
||||
@@ -655,6 +632,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void PopulateFormatCapabilities(const MG_External::GLESFunctionsTable& gl,
|
||||
const MG_External::GLESCapabilities& capabilities,
|
||||
FormatCapabilityCache& cache) {
|
||||
PopulateFormatCapabilitiesImpl(gl, capabilities, cache);
|
||||
}
|
||||
|
||||
BackendObject_DirectGLES::~BackendObject_DirectGLES() {
|
||||
DestroyEGLContext();
|
||||
}
|
||||
@@ -695,7 +678,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// the extension list is first built).
|
||||
UpdateAdvertisedTimerQueryExtension();
|
||||
UpdateDynamicBackendParameters();
|
||||
ProbeGLESFormatCapabilities(m_GLESFunctions, MutableFormatCapabilities(), m_dynamicParameters);
|
||||
PopulateFormatCapabilities(m_GLESFunctions, m_GLESCapabilities, MutableFormatCapabilities());
|
||||
PrintFormatCapabilities(GetFormatCapabilities());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// Populates the same format-capability cache used by backend startup. The caller
|
||||
// must keep the supplied GLES context current for the duration of this call.
|
||||
void PopulateFormatCapabilities(const MG_External::GLESFunctionsTable& gl,
|
||||
const MG_External::GLESCapabilities& capabilities,
|
||||
FormatCapabilityCache& cache);
|
||||
|
||||
class BackendObject_DirectGLES : public BackendObject {
|
||||
public:
|
||||
~BackendObject_DirectGLES() override;
|
||||
|
||||
@@ -182,25 +182,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return MG_Util::ConvertTextureInternalFormatToVkEnum(*fallbackLogicalFormat);
|
||||
}
|
||||
|
||||
constexpr FormatCapability kVulkanProbeCapabilities[] = {
|
||||
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 HasNewCaveatFormatCaps(FormatCapabilityFlags nativeCaps, FormatCapabilityFlags fallbackCaps) {
|
||||
for (FormatCapability capability : kVulkanProbeCapabilities) {
|
||||
for (FormatCapability capability : kReportedFormatCapabilities) {
|
||||
if (HasFormatCapability(fallbackCaps, capability) &&
|
||||
!HasFormatCapability(nativeCaps, capability)) {
|
||||
return true;
|
||||
@@ -209,21 +192,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return false;
|
||||
}
|
||||
|
||||
String GetFormatCapabilityTargetNameForLog(SizeT targetIndex) {
|
||||
if (targetIndex == GetRenderbufferFormatCapabilityTargetIndex()) {
|
||||
return "Renderbuffer";
|
||||
}
|
||||
if (targetIndex < kFormatCapabilityTextureTargetCount) {
|
||||
return MG_Util::ConvertTextureTargetToString(static_cast<TextureTarget>(targetIndex));
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void LogVulkanFormatCaveat(TextureInternalFormat logicalFormat,
|
||||
SizeT targetIndex,
|
||||
TextureInternalFormat fallbackFormat) {
|
||||
MGLOG_D("Caveat: %s %s not fully supported. Reason: native Vulkan format is not fully supported. Fallback: %s",
|
||||
GetFormatCapabilityTargetNameForLog(targetIndex).c_str(),
|
||||
GetFormatCapabilityTargetName(targetIndex).c_str(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(logicalFormat).c_str(),
|
||||
MG_Util::ConvertTextureInternalFormatToString(fallbackFormat).c_str());
|
||||
}
|
||||
@@ -237,11 +210,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return counts;
|
||||
}
|
||||
|
||||
void FillVulkanFormatCapabilities(VkPhysicalDevice physicalDevice,
|
||||
const DynamicBackendParameters& dynamicParameters,
|
||||
FormatCapabilityCache& cache) {
|
||||
void PopulateFormatCapabilitiesImpl(VkPhysicalDevice physicalDevice,
|
||||
PFN_vkGetPhysicalDeviceFormatProperties getFormatProperties,
|
||||
const MG_External::VulkanCapabilities& capabilities,
|
||||
FormatCapabilityCache& cache) {
|
||||
cache.Clear();
|
||||
if (physicalDevice == VK_NULL_HANDLE) {
|
||||
if (physicalDevice == VK_NULL_HANDLE || getFormatProperties == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -258,12 +232,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkFormatProperties nativeProperties{};
|
||||
if (nativeFormat != VK_FORMAT_UNDEFINED) {
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, nativeFormat, &nativeProperties);
|
||||
getFormatProperties(physicalDevice, nativeFormat, &nativeProperties);
|
||||
}
|
||||
|
||||
VkFormatProperties fallbackProperties{};
|
||||
if (fallbackFormat != VK_FORMAT_UNDEFINED && fallbackFormat != nativeFormat) {
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, fallbackFormat, &fallbackProperties);
|
||||
getFormatProperties(physicalDevice, fallbackFormat, &fallbackProperties);
|
||||
}
|
||||
|
||||
for (SizeT targetIndex = 0; targetIndex < kFormatCapabilityTextureTargetCount; ++targetIndex) {
|
||||
@@ -289,11 +263,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const Bool isDepth = MG_Util::IsDepthFormatInternalFormat(logicalFormat);
|
||||
const Bool isStencil = MG_Util::IsStencilFormatInternalFormat(logicalFormat);
|
||||
const Bool isInteger = IsIntegerInternalFormat(logicalFormat);
|
||||
Int maxSamples = dynamicParameters.MaxColorTextureSamples;
|
||||
Int maxSamples = capabilities.MaxColorTextureSamples;
|
||||
if (isDepth || isStencil) {
|
||||
maxSamples = dynamicParameters.MaxDepthTextureSamples;
|
||||
maxSamples = capabilities.MaxDepthTextureSamples;
|
||||
} else if (isInteger) {
|
||||
maxSamples = dynamicParameters.MaxIntegerSamples;
|
||||
maxSamples = capabilities.MaxIntegerSamples;
|
||||
}
|
||||
cache.SampleCounts[targetIndex][formatIndex] = BuildSampleCounts(maxSamples);
|
||||
}
|
||||
@@ -332,12 +306,19 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
cache.CaveatCaps[renderbufferTargetIndex][formatIndex];
|
||||
if (HasFormatCapability(rbCaps, FormatCapability::MultisampleRenderbuffer)) {
|
||||
cache.SampleCounts[renderbufferTargetIndex][formatIndex] =
|
||||
BuildSampleCounts(dynamicParameters.MaxFramebufferSamples);
|
||||
BuildSampleCounts(capabilities.MaxFramebufferSamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void PopulateFormatCapabilities(VkPhysicalDevice physicalDevice,
|
||||
PFN_vkGetPhysicalDeviceFormatProperties getFormatProperties,
|
||||
const MG_External::VulkanCapabilities& capabilities,
|
||||
FormatCapabilityCache& cache) {
|
||||
PopulateFormatCapabilitiesImpl(physicalDevice, getFormatProperties, capabilities, cache);
|
||||
}
|
||||
|
||||
BackendObject_DirectVulkan::~BackendObject_DirectVulkan() = default;
|
||||
|
||||
BackendObject_DirectVulkan::BackendObject_DirectVulkan(): m_rendererInfo{GetRendererIdentity()} {}
|
||||
@@ -394,7 +375,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
UpdateDynamicBackendParameters();
|
||||
UpdateAdvertisedExtensions();
|
||||
FillVulkanFormatCapabilities(physicalDevice.handle, m_dynamicParameters, MutableFormatCapabilities());
|
||||
PopulateFormatCapabilities(physicalDevice.handle, vkGetPhysicalDeviceFormatProperties, m_vulkanCaps,
|
||||
MutableFormatCapabilities());
|
||||
PrintFormatCapabilities(GetFormatCapabilities());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
#include <MG_Util/BackendLoaders/Vulkan/Loader.h>
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// Populates the same format-capability cache used by backend startup. Passing the
|
||||
// instance-resolved function keeps standalone callers independent of global loader
|
||||
// initialization; the physical device must remain valid for the duration of the call.
|
||||
void PopulateFormatCapabilities(VkPhysicalDevice physicalDevice,
|
||||
PFN_vkGetPhysicalDeviceFormatProperties getFormatProperties,
|
||||
const MG_External::VulkanCapabilities& capabilities,
|
||||
FormatCapabilityCache& cache);
|
||||
|
||||
class BackendObject_DirectVulkan : public BackendObject {
|
||||
public:
|
||||
BackendObject_DirectVulkan();
|
||||
|
||||
@@ -525,6 +525,9 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
summary.capsValid = true;
|
||||
const MG_External::GLESCapabilities& caps = summary.caps;
|
||||
builder.report.rendererInfo = format("{} ({})", caps.GLESRendererString, caps.GLESVersionString);
|
||||
builder.report.formatCapabilities.emplace();
|
||||
MG_Backend::DirectGLES::PopulateFormatCapabilities(
|
||||
glesFuncs, caps, builder.report.formatCapabilities.value());
|
||||
EvaluateGlesChecklist(builder, caps, glesFuncs);
|
||||
ProbeGlesTimerQuery(builder, caps, glesFuncs);
|
||||
} while (false);
|
||||
@@ -980,6 +983,9 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
getInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"));
|
||||
const auto vkGetPhysicalDeviceProperties2Fn = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2>(
|
||||
getInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"));
|
||||
const auto vkGetPhysicalDeviceFormatPropertiesFn =
|
||||
reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(
|
||||
getInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties"));
|
||||
|
||||
// The instance is destroyed from a scope guard so it is released on every early-return
|
||||
// path and even if a String/format allocation throws while report rows are being built.
|
||||
@@ -1059,6 +1065,14 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
summary.deviceName = String(properties.deviceName);
|
||||
summary.apiVersionString = VkApiVersionToString(properties.apiVersion);
|
||||
summary.driverVersionString = driverVersionString;
|
||||
if (vkGetPhysicalDeviceFormatPropertiesFn != nullptr) {
|
||||
MG_External::VulkanCapabilities formatProbeCapabilities{};
|
||||
BackendLoader::FillInVulkanCapabilities(formatProbeCapabilities, properties);
|
||||
builder.report.formatCapabilities.emplace();
|
||||
MG_Backend::DirectVulkan::PopulateFormatCapabilities(
|
||||
physicalDevice, vkGetPhysicalDeviceFormatPropertiesFn, formatProbeCapabilities,
|
||||
builder.report.formatCapabilities.value());
|
||||
}
|
||||
|
||||
// The chosen-device facts (name, enumeration count, graphics queue) ride along
|
||||
// on both outcomes so the device API verdict never hides them.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <Includes.h>
|
||||
#include <MG_Backend/BackendObject.h>
|
||||
|
||||
namespace MobileGL::MG_Util::SelfTest {
|
||||
// One row of a backend power-on self-test (POST) report.
|
||||
@@ -33,6 +34,7 @@ namespace MobileGL::MG_Util::SelfTest {
|
||||
String verdict = "UNSUPPORTED"; // "OK" | "DEGRADED" | "UNSUPPORTED"
|
||||
String rendererInfo;
|
||||
Vector<PostCheck> checks;
|
||||
Optional<MG_Backend::FormatCapabilityCache> formatCapabilities;
|
||||
};
|
||||
|
||||
// Probes the DEVICE GLES driver with self-contained EGL boilerplate (1x1 pbuffer
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#include "DriverPost.h"
|
||||
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
@@ -19,6 +20,9 @@ namespace {
|
||||
using MobileGL::SizeT;
|
||||
using MobileGL::String;
|
||||
using MobileGL::StringStream;
|
||||
using MobileGL::Uint64;
|
||||
using MobileGL::MG_Backend::FormatCapabilityCache;
|
||||
using MobileGL::MG_Backend::FormatCapabilityFlags;
|
||||
using MobileGL::MG_Util::SelfTest::BackendPostReport;
|
||||
using MobileGL::MG_Util::SelfTest::PostCheck;
|
||||
|
||||
@@ -70,6 +74,55 @@ namespace {
|
||||
out << '"' << EscapeJsonString(value) << '"';
|
||||
}
|
||||
|
||||
Uint64 BuildFormatCapabilityMask(FormatCapabilityFlags capabilities) {
|
||||
Uint64 mask = 0;
|
||||
for (SizeT capabilityIndex = 0;
|
||||
capabilityIndex < MobileGL::MG_Backend::kReportedFormatCapabilities.size(); ++capabilityIndex) {
|
||||
if (MobileGL::MG_Backend::HasFormatCapability(
|
||||
capabilities, MobileGL::MG_Backend::kReportedFormatCapabilities[capabilityIndex])) {
|
||||
mask |= 1ull << capabilityIndex;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
void AppendFormatCapabilitiesJson(StringStream& out, const FormatCapabilityCache& cache) {
|
||||
out << ",\"formatCapabilities\":{\"capabilities\":[";
|
||||
for (SizeT capabilityIndex = 0;
|
||||
capabilityIndex < MobileGL::MG_Backend::kReportedFormatCapabilities.size(); ++capabilityIndex) {
|
||||
if (capabilityIndex != 0) {
|
||||
out << ',';
|
||||
}
|
||||
AppendJsonString(
|
||||
out, MobileGL::MG_Backend::GetFormatCapabilityName(
|
||||
MobileGL::MG_Backend::kReportedFormatCapabilities[capabilityIndex]));
|
||||
}
|
||||
out << "],\"targets\":[";
|
||||
for (SizeT targetIndex = 0; targetIndex < MobileGL::MG_Backend::kFormatCapabilityTargetCount;
|
||||
++targetIndex) {
|
||||
if (targetIndex != 0) {
|
||||
out << ',';
|
||||
}
|
||||
out << "{\"name\":";
|
||||
AppendJsonString(out, MobileGL::MG_Backend::GetFormatCapabilityTargetName(targetIndex));
|
||||
out << ",\"rows\":[";
|
||||
for (SizeT formatIndex = 0; formatIndex < MobileGL::MG_Backend::kFormatCapabilityFormatCount;
|
||||
++formatIndex) {
|
||||
if (formatIndex != 0) {
|
||||
out << ',';
|
||||
}
|
||||
out << '[';
|
||||
AppendJsonString(
|
||||
out, MobileGL::MG_Util::ConvertTextureInternalFormatToString(
|
||||
static_cast<MobileGL::TextureInternalFormat>(formatIndex)));
|
||||
out << ',' << BuildFormatCapabilityMask(cache.FullCaps[targetIndex][formatIndex]);
|
||||
out << ',' << BuildFormatCapabilityMask(cache.CaveatCaps[targetIndex][formatIndex]) << ']';
|
||||
}
|
||||
out << "]}";
|
||||
}
|
||||
out << "]}";
|
||||
}
|
||||
|
||||
void AppendBackendReportJson(StringStream& out, const BackendPostReport& report) {
|
||||
out << "{\"available\":" << (report.available ? "true" : "false");
|
||||
out << ",\"verdict\":";
|
||||
@@ -90,7 +143,11 @@ namespace {
|
||||
AppendJsonString(out, check.detail);
|
||||
out << '}';
|
||||
}
|
||||
out << "]}";
|
||||
out << ']';
|
||||
if (report.formatCapabilities.has_value()) {
|
||||
AppendFormatCapabilitiesJson(out, report.formatCapabilities.value());
|
||||
}
|
||||
out << '}';
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in New Issue
Block a user