summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-02-26 01:00:25 +0100
committerEdward Welbourne <edward.welbourne@qt.io>2020-02-26 18:39:21 +0100
commit75c0ffaf6d2b92cdf26092e01acdd5af4afeac97 (patch)
treebb9e85c21248790ec99b3665928872e39b14db64 /src/gui/rhi
parent4753d69d8934258de7fb64550e50a5cbb9b5603f (diff)
parent462c2745a5168a5b57381d05779b5d16aebe018e (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts: examples/network/bearermonitor/CMakeLists.txt examples/network/CMakeLists.txt src/corelib/tools/qlinkedlist.h src/sql/kernel/qsqldriver_p.h src/sql/kernel/qsqlresult_p.h src/widgets/kernel/qwidget.cpp src/widgets/kernel/qwidget_p.h tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp tests/auto/tools/moc/allmocs_baseline_in.json Change-Id: I21a3c34570ae79ea9d30107fae71759d7eac17d9
Diffstat (limited to 'src/gui/rhi')
-rw-r--r--src/gui/rhi/qrhi.cpp132
-rw-r--r--src/gui/rhi/qrhi_p.h13
-rw-r--r--src/gui/rhi/qrhid3d11.cpp15
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h1
-rw-r--r--src/gui/rhi/qrhigles2.cpp18
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h5
-rw-r--r--src/gui/rhi/qrhimetal.mm17
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h1
-rw-r--r--src/gui/rhi/qrhinull.cpp4
-rw-r--r--src/gui/rhi/qrhivulkan.cpp17
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h1
11 files changed, 205 insertions, 19 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index f0bf19bd91..7a0d53e1e4 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -577,6 +577,11 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
specifying a non-zero level in QRhiReadbackDescription leads to returning
an all-zero image. In practice this feature will be unsupported with OpenGL
ES 2.0, while it will likely be supported everywhere else.
+
+ \value TexelFetch Indicates that texelFetch() is available in shaders. In
+ practice this will be reported as unsupported with OpenGL ES 2.0 and OpenGL
+ 2.x contexts, because GLSL 100 es and versions before 130 do not support
+ this function.
*/
/*!
@@ -622,18 +627,27 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
is what some OpenGL ES implementations provide.
\value FramesInFlight The number of frames the backend may keep "in
- flight". The value has no relevance, and is unspecified, with backends like
- OpenGL and Direct3D 11. With backends like Vulkan or Metal, it is the
- responsibility of QRhi to block whenever starting a new frame and finding
- the CPU is already \c{N - 1} frames ahead of the GPU (because the command
- buffer submitted in frame no. \c{current} - \c{N} has not yet completed).
- The value N is what is returned from here, and is typically 2. This can be
- relevant to applications that integrate rendering done directly with the
- graphics API, as such rendering code may want to perform double (if the
- value is 2) buffering for resources, such as, buffers, similarly to the
- QRhi backends themselves. The current frame slot index (a value running 0,
- 1, .., N-1, then wrapping around) is retrievable from
- QRhi::currentFrameSlot().
+ flight": with backends like Vulkan or Metal, it is the responsibility of
+ QRhi to block whenever starting a new frame and finding the CPU is already
+ \c{N - 1} frames ahead of the GPU (because the command buffer submitted in
+ frame no. \c{current} - \c{N} has not yet completed). The value N is what
+ is returned from here, and is typically 2. This can be relevant to
+ applications that integrate rendering done directly with the graphics API,
+ as such rendering code may want to perform double (if the value is 2)
+ buffering for resources, such as, buffers, similarly to the QRhi backends
+ themselves. The current frame slot index (a value running 0, 1, .., N-1,
+ then wrapping around) is retrievable from QRhi::currentFrameSlot(). The
+ value is 1 for backends where the graphics API offers no such low level
+ control over the command submission process. Note that pipelining may still
+ happen even when this value is 1 (some backends, such as D3D11, are
+ designed to attempt to enable this, for instance, by using an update
+ strategy for uniform buffers that does not stall the pipeline), but that is
+ then not controlled by QRhi and so not reflected here in the API.
+
+ \value MaxAsyncReadbackFrames The number of \l{QRhi::endFrame()}{submitted}
+ frames (including the one that contains the readback) after which an
+ asynchronous texture or buffer readback is guaranteed to complete upon
+ \l{QRhi::beginFrame()}{starting a new frame}.
*/
/*!
@@ -1946,6 +1960,40 @@ quint64 QRhiResource::globalResourceId() const
*/
/*!
+ \class QRhiBuffer::NativeBuffer
+ \brief Contains information about the underlying native resources of a buffer.
+ */
+
+/*!
+ \variable QRhiBuffer::NativeBuffer::objects
+ \brief an array with pointers to the native object handles.
+
+ With OpenGL, the native handle is a GLuint value, so the elements in the \c
+ objects array are pointers to a GLuint. With Vulkan, the native handle is a
+ VkBuffer, so the elements of the array are pointers to a VkBuffer. With
+ Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
+ MTLBuffer pointer, respectively.
+
+ \note Pay attention to the fact that the elements are always pointers to
+ the native buffer handle type, even if the native type itself is a pointer.
+ */
+
+/*!
+ \variable QRhiBuffer::NativeBuffer::slotCount
+ \brief Specifies the number of valid elements in the objects array.
+
+ The value can be 0, 1, 2, or 3 in practice. 0 indicates that the QRhiBuffer
+ is not backed by any native buffer objects. This can happen with
+ QRhiBuffers with the usage UniformBuffer when the underlying API does not
+ support (or the backend chooses not to use) native uniform buffers. 1 is
+ commonly used for Immutable and Static types (but some backends may
+ differ). 2 or 3 is typical when the type is Dynamic (but some backends may
+ differ).
+
+ \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
+ */
+
+/*!
\internal
*/
QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_)
@@ -1974,6 +2022,46 @@ QRhiResource::Type QRhiBuffer::resourceType() const
*/
/*!
+ \return the underlying native resources for this buffer. The returned value
+ will be empty if exposing the underlying native resources is not supported by
+ the backend.
+
+ A QRhiBuffer may be backed by multiple native buffer objects, depending on
+ the type() and the QRhi backend in use. When this is the case, all of them
+ are returned in the objects array in the returned struct, with slotCount
+ specifying the number of native buffer objects. While
+ \l{QRhi::beginFrame()}{recording a frame}, QRhi::currentFrameSlot() can be
+ used to determine which of the native buffers QRhi is using for operations
+ that read or write from this QRhiBuffer within the frame being recorded.
+
+ In some cases a QRhiBuffer will not be backed by a native buffer object at
+ all. In this case slotCount will be set to 0 and no valid native objects
+ are returned. This is not an error, and is perfectly valid when a given
+ backend does not use native buffers for QRhiBuffers with certain types or
+ usages.
+
+ \note Be aware that QRhi backends may employ various buffer update
+ strategies. Unlike textures, where uploading image data always means
+ recording a buffer-to-image (or similar) copy command on the command
+ buffer, buffers, in particular Dynamic and UniformBuffer ones, can operate
+ in many different ways. For example, a QRhiBuffer with usage type
+ UniformBuffer may not even be backed by a native buffer object at all if
+ uniform buffers are not used or supported by a given backend and graphics
+ API. There are also differences to how data is written to the buffer and
+ the type of backing memory used, and, if host visible memory is involved,
+ when memory writes become available and visible. Therefore, in general it
+ is recommended to limit native buffer object access to vertex and index
+ buffers with types Static or Immutable, because these operate in a
+ relatively uniform manner with all backends.
+
+ \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
+ */
+QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
+{
+ return {};
+}
+
+/*!
\class QRhiRenderBuffer
\internal
\inmodule QtGui
@@ -4334,7 +4422,15 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *da
is supported only when the QRhi::ReadBackNonUniformBuffer feature is
reported as supported.
- \a readBackTexture(), QRhi::isFeatureSupported()
+ \note The asynchronous readback is guaranteed to have completed when one of
+ the following conditions is met: \l{QRhi::finish()}{finish()} has been
+ called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
+ including the frame that issued the readback operation, and the
+ \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
+ N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
+ QRhi::MaxAsyncReadbackFrames.
+
+ \sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
*/
void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
{
@@ -4425,6 +4521,16 @@ void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, co
happens with a byte ordered format. A \l{QRhiTexture::RGBA8}{RGBA8} texture
maps therefore to byte ordered QImage formats, such as,
QImage::Format_RGBA8888.
+
+ \note The asynchronous readback is guaranteed to have completed when one of
+ the following conditions is met: \l{QRhi::finish()}{finish()} has been
+ called; or, at least \c N frames have been \l{QRhi::endFrame()}{submitted},
+ including the frame that issued the readback operation, and the
+ \l{QRhi::beginFrame()}{recording of a new frame} has been started, where \c
+ N is the \l{QRhi::resourceLimit()}{resource limit value} returned for
+ QRhi::MaxAsyncReadbackFrames.
+
+ \sa readBackBuffer(), QRhi::resourceLimit()
*/
void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
{
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index d17112a241..8f53808d34 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -681,6 +681,11 @@ public:
};
Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
+ struct NativeBuffer {
+ const void *objects[3];
+ int slotCount;
+ };
+
QRhiResource::Type resourceType() const override;
Type type() const { return m_type; }
@@ -694,6 +699,8 @@ public:
virtual bool build() = 0;
+ virtual NativeBuffer nativeBuffer();
+
protected:
QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_);
Type m_type;
@@ -1430,7 +1437,8 @@ public:
BaseInstance,
TriangleFanTopology,
ReadBackNonUniformBuffer,
- ReadBackNonBaseMipLevel
+ ReadBackNonBaseMipLevel,
+ TexelFetch
};
enum BeginFrameFlag {
@@ -1447,7 +1455,8 @@ public:
TextureSizeMin = 1,
TextureSizeMax,
MaxColorAttachments,
- FramesInFlight
+ FramesInFlight,
+ MaxAsyncReadbackFrames
};
~QRhi();
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 75b90b6995..f7c7f4a9f2 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -464,6 +464,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::ReadBackNonBaseMipLevel:
return true;
+ case QRhi::TexelFetch:
+ return true;
default:
Q_UNREACHABLE();
return false;
@@ -480,7 +482,13 @@ int QRhiD3D11::resourceLimit(QRhi::ResourceLimit limit) const
case QRhi::MaxColorAttachments:
return 8;
case QRhi::FramesInFlight:
- return 2; // dummy
+ // From our perspective. What D3D does internally is another question
+ // (there could be pipelining, helped f.ex. by our MAP_DISCARD based
+ // uniform buffer update strategy), but that's out of our hands and
+ // does not concern us here.
+ return 1;
+ case QRhi::MaxAsyncReadbackFrames:
+ return 1;
default:
Q_UNREACHABLE();
return 0;
@@ -2378,6 +2386,11 @@ bool QD3D11Buffer::build()
return true;
}
+QRhiBuffer::NativeBuffer QD3D11Buffer::nativeBuffer()
+{
+ return { { &buffer }, 1 };
+}
+
ID3D11UnorderedAccessView *QD3D11Buffer::unorderedAccessView()
{
if (uav)
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index c3a4021241..04751397f7 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -64,6 +64,7 @@ struct QD3D11Buffer : public QRhiBuffer
~QD3D11Buffer();
void release() override;
bool build() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
ID3D11UnorderedAccessView *unorderedAccessView();
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 3b6c022399..4a442bc582 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -512,6 +512,8 @@ bool QRhiGles2::create(QRhi::Flags flags)
else
caps.nonBaseLevelFramebufferTexture = true;
+ caps.texelFetch = caps.ctxMajor >= 3; // 3.0 or ES 3.0
+
if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
f->glEnable(GL_POINT_SPRITE);
@@ -765,6 +767,8 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return !caps.gles || caps.properMapBuffer;
case QRhi::ReadBackNonBaseMipLevel:
return caps.nonBaseLevelFramebufferTexture;
+ case QRhi::TexelFetch:
+ return caps.texelFetch;
default:
Q_UNREACHABLE();
return false;
@@ -781,7 +785,11 @@ int QRhiGles2::resourceLimit(QRhi::ResourceLimit limit) const
case QRhi::MaxColorAttachments:
return caps.maxDrawBuffers;
case QRhi::FramesInFlight:
- return 2; // dummy
+ // From our perspective. What the GL impl does internally is another
+ // question, but that's out of our hands and does not concern us here.
+ return 1;
+ case QRhi::MaxAsyncReadbackFrames:
+ return 1;
default:
Q_UNREACHABLE();
return 0;
@@ -3293,6 +3301,14 @@ bool QGles2Buffer::build()
return true;
}
+QRhiBuffer::NativeBuffer QGles2Buffer::nativeBuffer()
+{
+ if (m_usage.testFlag(QRhiBuffer::UniformBuffer))
+ return { {}, 0 };
+
+ return { { &buffer }, 1 };
+}
+
QGles2RenderBuffer::QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags)
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 00caf40118..8b7d01532a 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -64,6 +64,7 @@ struct QGles2Buffer : public QRhiBuffer
~QGles2Buffer();
void release() override;
bool build() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
GLuint buffer = 0;
GLenum targetForDataOps;
@@ -778,7 +779,8 @@ public:
compute(false),
textureCompareMode(false),
properMapBuffer(false),
- nonBaseLevelFramebufferTexture(false)
+ nonBaseLevelFramebufferTexture(false),
+ texelFetch(false)
{ }
int ctxMajor;
int ctxMinor;
@@ -811,6 +813,7 @@ public:
uint textureCompareMode : 1;
uint properMapBuffer : 1;
uint nonBaseLevelFramebufferTexture : 1;
+ uint texelFetch : 1;
} caps;
QGles2SwapChain *currentSwapChain = nullptr;
QVector<GLint> supportedCompressedFormats;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 9e8f1ac096..48a562ef1d 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -562,6 +562,8 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::ReadBackNonBaseMipLevel:
return true;
+ case QRhi::TexelFetch:
+ return true;
default:
Q_UNREACHABLE();
return false;
@@ -579,6 +581,8 @@ int QRhiMetal::resourceLimit(QRhi::ResourceLimit limit) const
return 8;
case QRhi::FramesInFlight:
return QMTL_FRAMES_IN_FLIGHT;
+ case QRhi::MaxAsyncReadbackFrames:
+ return QMTL_FRAMES_IN_FLIGHT;
default:
Q_UNREACHABLE();
return 0;
@@ -2196,6 +2200,19 @@ bool QMetalBuffer::build()
return true;
}
+QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer()
+{
+ if (d->slotted) {
+ NativeBuffer b;
+ Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QMTL_FRAMES_IN_FLIGHT));
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ b.objects[i] = &d->buf[i];
+ b.slotCount = QMTL_FRAMES_IN_FLIGHT;
+ return b;
+ }
+ return { { &d->buf[0] }, 1 };
+}
+
QMetalRenderBuffer::QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags)
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags),
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index 58e93e2cdb..212b731b71 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -65,6 +65,7 @@ struct QMetalBuffer : public QRhiBuffer
~QMetalBuffer();
void release() override;
bool build() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
QMetalBufferData *d;
uint generation = 0;
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index 4c59900aa6..8c07e09b32 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -146,7 +146,9 @@ int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const
case QRhi::MaxColorAttachments:
return 8;
case QRhi::FramesInFlight:
- return 2; // dummy
+ return 1;
+ case QRhi::MaxAsyncReadbackFrames:
+ return 1;
default:
Q_UNREACHABLE();
return 0;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 84ca835392..d378e2a4ad 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -3990,6 +3990,8 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::ReadBackNonBaseMipLevel:
return true;
+ case QRhi::TexelFetch:
+ return true;
default:
Q_UNREACHABLE();
return false;
@@ -4007,6 +4009,8 @@ int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const
return int(physDevProperties.limits.maxColorAttachments);
case QRhi::FramesInFlight:
return QVK_FRAMES_IN_FLIGHT;
+ case QRhi::MaxAsyncReadbackFrames:
+ return QVK_FRAMES_IN_FLIGHT;
default:
Q_UNREACHABLE();
return 0;
@@ -5181,6 +5185,19 @@ bool QVkBuffer::build()
return true;
}
+QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer()
+{
+ if (m_type == Dynamic) {
+ NativeBuffer b;
+ Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QVK_FRAMES_IN_FLIGHT));
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ b.objects[i] = &buffers[i];
+ b.slotCount = QVK_FRAMES_IN_FLIGHT;
+ return b;
+ }
+ return { { &buffers[0] }, 1 };
+}
+
QVkRenderBuffer::QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, Flags flags)
: QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index d42b83b882..6322882569 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -76,6 +76,7 @@ struct QVkBuffer : public QRhiBuffer
~QVkBuffer();
void release() override;
bool build() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];