summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2019-10-06 17:25:06 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2019-10-09 17:15:05 +0200
commitdd105fab8d8b4bd39654e7e268e6782e53cce2de (patch)
tree928e7ae7ca67c135e92f9b759b2efbccacf5c7ba /src
parent9baf69c765c446b7c8f069ebdd50910877a7d0f8 (diff)
rhi: Autotest rendering a triangle
Also improve (docs and runtime checks) and test the minimum set of required data to create a graphics pipeline. Task-number: QTBUG-78971 Change-Id: If5c14f1ab1ff3cf70f168fde585f05fc9d28ec91 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/gui/rhi/qrhi.cpp48
-rw-r--r--src/gui/rhi/qrhi_p.h1
-rw-r--r--src/gui/rhi/qrhi_p_p.h2
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2
-rw-r--r--src/gui/rhi/qrhigles2.cpp3
-rw-r--r--src/gui/rhi/qrhimetal.mm2
-rw-r--r--src/gui/rhi/qrhinull.cpp4
-rw-r--r--src/gui/rhi/qrhivulkan.cpp3
8 files changed, 61 insertions, 4 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 57c466678e..dabad35688 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -3084,9 +3084,13 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
\inmodule QtGui
\brief Graphics pipeline state resource.
+ \note Setting the shader stages is mandatory. There must be at least one
+ stage, and there must be a vertex stage.
+
\note Setting the shader resource bindings is mandatory. The referenced
QRhiShaderResourceBindings must already be built by the time build() is
- called.
+ called. Associating with a QRhiShaderResourceBindings that has no bindings
+ is also valid, as long as no shader in any stage expects any resources.
\note Setting the render pass descriptor is mandatory. To obtain a
QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
@@ -3095,8 +3099,6 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
\note Setting the vertex input layout is mandatory.
- \note Setting the shader stages is mandatory.
-
\note sampleCount() defaults to 1 and must match the sample count of the
render target's color and depth stencil attachments.
@@ -3912,6 +3914,46 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
return approxSize;
}
+bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
+{
+ if (ps->cbeginShaderStages() == ps->cendShaderStages()) {
+ qWarning("Cannot build a graphics pipeline without any stages");
+ return false;
+ }
+
+ bool hasVertexStage = false;
+ for (auto it = ps->cbeginShaderStages(), itEnd = ps->cendShaderStages(); it != itEnd; ++it) {
+ if (!it->shader().isValid()) {
+ qWarning("Empty shader passed to graphics pipeline");
+ return false;
+ }
+ if (it->type() == QRhiShaderStage::Vertex) {
+ hasVertexStage = true;
+ const QRhiVertexInputLayout inputLayout = ps->vertexInputLayout();
+ if (inputLayout.cbeginAttributes() == inputLayout.cendAttributes()) {
+ qWarning("Vertex stage present without any vertex inputs");
+ return false;
+ }
+ }
+ }
+ if (!hasVertexStage) {
+ qWarning("Cannot build a graphics pipeline without a vertex stage");
+ return false;
+ }
+
+ if (!ps->renderPassDescriptor()) {
+ qWarning("Cannot build a graphics pipeline without a QRhiRenderPassDescriptor");
+ return false;
+ }
+
+ if (!ps->shaderResourceBindings()) {
+ qWarning("Cannot build a graphics pipeline without QRhiShaderResourceBindings");
+ return false;
+ }
+
+ return true;
+}
+
/*!
\internal
*/
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index bfcc1d39f5..907924c788 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -72,7 +72,6 @@ class QRhiCommandBuffer;
class QRhiResourceUpdateBatch;
class QRhiResourceUpdateBatchPrivate;
class QRhiProfiler;
-class QRhiShaderResourceBindingPrivate;
class Q_GUI_EXPORT QRhiDepthStencilClearValue
{
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index cc14293580..baffe28202 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -205,6 +205,8 @@ public:
cleanupCallbacks.append(callback);
}
+ bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
+
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 096a8c2756..57ebb2909f 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -3491,6 +3491,8 @@ bool QD3D11GraphicsPipeline::build()
release();
QRHI_RES_RHI(QRhiD3D11);
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
D3D11_RASTERIZER_DESC rastDesc;
memset(&rastDesc, 0, sizeof(rastDesc));
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index ca1c91499d..4163ab1e79 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -3690,6 +3690,9 @@ bool QGles2GraphicsPipeline::build()
if (!rhiD->ensureContext())
return false;
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
+
drawMode = toGlTopology(m_topology);
program = rhiD->f->glCreateProgram();
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 694882ab93..ef5ab696d7 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -3139,6 +3139,8 @@ bool QMetalGraphicsPipeline::build()
release();
QRHI_RES_RHI(QRhiMetal);
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
// same binding space for vertex and constant buffers - work it around
const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, m_shaderResourceBindings)->maxBinding + 1;
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index d78b5e20c5..2eb55e705b 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -805,6 +805,10 @@ void QNullGraphicsPipeline::release()
bool QNullGraphicsPipeline::build()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
+
return true;
}
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 0d364dd9fc..fca2125f10 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -5886,6 +5886,9 @@ bool QVkGraphicsPipeline::build()
release();
QRHI_RES_RHI(QRhiVulkan);
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
+
if (!rhiD->ensurePipelineCache())
return false;