summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-02-20 11:03:16 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-02-21 09:15:18 +0100
commit2940c375e40687f5758d173adceaee212239e2ca (patch)
tree3f75011b37d9d0e205e4d11d6a85dc38fa9b8f51 /src/gui/rhi
parent79b605d285d006ff7434fc813effa3479138b952 (diff)
rhi: Allow querying the native buffer objects behind a QRhiBuffer
Modeled after QRhiTexture's NativeTexture query. This becomes valuable in advanced cases of integrating external native rendering code with Qt Quick(3D), because it allows using (typically vertex and index) buffers created by Quick(3D) in the custom renderer as well, without having to duplicate the content by manually creating native buffers with the same vertex and index data. Change-Id: I659193345fa1dfe6221b898043f0b75ba649d296 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r--src/gui/rhi/qrhi.cpp74
-rw-r--r--src/gui/rhi/qrhi_p.h7
-rw-r--r--src/gui/rhi/qrhid3d11.cpp5
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h1
-rw-r--r--src/gui/rhi/qrhigles2.cpp8
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h1
-rw-r--r--src/gui/rhi/qrhimetal.mm13
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp13
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h1
10 files changed, 124 insertions, 0 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 584fbb263d..7a0d53e1e4 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -1960,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_)
@@ -1988,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
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index be96ebbf05..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;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 221ec6e6e5..f7c7f4a9f2 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -2386,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 df0b255bed..feeb65137a 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -3303,6 +3303,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 e10da2a342..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;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index b0813bfc77..48a562ef1d 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -2200,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/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 5d6e9b21bc..d378e2a4ad 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -5185,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];