summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-11-09 13:18:15 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2021-11-10 13:31:05 +0100
commita8be40bd64b9258334d6936b1775bc6631fd158d (patch)
tree0a6e2f2a53db8348c118f0240cf3108e9e216c45
parentcdf784a1c7bf9548a1aed8cbfe376b817d13640a (diff)
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>
-rw-r--r--src/gui/rhi/qrhi.cpp15
-rw-r--r--src/gui/rhi/qrhi_p.h3
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2
-rw-r--r--src/gui/rhi/qrhigles2.cpp35
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h2
-rw-r--r--src/gui/rhi/qrhimetal.mm2
-rw-r--r--src/gui/rhi/qrhinull.cpp2
-rw-r--r--src/gui/rhi/qrhivulkan.cpp2
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp2
-rw-r--r--tests/manual/rhi/triquadcube/triquadcube.cpp2
10 files changed, 66 insertions, 1 deletions
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<qint64>(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<uint32_t>(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()