summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <[email protected]>2024-02-12 16:14:40 +0100
committerLaszlo Agocs <[email protected]>2024-02-14 10:43:07 +0100
commit5db954f944a5b18626b719a7078f4be7d2e65c51 (patch)
tree8c3a55a5f676a989348855d0218510a1e9ec6a73
parent5113e578653431728f3861c91a2ce1338cffadaf (diff)
rhi: Make sample count selection logic be closer to Qt 5
Backport specifically for Qt 6.5. Fixes: QTBUG-119148 Change-Id: Ia119ab3ced9da08853c608aa256bde08a6fd8d4e Reviewed-by: Andy Nichols <[email protected]> Reviewed-by: Qt CI Bot <[email protected]> (cherry picked from commit bb1d9bab36d779e595a924e3218d4066d84fca38) Reviewed-by: Tor Arne Vestbø <[email protected]> Reviewed-by: Laszlo Agocs <[email protected]> (cherry picked from commit 153ca77c263d9a0f515402ad35806c68aebc33be)
-rw-r--r--src/gui/rhi/qrhi.cpp35
-rw-r--r--src/gui/rhi/qrhi_p_p.h2
-rw-r--r--src/gui/rhi/qrhid3d11.cpp18
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h2
-rw-r--r--src/gui/rhi/qrhigles2.cpp11
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h1
-rw-r--r--src/gui/rhi/qrhimetal.mm11
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h2
-rw-r--r--src/gui/rhi/qrhivulkan.cpp20
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h2
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp63
11 files changed, 114 insertions, 53 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index c3c29895648..d4f6e2ed61d 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -5498,6 +5498,41 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
return true;
}
+int QRhiImplementation::effectiveSampleCount(int sampleCount) const
+{
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ const int s = qBound(1, sampleCount, 64);
+ const QList<int> supported = supportedSampleCounts();
+ int result = 1;
+
+ // Stay compatible with Qt 5 in that requesting an unsupported sample count
+ // is not an error (although we still do a categorized debug print about
+ // this), and rather a supported value, preferably a close one, not just 1,
+ // is used instead. This is actually deviating from Qt 5 as that performs a
+ // clamping only and does not handle cases such as when sample count 2 is
+ // not supported but 4 is. (OpenGL handles things like that gracefully,
+ // other APIs may not, so improve this by picking the next largest, or in
+ // absence of that, the largest value; this with the goal to not reduce
+ // quality by rather picking a larger-than-requested value than a smaller one)
+
+ for (int i = 0, ie = supported.count(); i != ie; ++i) {
+ // assumes the 'supported' list is sorted
+ if (supported[i] >= s) {
+ result = supported[i];
+ break;
+ }
+ }
+
+ if (result != s) {
+ if (result == 1 && !supported.isEmpty())
+ result = supported.last();
+ qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
+ sampleCount, result);
+ }
+
+ return result;
+}
+
/*!
\internal
*/
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index 50a3d9bab79..6f837ad28fe 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -229,6 +229,8 @@ public:
QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
+ int effectiveSampleCount(int sampleCount) const;
+
QRhi *q;
static const int MAX_SHADER_CACHE_ENTRIES = 128;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 7dc3af01c38..20ceeaf254a 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -399,19 +399,13 @@ QList<int> QRhiD3D11::supportedSampleCounts() const
return { 1, 2, 4, 8 };
}
-DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleCount(int sampleCount) const
+DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleDesc(int sampleCount) const
{
DXGI_SAMPLE_DESC desc;
desc.Count = 1;
desc.Quality = 0;
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- int s = qBound(1, sampleCount, 64);
-
- if (!supportedSampleCounts().contains(s)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return desc;
- }
+ const int s = effectiveSampleCount(sampleCount);
desc.Count = UINT(s);
if (s > 1)
@@ -3003,7 +2997,7 @@ bool QD3D11RenderBuffer::create()
return false;
QRHI_RES_RHI(QRhiD3D11);
- sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = UINT(m_pixelSize.width());
@@ -3174,7 +3168,7 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
QRHI_RES_RHI(QRhiD3D11);
dxgiFormat = toD3DTextureFormat(m_format, m_flags);
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
- sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
if (sampleDesc.Count > 1) {
if (isCube) {
qWarning("Cubemap texture cannot be multisample");
@@ -4345,7 +4339,7 @@ bool QD3D11GraphicsPipeline::create()
rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
rastDesc.DepthClipEnable = true;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
- rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1;
+ rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
if (FAILED(hr)) {
qWarning("Failed to create rasterizer state: %s",
@@ -4974,7 +4968,7 @@ bool QD3D11SwapChain::createOrResize()
swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
if (!swapChain) {
- sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
colorFormat = DEFAULT_FORMAT;
srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index c4d9036a5f1..164ceacde47 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -720,7 +720,7 @@ public:
bool offsetOnlyChange);
void resetShaderResources();
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
- DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
+ DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
void finishActiveReadbacks();
void reportLiveObjects(ID3D11Device *device);
void clearShaderCache();
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 7995969b585..5509abb50f2 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -1035,17 +1035,6 @@ QList<int> QRhiGles2::supportedSampleCounts() const
return supportedSampleCountList;
}
-int QRhiGles2::effectiveSampleCount(int sampleCount) const
-{
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- const int s = qBound(1, sampleCount, 64);
- if (!supportedSampleCounts().contains(s)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return 1;
- }
- return s;
-}
-
QRhiSwapChain *QRhiGles2::createSwapChain()
{
return new QGles2SwapChain(this);
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index d370cb1fde3..2e107444d24 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -854,7 +854,6 @@ public:
QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
void enqueueBarriersForPass(QGles2CommandBuffer *cbD);
- int effectiveSampleCount(int sampleCount) const;
QByteArray shaderSource(const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion);
bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion);
bool linkProgram(GLuint program);
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 206b89a8003..e04136d0f15 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -610,17 +610,6 @@ QVector<int> QRhiMetal::supportedSampleCounts() const
return caps.supportedSampleCounts;
}
-int QRhiMetal::effectiveSampleCount(int sampleCount) const
-{
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- const int s = qBound(1, sampleCount, 64);
- if (!supportedSampleCounts().contains(s)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return 1;
- }
- return s;
-}
-
QRhiSwapChain *QRhiMetal::createSwapChain()
{
return new QMetalSwapChain(this);
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index cdb404afb90..44dbc04152e 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -453,7 +453,7 @@ public:
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
bool offsetOnlyChange,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]);
- int effectiveSampleCount(int sampleCount) const;
+
struct TessDrawArgs {
QMetalCommandBuffer *cbD;
enum {
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 18179c1f7fd..c6ecd8a2fba 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -3722,18 +3722,12 @@ QList<int> QRhiVulkan::supportedSampleCounts() const
return result;
}
-VkSampleCountFlagBits QRhiVulkan::effectiveSampleCount(int sampleCount)
+VkSampleCountFlagBits QRhiVulkan::effectiveSampleCountBits(int sampleCount)
{
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- sampleCount = qBound(1, sampleCount, 64);
-
- if (!supportedSampleCounts().contains(sampleCount)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return VK_SAMPLE_COUNT_1_BIT;
- }
+ const int s = effectiveSampleCount(sampleCount);
for (const auto &qvk_sampleCount : qvk_sampleCounts) {
- if (qvk_sampleCount.count == sampleCount)
+ if (qvk_sampleCount.count == s)
return qvk_sampleCount.mask;
}
@@ -5753,7 +5747,7 @@ bool QVkRenderBuffer::create()
return false;
QRHI_RES_RHI(QRhiVulkan);
- samples = rhiD->effectiveSampleCount(m_sampleCount);
+ samples = rhiD->effectiveSampleCountBits(m_sampleCount);
switch (m_type) {
case QRhiRenderBuffer::Color:
@@ -5894,7 +5888,7 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
qWarning("Too many mip levels (%d, max is %d), truncating mip chain", mipLevelCount, maxLevels);
mipLevelCount = maxLevels;
}
- samples = rhiD->effectiveSampleCount(m_sampleCount);
+ samples = rhiD->effectiveSampleCountBits(m_sampleCount);
if (samples > VK_SAMPLE_COUNT_1_BIT) {
if (isCube) {
qWarning("Cubemap texture cannot be multisample");
@@ -6990,7 +6984,7 @@ bool QVkGraphicsPipeline::create()
VkPipelineMultisampleStateCreateInfo msInfo = {};
msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- msInfo.rasterizationSamples = rhiD->effectiveSampleCount(m_sampleCount);
+ msInfo.rasterizationSamples = rhiD->effectiveSampleCountBits(m_sampleCount);
pipelineInfo.pMultisampleState = &msInfo;
VkPipelineDepthStencilStateCreateInfo dsInfo = {};
@@ -7380,7 +7374,7 @@ bool QVkSwapChain::ensureSurface()
}
}
- samples = rhiD->effectiveSampleCount(m_sampleCount);
+ samples = rhiD->effectiveSampleCountBits(m_sampleCount);
quint32 presModeCount = 0;
rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR(rhiD->physDev, surface, &presModeCount, nullptr);
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index af826b2ac5f..dade046c86c 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -753,7 +753,7 @@ public:
void releaseSwapChainResources(QRhiSwapChain *swapChain);
VkFormat optimalDepthStencilFormat();
- VkSampleCountFlagBits effectiveSampleCount(int sampleCount);
+ VkSampleCountFlagBits effectiveSampleCountBits(int sampleCount);
bool createDefaultRenderPass(QVkRenderPassDescriptor *rpD,
bool hasDepthStencil,
VkSampleCountFlagBits samples,
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
index c3e3c09369b..28385ec461d 100644
--- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -86,6 +86,8 @@ private slots:
void renderPassDescriptorCompatibility();
void renderPassDescriptorClone_data();
void renderPassDescriptorClone();
+ void textureWithSampleCount_data();
+ void textureWithSampleCount();
void renderToTextureSimple_data();
void renderToTextureSimple();
@@ -293,8 +295,13 @@ void tst_QRhi::create()
QVERIFY(resUpd);
resUpd->release();
- QVERIFY(!rhi->supportedSampleCounts().isEmpty());
- QVERIFY(rhi->supportedSampleCounts().contains(1));
+ const QVector<int> supportedSampleCounts = rhi->supportedSampleCounts();
+ QVERIFY(!supportedSampleCounts.isEmpty());
+ QVERIFY(supportedSampleCounts.contains(1));
+ for (int i = 1; i < supportedSampleCounts.count(); ++i) {
+ // Verify the list is sorted. Internally the backends rely on this.
+ QVERIFY(supportedSampleCounts[i] > supportedSampleCounts[i - 1]);
+ }
QVERIFY(rhi->ubufAlignment() > 0);
QCOMPARE(rhi->ubufAligned(123), aligned(123, rhi->ubufAlignment()));
@@ -4411,6 +4418,58 @@ void tst_QRhi::pipelineCache()
}
}
+void tst_QRhi::textureWithSampleCount_data()
+{
+ rhiTestData();
+}
+
+void tst_QRhi::textureWithSampleCount()
+{
+ QFETCH(QRhi::Implementation, impl);
+ QFETCH(QRhiInitParams *, initParams);
+
+ QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
+ if (!rhi)
+ QSKIP("QRhi could not be created, skipping testing renderpass descriptors");
+
+ if (!rhi->isFeatureSupported(QRhi::MultisampleTexture))
+ QSKIP("No multisample texture support with this backend, skipping");
+
+ {
+ QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1));
+ QVERIFY(tex->create());
+ }
+
+ // Ensure 0 is accepted the same way as 1.
+ {
+ QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 0));
+ QVERIFY(tex->create());
+ }
+
+ // Note that we intentionally do not pass in RenderTarget in flags. Where
+ // matters for create(), the backend is expected to act as if it was
+ // specified whenever samples > 1. (in practice it does not make sense to not
+ // have the flag for an msaa texture, but we only care about create() here)
+
+ // Pick the commonly supported sample count of 4.
+ {
+ QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 4));
+ QVERIFY(tex->create());
+ }
+
+ // Now a bogus value that is typically in-between the supported values.
+ {
+ QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 3));
+ QVERIFY(tex->create());
+ }
+
+ // Now a bogus value that is out of range.
+ {
+ QScopedPointer<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 123));
+ QVERIFY(tex->create());
+ }
+}
+
void tst_QRhi::textureImportOpenGL()
{
#ifdef TST_GL