mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-18 00:58:30 +09:00
[Fix, Test] (GLImpl, ShaderTranspiler): reconcile the atomic-counter limits glGetIntegerv and glslang advertise
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <MG_State/GLState/FramebufferState/FramebufferObject.h>
|
||||
#include <MG_Util/Texture/TextureFormatProcessor.h>
|
||||
#include <MG_Util/Async/ShaderCompilePool.h>
|
||||
#include <MG_Util/ShaderTranspiler/Types.h>
|
||||
#include <MG_Backend/BackendObjects.h>
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
@@ -47,12 +48,25 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
constexpr GLint kFrontendMaxComputeUniformComponents = 1024;
|
||||
constexpr GLint kFrontendMaxComputeAtomicCounters = 8;
|
||||
constexpr GLint kFrontendMaxComputeAtomicCounterBuffers = 8;
|
||||
// Every atomic-counter limit is shared with the glslang resource table
|
||||
// (BuildTBuiltInResource) through MG_Util/ShaderTranspiler/Types.h: GL 4.6 requires
|
||||
// glGetIntegerv and the gl_MaxAtomicCounter* built-in constants to agree, and the two
|
||||
// used to be independent tables that disagreed on both the binding count and the buffer
|
||||
// size. Never move one of these without the other.
|
||||
constexpr GLint kFrontendMaxComputeAtomicCounters =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTERS_PER_STAGE);
|
||||
constexpr GLint kFrontendMaxComputeAtomicCounterBuffers =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTER_BUFFERS_PER_STAGE);
|
||||
constexpr GLint kFrontendMaxComputeSharedMemorySize = 32768;
|
||||
constexpr GLint kFrontendMaxComputeWorkGroupInvocations = 1024;
|
||||
constexpr GLint kFrontendMaxCombinedAtomicCounters = 8;
|
||||
constexpr GLint kFrontendMaxFragmentAtomicCounters = 8;
|
||||
constexpr GLint kFrontendMaxCombinedAtomicCounters =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTERS_PER_STAGE);
|
||||
constexpr GLint kFrontendMaxCombinedAtomicCounterBuffers =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTER_BUFFERS_PER_STAGE);
|
||||
constexpr GLint kFrontendMaxFragmentAtomicCounters =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTERS_PER_STAGE);
|
||||
constexpr GLint kFrontendMaxFragmentAtomicCounterBuffers =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTER_BUFFERS_PER_STAGE);
|
||||
constexpr GLint kFrontendMaxGeometryAtomicCounters = 0;
|
||||
constexpr GLint kFrontendMaxTessControlAtomicCounters = 0;
|
||||
constexpr GLint kFrontendMaxTessEvaluationAtomicCounters = 0;
|
||||
@@ -66,10 +80,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
constexpr GLint kFrontendMaxTessControlAtomicCounterBuffers = 0;
|
||||
constexpr GLint kFrontendMaxTessEvaluationAtomicCounterBuffers = 0;
|
||||
constexpr GLint kFrontendMaxVertexAtomicCounterBuffers = 0;
|
||||
// One atomic counter is a uint, and a buffer never has to hold more counters than the
|
||||
// combined limit the frontend advertises. GL 4.6 table 23.63 floors this at 32 bytes.
|
||||
// GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS / _SIZE. Both come from the shared table above:
|
||||
// the binding count is how many counter buffers a backend can actually address (each one
|
||||
// costs a shader-storage binding point once glslang has lowered the counters onto a
|
||||
// storage block), and the size is the byte offset ceiling a counter may be declared at.
|
||||
constexpr GLint kFrontendMaxAtomicCounterBufferBindings =
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
|
||||
constexpr GLint kFrontendMaxAtomicCounterBufferSize =
|
||||
kFrontendMaxCombinedAtomicCounters * static_cast<GLint>(sizeof(GLuint));
|
||||
static_cast<GLint>(MG_Util::ShaderTranspiler::MAX_ATOMIC_COUNTER_BUFFER_SIZE);
|
||||
// KHR_debug minima (GL 4.6 table 23.66); the debug entry points are stubs, but the
|
||||
// limits they advertise still have to be legal.
|
||||
constexpr GLint kFrontendMaxDebugGroupStackDepth = 64;
|
||||
@@ -1532,6 +1550,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_MAX_COMBINED_ATOMIC_COUNTERS:
|
||||
*params = kFrontendMaxCombinedAtomicCounters;
|
||||
return;
|
||||
case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
|
||||
*params = kFrontendMaxCombinedAtomicCounterBuffers;
|
||||
return;
|
||||
case GL_MAX_COMBINED_UNIFORM_BLOCKS:
|
||||
*params = ClampUniformBlockCount(kFrontendMaxCombinedUniformBlocks);
|
||||
return;
|
||||
@@ -1547,6 +1568,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
|
||||
*params = kFrontendMaxFragmentAtomicCounters;
|
||||
return;
|
||||
case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
|
||||
*params = kFrontendMaxFragmentAtomicCounterBuffers;
|
||||
return;
|
||||
case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
|
||||
*params = ClampStorageBlockCount(16); // TODO
|
||||
return;
|
||||
@@ -1984,6 +2008,24 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
case GL_UNIFORM_BUFFER_START:
|
||||
RecordIndexedOnlyGetterError(__func__, pname);
|
||||
return;
|
||||
// glBindBufferBase/Range set the GENERIC binding point too (GL 4.6 core 6.1.1), and this
|
||||
// is the one indexed-buffer family whose non-indexed query was never answered - so it
|
||||
// fell through to INVALID_ENUM and left the caller's variable holding whatever was in its
|
||||
// stack slot. _START/_SIZE stay indexed-only, exactly like their uniform-buffer siblings.
|
||||
case GL_ATOMIC_COUNTER_BUFFER_BINDING:
|
||||
if (const auto& obj =
|
||||
MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::AtomicCounter).GetBoundObject()) {
|
||||
*params = static_cast<GLint>(obj->GetExternalIndex());
|
||||
} else {
|
||||
*params = 0;
|
||||
}
|
||||
return;
|
||||
case GL_ATOMIC_COUNTER_BUFFER_START:
|
||||
RecordIndexedOnlyGetterError(__func__, pname);
|
||||
return;
|
||||
case GL_ATOMIC_COUNTER_BUFFER_SIZE:
|
||||
RecordIndexedOnlyGetterError(__func__, pname);
|
||||
return;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
*params = MG_State::pGLContext->GetPixelStoreParam(PixelStoreParam::UnpackAlignment);
|
||||
return;
|
||||
@@ -2219,18 +2261,20 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
static_cast<Uint64>(INT32_MAX)));
|
||||
break;
|
||||
case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
|
||||
*params = static_cast<GLint>(GetIndexedBufferQueryPointCount(BufferTarget::AtomicCounter));
|
||||
// NOT the frontend's binding-point array size (36). A counter buffer only reaches a
|
||||
// shader as a lowered storage block, so the number an implementation can serve is
|
||||
// the reserved shader-storage range, and it has to be the same number glslang
|
||||
// compiles a layout(binding = N) atomic_uint against.
|
||||
*params = std::min<GLint>(kFrontendMaxAtomicCounterBufferBindings,
|
||||
static_cast<GLint>(GetIndexedBufferQueryPointCount(BufferTarget::AtomicCounter)));
|
||||
break;
|
||||
case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
|
||||
// The conformance suite splits this evenly across every advertised binding point and
|
||||
// binds all of them in one glBindBuffersRange
|
||||
// (KHR-GL44.multi_bind.functional_bind_buffers_range), so the pair has to divide:
|
||||
// 32 bytes over 36 binding points is a zero-sized range, which BindBufferRange
|
||||
// rejects with INVALID_VALUE before it binds anything. Floor the advertised size at
|
||||
// one counter per binding point.
|
||||
*params = std::max<GLint>(
|
||||
kFrontendMaxAtomicCounterBufferSize,
|
||||
static_cast<GLint>(GetIndexedBufferQueryPointCount(BufferTarget::AtomicCounter) * sizeof(GLuint)));
|
||||
// (KHR-GL44.multi_bind.functional_bind_buffers_range), so the pair has to divide -
|
||||
// a zero-sized range is INVALID_VALUE before BindBufferRange binds anything. The
|
||||
// shared constant is 16384 over 8 binding points, which divides.
|
||||
*params = kFrontendMaxAtomicCounterBufferSize;
|
||||
break;
|
||||
case GL_MAX_TEXTURE_BUFFER_SIZE:
|
||||
*params = dynamicParameters.MaxTextureBufferSize;
|
||||
|
||||
Reference in New Issue
Block a user