mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 05:38:31 +09:00
[Fix, Test] (BackendLoader, DirectVulkan, ShaderTranspiler): report GL_MAX_CLIP_DISTANCES from the backend's real clip-distance capability
This commit is contained in:
@@ -1063,7 +1063,15 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
GLint maxComputeImageUniforms = 8;
|
||||
GLint maxDrawBuffers = 8;
|
||||
GLint maxColorAttachments = 8;
|
||||
GLint maxClipDistances = 8;
|
||||
// Zero is a legal answer, not a placeholder. GL_MAX_CLIP_DISTANCES exists in ES only as
|
||||
// GL_MAX_CLIP_DISTANCES_EXT under GL_EXT_clip_cull_distance, so on a driver without that
|
||||
// extension there is nowhere to put a clip distance at all: SPIRV-Cross emits
|
||||
// gl_ClipDistance behind an `#extension ... : require` the ESSL compiler rejects, and
|
||||
// DirectGLES has no state to forward the per-distance enables into (see the gate in
|
||||
// DirectGLES::SyncRenderState). Starting at 8 meant a probe that could never run left an
|
||||
// optimistic 8 behind, so the frontend promised eight clip planes and every draw with a
|
||||
// clipping program silently rendered nothing. The guarded probe below only ever widens it.
|
||||
GLint maxClipDistances = 0;
|
||||
GLint maxViewports = 16;
|
||||
GLfloat minFragmentInterpolationOffset = -0.5f;
|
||||
GLfloat maxFragmentInterpolationOffset = 0.4375f;
|
||||
@@ -1195,7 +1203,30 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
}
|
||||
glesFuncs.glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances);
|
||||
// GL_MAX_CLIP_DISTANCES is 0x0D32, which ES only ever spells GL_MAX_CLIP_DISTANCES_EXT and
|
||||
// only ever has under GL_EXT_clip_cull_distance. The extension was already resolved into
|
||||
// caps.SupportsClipDistance a few hundred lines above and is the same flag DirectGLES
|
||||
// gates the CLIP_DISTANCEi enable forwarding on, so ask the driver only where the pname
|
||||
// exists; everywhere else the honest 0 stands and no GL_INVALID_ENUM is left behind for an
|
||||
// unrelated query - or the application's first glGetError - to trip over.
|
||||
if (caps.SupportsClipDistance) {
|
||||
if (glesFuncs.glGetError) {
|
||||
while (glesFuncs.glGetError() != GL_NO_ERROR) {
|
||||
}
|
||||
}
|
||||
glesFuncs.glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances);
|
||||
Bool queryFailed = false;
|
||||
if (glesFuncs.glGetError) {
|
||||
while (glesFuncs.glGetError() != GL_NO_ERROR) {
|
||||
queryFailed = true;
|
||||
}
|
||||
}
|
||||
if (queryFailed) {
|
||||
MGLOG_W("GL_EXT_clip_cull_distance is advertised but GL_MAX_CLIP_DISTANCES was "
|
||||
"rejected; reporting no clip distances");
|
||||
maxClipDistances = 0;
|
||||
}
|
||||
}
|
||||
glesFuncs.glGetIntegerv(GL_MAX_VIEWPORTS, &maxViewports);
|
||||
glesFuncs.glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDims);
|
||||
glesFuncs.glGetIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &viewportSubpixelBits);
|
||||
@@ -1368,7 +1399,9 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
caps.MaxComputeImageUniforms = maxComputeImageUniforms;
|
||||
caps.MaxDrawBuffers = maxDrawBuffers;
|
||||
caps.MaxColorAttachments = maxColorAttachments;
|
||||
caps.MaxClipDistances = maxClipDistances;
|
||||
// A driver is free to write nonsense into an out-param it then rejects, and without the
|
||||
// extension the probe above never ran at all - so the flag, not the local, decides.
|
||||
caps.MaxClipDistances = caps.SupportsClipDistance ? std::max(maxClipDistances, 0) : 0;
|
||||
caps.MaxViewports = maxViewports;
|
||||
caps.MaxViewportWidth = maxViewportDims[0];
|
||||
caps.MaxViewportHeight = maxViewportDims[1];
|
||||
@@ -1450,7 +1483,12 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
MGLOG_I(" GL_MAX_COMPUTE_IMAGE_UNIFORMS: %d", caps.MaxComputeImageUniforms);
|
||||
MGLOG_I(" GL_MAX_DRAW_BUFFERS: %d", caps.MaxDrawBuffers);
|
||||
MGLOG_I(" GL_MAX_COLOR_ATTACHMENTS: %d", caps.MaxColorAttachments);
|
||||
MGLOG_I(" GL_MAX_CLIP_DISTANCES: %d", caps.MaxClipDistances);
|
||||
// Worth spelling the reason out for the same reason the per-stage storage block counts
|
||||
// are: a zero here is what stops an application's gl_ClipDistance from ever clipping, and
|
||||
// reading it back from an artifact is the difference between "MobileGL dropped my draw"
|
||||
// and "this driver has no clip distances".
|
||||
MGLOG_I(" GL_MAX_CLIP_DISTANCES: %d%s", caps.MaxClipDistances,
|
||||
caps.SupportsClipDistance ? "" : " (no GL_EXT_clip_cull_distance on this driver)");
|
||||
MGLOG_I(" GL_MAX_VIEWPORTS: %d", caps.MaxViewports);
|
||||
MGLOG_I(" GL_MAX_VIEWPORT_DIMS: [%d, %d]", caps.MaxViewportWidth, caps.MaxViewportHeight);
|
||||
MGLOG_I(" GL_VIEWPORT_BOUNDS_RANGE: [%.3f, %.3f]", caps.ViewportBoundsRangeMin,
|
||||
|
||||
@@ -1275,7 +1275,10 @@ namespace MobileGL {
|
||||
Int MaxComputeImageUniforms = 8;
|
||||
Int MaxDrawBuffers = 8;
|
||||
Int MaxColorAttachments = 8;
|
||||
Int MaxClipDistances = 8;
|
||||
// Zero is a legal answer, not a placeholder: ES reaches clip distances only through
|
||||
// GL_EXT_clip_cull_distance, so a driver without it has none. See the guarded probe
|
||||
// in FillInGLESCapabilities.
|
||||
Int MaxClipDistances = 0;
|
||||
Int MaxViewports = 16;
|
||||
Int MaxViewportWidth = 16384;
|
||||
Int MaxViewportHeight = 16384;
|
||||
|
||||
@@ -237,6 +237,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
supportedFeatures.vertexPipelineStoresAndAtomics == VK_TRUE;
|
||||
caps.SupportsFragmentStoresAndAtomics = supportedFeatures.fragmentStoresAndAtomics == VK_TRUE;
|
||||
caps.SupportsGeometryShader = supportedFeatures.geometryShader == VK_TRUE;
|
||||
caps.SupportsShaderClipDistance = supportedFeatures.shaderClipDistance == VK_TRUE;
|
||||
caps.MaxShaderStorageBlockSize = static_cast<SizeT>(p.limits.maxStorageBufferRange);
|
||||
const Bool supportsShaderSubgroup = vk.vkGetPhysicalDeviceProperties2 &&
|
||||
HasUsableShaderSubgroupSupport(subgroupProps);
|
||||
@@ -331,6 +332,7 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
caps.SupportsVertexPipelineStoresAndAtomics = false;
|
||||
caps.SupportsFragmentStoresAndAtomics = false;
|
||||
caps.SupportsGeometryShader = false;
|
||||
caps.SupportsShaderClipDistance = false;
|
||||
caps.MaxShaderStorageBlockSize = static_cast<SizeT>(properties.limits.maxStorageBufferRange);
|
||||
caps.SupportsShaderSubgroup = false;
|
||||
caps.SubgroupSize = 0;
|
||||
|
||||
@@ -96,6 +96,12 @@ namespace MobileGL {
|
||||
Bool SupportsVertexPipelineStoresAndAtomics = false;
|
||||
Bool SupportsFragmentStoresAndAtomics = false;
|
||||
Bool SupportsGeometryShader = false;
|
||||
// VkPhysicalDeviceFeatures::shaderClipDistance. maxClipDistances is a LIMIT and is
|
||||
// reported whatever the feature says, so the limit alone does not mean a module may
|
||||
// declare ClipDistance - VulkanRenderer enables the feature only where the physical
|
||||
// device has it, and without it a shader writing gl_ClipDistance is invalid. Very
|
||||
// widely supported, hence read from the device features and never assumed false.
|
||||
Bool SupportsShaderClipDistance = false;
|
||||
SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024;
|
||||
Bool SupportsShaderSubgroup = false;
|
||||
Uint32 SubgroupSize = 0;
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace MobileGL {
|
||||
Resources.maxFragmentInputVectors = 15;
|
||||
Resources.minProgramTexelOffset = -8;
|
||||
Resources.maxProgramTexelOffset = 7;
|
||||
Resources.maxClipDistances = 8;
|
||||
Resources.maxComputeUniformComponents = MAX_COMPUTE_UNIFORM_COMPONENTS;
|
||||
Resources.maxComputeTextureImageUnits = 16;
|
||||
Resources.maxComputeImageUniforms = 8;
|
||||
@@ -173,6 +172,14 @@ namespace MobileGL {
|
||||
Resources.maxComputeImageUniforms = dynamicParameters.MaxComputeImageUniforms;
|
||||
Resources.maxCombinedImageUniforms = dynamicParameters.MaxCombinedImageUniforms;
|
||||
Resources.maxComputeTextureImageUnits = dynamicParameters.MaxComputeTextureImageUnits;
|
||||
// Load-bearing, not cosmetic. glslang rejects gl_ClipDistance[i] for
|
||||
// i >= maxClipDistances (ParseHelper.cpp) and expands gl_MaxClipDistances from the
|
||||
// same number, so tracking the backend limit is what turns "the program links,
|
||||
// the backend's shader compile fails somewhere the frontend never surfaces, and
|
||||
// the draw renders nothing" into an honest glCompileShader error with a log. It is
|
||||
// also what makes glGetIntegerv(GL_MAX_CLIP_DISTANCES) and gl_MaxClipDistances
|
||||
// agree, which KHR-GLxx.clip_distance.coverage compares directly.
|
||||
Resources.maxClipDistances = dynamicParameters.MaxClipDistances;
|
||||
|
||||
// The compute work-group limits are the env's, not the backend parameters': they
|
||||
// are the only ones that come from a REAL indexed driver query, which
|
||||
|
||||
Reference in New Issue
Block a user