diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index efa3c1893d3..952183f55e7 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -776,6 +776,12 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general") \value TextureArraySizeMax Maximum texture array size. Typically in range 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture array} with more elements will likely fail. + + \value MaxUniformBufferRange The number of bytes that can be exposed from a + uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0 + implementations this may be as low as 3584 bytes (224 four component, 32 + bits per component vectors). Elsewhere the value is typically 16384 (1024 + vec4s) or 65536 (4096 vec4s). */ /*! @@ -3228,6 +3234,9 @@ bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBindi suitable for creating pipelines. Such a pipeline must then always be used together with another, layout compatible QRhiShaderResourceBindings with resources present passed to QRhiCommandBuffer::setShaderResources(). + + \note If the size of \a buf exceeds the limit reported for + QRhi::MaxUniformBufferRange, unexpected errors may occur. */ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer( int binding, StageFlags stage, QRhiBuffer *buf) @@ -3262,6 +3271,9 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer( suitable for creating pipelines. Such a pipeline must then always be used together with another, layout compatible QRhiShaderResourceBindings with resources present passed to QRhiCommandBuffer::setShaderResources(). + + \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange, + unexpected errors may occur. */ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer( int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size) @@ -3296,6 +3308,9 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer( suitable for creating pipelines. Such a pipeline must then always be used together with another, layout compatible QRhiShaderResourceBindings with resources present passed to QRhiCommandBuffer::setShaderResources(). + + \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange, + unexpected errors may occur. */ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset( int binding, StageFlags stage, QRhiBuffer *buf, int size) diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 4decdd0c917..5344046841a 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1612,7 +1612,8 @@ public: MaxThreadGroupX, MaxThreadGroupY, MaxThreadGroupZ, - TextureArraySizeMax + TextureArraySizeMax, + MaxUniformBufferRange }; ~QRhi(); diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 631e7f7adf4..d2b217b6d4a 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -580,6 +580,8 @@ int QRhiD3D11::resourceLimit(QRhi::ResourceLimit limit) const return D3D11_CS_THREAD_GROUP_MAX_Z; case QRhi::TextureArraySizeMax: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + case QRhi::MaxUniformBufferRange: + return 65536; default: Q_UNREACHABLE(); return 0; diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 5259be270ca..4512acb9697 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -405,6 +405,22 @@ QT_BEGIN_NAMESPACE #define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF #endif +#ifndef GL_MAX_VERTEX_UNIFORM_COMPONENTS +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#endif + +#ifndef GL_MAX_FRAGMENT_UNIFORM_COMPONENTS +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#endif + +#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#endif + +#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#endif + /*! Constructs a new QRhiGles2InitParams. @@ -694,6 +710,23 @@ bool QRhiGles2::create(QRhi::Flags flags) caps.maxTextureArraySize = 0; } + // The ES 2.0 spec only has MAX_xxxx_VECTORS. ES 3.0 and up has both + // *VECTORS and *COMPONENTS. OpenGL 2.0-4.0 only has MAX_xxxx_COMPONENTS. + // 4.1 and above has both. What a mess. + if (caps.gles) { + GLint maxVertexUniformVectors = 0; + f->glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors); + GLint maxFragmentUniformVectors = 0; + f->glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors); + caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors); + } else { + GLint maxVertexUniformComponents = 0; + f->glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &maxVertexUniformComponents); + GLint maxFragmentUniformComponents = 0; + f->glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &maxFragmentUniformComponents); + caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4; + } + if (!caps.gles) { f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); f->glEnable(GL_POINT_SPRITE); @@ -1125,6 +1158,8 @@ int QRhiGles2::resourceLimit(QRhi::ResourceLimit limit) const return caps.maxThreadGroupsZ; case QRhi::TextureArraySizeMax: return 2048; + case QRhi::MaxUniformBufferRange: + return int(qMin(INT_MAX, caps.maxUniformVectors * qint64(16))); default: Q_UNREACHABLE(); return 0; diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 48f79e3c1db..c3297f488d6 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -918,6 +918,7 @@ public: maxThreadGroupsX(0), maxThreadGroupsY(0), maxThreadGroupsZ(0), + maxUniformVectors(4096), msaaRenderBuffer(false), multisampledTexture(false), npotTextureFull(true), @@ -960,6 +961,7 @@ public: int maxThreadGroupsX; int maxThreadGroupsY; int maxThreadGroupsZ; + int maxUniformVectors; // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not // the same as multisample textures! uint msaaRenderBuffer : 1; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 3e4c0e08e25..169d80251d8 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -650,6 +650,8 @@ int QRhiMetal::resourceLimit(QRhi::ResourceLimit limit) const #endif case QRhi::TextureArraySizeMax: return 2048; + case QRhi::MaxUniformBufferRange: + return 65536; default: Q_UNREACHABLE(); return 0; diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index c1609584935..b23af75bd96 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -164,6 +164,8 @@ int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const return 0; case QRhi::TextureArraySizeMax: return 2048; + case QRhi::MaxUniformBufferRange: + return 65536; default: Q_UNREACHABLE(); return 0; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index c0d5ab1c07d..1cead19f771 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -4305,6 +4305,8 @@ int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const return int(physDevProperties.limits.maxComputeWorkGroupSize[2]); case QRhi::TextureArraySizeMax: return int(physDevProperties.limits.maxImageArrayLayers); + case QRhi::MaxUniformBufferRange: + return int(qMin(INT_MAX, physDevProperties.limits.maxUniformBufferRange)); default: Q_UNREACHABLE(); return 0; diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index eba9b9ce302..8ac18af9fbb 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -339,12 +339,14 @@ void tst_QRhi::create() const int maxAtt = rhi->resourceLimit(QRhi::MaxColorAttachments); const int framesInFlight = rhi->resourceLimit(QRhi::FramesInFlight); const int texArrayMax = rhi->resourceLimit(QRhi::TextureArraySizeMax); + const int uniBufRangeMax = rhi->resourceLimit(QRhi::MaxUniformBufferRange); QVERIFY(texMin >= 1); QVERIFY(texMax >= texMin); QVERIFY(maxAtt >= 1); QVERIFY(framesInFlight >= 1); if (rhi->isFeatureSupported(QRhi::TextureArrays)) QVERIFY(texArrayMax > 1); + QVERIFY(uniBufRangeMax >= 224 * 4 * 4); QVERIFY(rhi->nativeHandles()); QVERIFY(rhi->profiler()); diff --git a/tests/manual/rhi/triquadcube/triquadcube.cpp b/tests/manual/rhi/triquadcube/triquadcube.cpp index 03ef049e000..12243df5658 100644 --- a/tests/manual/rhi/triquadcube/triquadcube.cpp +++ b/tests/manual/rhi/triquadcube/triquadcube.cpp @@ -190,6 +190,8 @@ void Window::customInit() qDebug("MaxThreadGroupX: %d", m_r->resourceLimit(QRhi::MaxThreadGroupX)); qDebug("MaxThreadGroupY: %d", m_r->resourceLimit(QRhi::MaxThreadGroupY)); qDebug("MaxThreadGroupZ: %d", m_r->resourceLimit(QRhi::MaxThreadGroupZ)); + qDebug("TextureArraySizeMax: %d", m_r->resourceLimit(QRhi::TextureArraySizeMax)); + qDebug("MaxUniformBufferRange: %d", m_r->resourceLimit(QRhi::MaxUniformBufferRange)); } void Window::customRelease()