rhi: Add queries for vertex input/output limits

Mainly because we do have legacy code in the Qt 5 graphical effects that
tries to dynamically determine the max number of varyings. Make it
easier to port such code.

Change-Id: I846cab2c2fe7b4cd473b5ced0146ca36f1c8169b
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Strømme <christian.stromme@qt.io>
This commit is contained in:
Laszlo Agocs 2022-01-07 15:26:53 +01:00
parent 9d15854138
commit bfc713530a
10 changed files with 77 additions and 1 deletions

View File

@ -792,6 +792,16 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
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).
\value MaxVertexInputs The number of input attributes to the vertex shader.
The location in a QRhiVertexInputAttribute must be in range \c{[0,
MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
Elsewhere, typical values are 16, 31, or 32.
\value MaxVertexOutputs The maximum number of outputs (4 component vector
\c out variables) from the vertex shader. The value may be as low as 8 with
OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
a typical value is 32.
*/
/*!

View File

@ -1678,7 +1678,9 @@ public:
MaxThreadGroupY,
MaxThreadGroupZ,
TextureArraySizeMax,
MaxUniformBufferRange
MaxUniformBufferRange,
MaxVertexInputs,
MaxVertexOutputs
};
~QRhi();

View File

@ -124,6 +124,10 @@ QT_BEGIN_NAMESPACE
#define D3D11_1_UAV_SLOT_COUNT 64
#endif
#ifndef D3D11_VS_INPUT_REGISTER_COUNT
#define D3D11_VS_INPUT_REGISTER_COUNT 32
#endif
QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importParams)
: ofr(this),
deviceCurse(this)
@ -583,6 +587,10 @@ int QRhiD3D11::resourceLimit(QRhi::ResourceLimit limit) const
return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
case QRhi::MaxUniformBufferRange:
return 65536;
case QRhi::MaxVertexInputs:
return D3D11_VS_INPUT_REGISTER_COUNT;
case QRhi::MaxVertexOutputs:
return D3D11_VS_OUTPUT_REGISTER_COUNT;
default:
Q_UNREACHABLE();
return 0;

View File

@ -430,6 +430,18 @@ QT_BEGIN_NAMESPACE
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
#endif
#ifndef GL_MAX_VARYING_COMPONENTS
#define GL_MAX_VARYING_COMPONENTS 0x8B4B
#endif
#ifndef GL_MAX_VARYING_FLOATS
#define GL_MAX_VARYING_FLOATS 0x8B4B
#endif
#ifndef GL_MAX_VARYING_VECTORS
#define GL_MAX_VARYING_VECTORS 0x8DFC
#endif
/*!
Constructs a new QRhiGles2InitParams.
@ -849,6 +861,23 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
}
f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
if (caps.gles) {
f->glGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.maxVertexOutputs);
} else if (caps.ctxMajor >= 3) {
GLint components = 0;
f->glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &components);
caps.maxVertexOutputs = components / 4;
} else {
// OpenGL before 3.0 only has this, and not the same as
// MAX_VARYING_COMPONENTS strictly speaking, but will do.
GLint components = 0;
f->glGetIntegerv(GL_MAX_VARYING_FLOATS, &components);
if (components > 0)
caps.maxVertexOutputs = components / 4;
}
if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
f->glEnable(GL_POINT_SPRITE);
@ -1239,6 +1268,10 @@ int QRhiGles2::resourceLimit(QRhi::ResourceLimit limit) const
return 2048;
case QRhi::MaxUniformBufferRange:
return int(qMin<qint64>(INT_MAX, caps.maxUniformVectors * qint64(16)));
case QRhi::MaxVertexInputs:
return caps.maxVertexInputs;
case QRhi::MaxVertexOutputs:
return caps.maxVertexOutputs;
default:
Q_UNREACHABLE();
return 0;

View File

@ -930,6 +930,8 @@ public:
maxThreadGroupsY(0),
maxThreadGroupsZ(0),
maxUniformVectors(4096),
maxVertexInputs(8),
maxVertexOutputs(8),
msaaRenderBuffer(false),
multisampledTexture(false),
npotTextureFull(true),
@ -974,6 +976,8 @@ public:
int maxThreadGroupsY;
int maxThreadGroupsZ;
int maxUniformVectors;
int maxVertexInputs;
int maxVertexOutputs;
// Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not
// the same as multisample textures!
uint msaaRenderBuffer : 1;

View File

@ -654,6 +654,10 @@ int QRhiMetal::resourceLimit(QRhi::ResourceLimit limit) const
return 2048;
case QRhi::MaxUniformBufferRange:
return 65536;
case QRhi::MaxVertexInputs:
return 31;
case QRhi::MaxVertexOutputs:
return 15; // use the minimum from MTLGPUFamily1/2/3
default:
Q_UNREACHABLE();
return 0;

View File

@ -165,6 +165,10 @@ int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const
return 2048;
case QRhi::MaxUniformBufferRange:
return 65536;
case QRhi::MaxVertexInputs:
return 32;
case QRhi::MaxVertexOutputs:
return 32;
default:
Q_UNREACHABLE();
return 0;

View File

@ -4336,6 +4336,10 @@ int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const
return int(physDevProperties.limits.maxImageArrayLayers);
case QRhi::MaxUniformBufferRange:
return int(qMin<uint32_t>(INT_MAX, physDevProperties.limits.maxUniformBufferRange));
case QRhi::MaxVertexInputs:
return physDevProperties.limits.maxVertexInputAttributes;
case QRhi::MaxVertexOutputs:
return physDevProperties.limits.maxVertexOutputComponents / 4;
default:
Q_UNREACHABLE();
return 0;

View File

@ -353,6 +353,9 @@ void tst_QRhi::create()
const int framesInFlight = rhi->resourceLimit(QRhi::FramesInFlight);
const int texArrayMax = rhi->resourceLimit(QRhi::TextureArraySizeMax);
const int uniBufRangeMax = rhi->resourceLimit(QRhi::MaxUniformBufferRange);
const int maxVertexInputs = rhi->resourceLimit(QRhi::MaxVertexInputs);
const int maxVertexOutputs = rhi->resourceLimit(QRhi::MaxVertexOutputs);
QVERIFY(texMin >= 1);
QVERIFY(texMax >= texMin);
QVERIFY(maxAtt >= 1);
@ -360,6 +363,8 @@ void tst_QRhi::create()
if (rhi->isFeatureSupported(QRhi::TextureArrays))
QVERIFY(texArrayMax > 1);
QVERIFY(uniBufRangeMax >= 224 * 4 * 4);
QVERIFY(maxVertexInputs >= 8);
QVERIFY(maxVertexOutputs >= 8);
QVERIFY(rhi->nativeHandles());

View File

@ -177,6 +177,8 @@ void Window::customInit()
qDebug("MaxThreadGroupZ: %d", m_r->resourceLimit(QRhi::MaxThreadGroupZ));
qDebug("TextureArraySizeMax: %d", m_r->resourceLimit(QRhi::TextureArraySizeMax));
qDebug("MaxUniformBufferRange: %d", m_r->resourceLimit(QRhi::MaxUniformBufferRange));
qDebug("MaxVertexInputs: %d", m_r->resourceLimit(QRhi::MaxVertexInputs));
qDebug("MaxVertexOutputs: %d", m_r->resourceLimit(QRhi::MaxVertexOutputs));
// With Vulkan at least we should see some details from the memory allocator.
qDebug() << m_r->graphicsMemoryAllocationStatistics();