rhi: Expose the maximum uniform buffer range limit

Pick-to: 6.2
Task-number: QTBUG-97715
Change-Id: I7f0a52c410b9b77f735fb3b7fd33141674bb0cda
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2021-11-09 13:18:15 +01:00
parent cdf784a1c7
commit a8be40bd64
10 changed files with 66 additions and 1 deletions

View File

@ -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)

View File

@ -1612,7 +1612,8 @@ public:
MaxThreadGroupX,
MaxThreadGroupY,
MaxThreadGroupZ,
TextureArraySizeMax
TextureArraySizeMax,
MaxUniformBufferRange
};
~QRhi();

View File

@ -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;

View File

@ -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<qint64>(INT_MAX, caps.maxUniformVectors * qint64(16)));
default:
Q_UNREACHABLE();
return 0;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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<uint32_t>(INT_MAX, physDevProperties.limits.maxUniformBufferRange));
default:
Q_UNREACHABLE();
return 0;

View File

@ -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());

View File

@ -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()