[Fix] (GLImpl, DirectGLES, DirectVulkan): floor every advertised sample cap and clamp the realised count in the backends

This commit is contained in:
2026-08-20 04:10:45 -04:00
parent d9abf1c2c1
commit f297af7d2b
8 changed files with 137 additions and 22 deletions
@@ -13,6 +13,7 @@
#include <MG_Backend/BackendObjects.h>
#include <MG_Util/Metrics/TextureMetrics.h>
#include <MG_Impl/GLImpl/Texture/Validators.h>
#include <MG_Impl/GLImpl/Getter/GL_Getter.h>
#include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
@@ -617,16 +618,17 @@ namespace MobileGL::MG_Impl::GLImpl {
if (MG_Backend::pActiveBackendObject == nullptr) {
return std::numeric_limits<Int>::max();
}
return std::max(MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxSamples, 1);
return GetAdvertisedMaxSamples();
}
// GL_MAX_SAMPLES is the ceiling over all formats; an integer format has its own, lower
// one (GL_MAX_INTEGER_SAMPLES) and GL 4.6 core 9.2.4 makes exceeding it INVALID_OPERATION.
// The multisample TEXTURE path already resolves the limit per format
// (GL_Texture.cpp, GetMaxTextureSamplesForFormat); renderbuffers only ever compared
// against GL_MAX_SAMPLES, so on a driver where the two differ - Adreno reports
// GL_MAX_SAMPLES 4 and GL_MAX_INTEGER_SAMPLES 1 - an integer renderbuffer accepted a
// sample count the format cannot deliver, and said GL_NO_ERROR about it.
// GL_MAX_SAMPLES is the ceiling over all formats; an integer format has its own
// (GL_MAX_INTEGER_SAMPLES) and GL 4.6 core 9.2.4 makes exceeding it INVALID_OPERATION.
// The multisample TEXTURE path resolves the limit per format the same way
// (GL_Texture.cpp, GetMaxSupportedTextureSamples). Both are floored to the value MobileGL
// advertises: on a driver where the two differ - Adreno reports GL_MAX_SAMPLES 4 and
// GL_MAX_INTEGER_SAMPLES 1 - rejecting the advertised count here only moves the failure
// from the driver into MobileGL, so the frontend accepts it and the backend clamps the
// count it actually hands the driver.
Int GetMaxRenderbufferSamplesForFormat_State(TextureInternalFormat format) {
if (MG_Backend::pActiveBackendObject == nullptr) {
return std::numeric_limits<Int>::max();
@@ -645,7 +647,10 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!isIntegerFormat) {
return GetMaxRenderbufferSamples_State();
}
return std::max(dynamicParameters.MaxIntegerSamples, 1);
// Per-format still, but never below the ceiling glGetIntegerv(GL_MAX_SAMPLES) promised:
// the driver's raw GL_MAX_INTEGER_SAMPLES stays the *backend* limit and the backend
// clamps to it, while the frontend honours what it advertised.
return std::max(dynamicParameters.MaxIntegerSamples, GetAdvertisedMaxSamples());
}
Bool ValidateRenderbufferStorageSize_State(GLsizei width, GLsizei height, const char* caller) {