From 53599592e09edd215bfa1eaa7e6f3a9f3fc50ae6 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 22 Mar 2019 09:55:03 +0100 Subject: Introduce the Qt graphics abstraction as private QtGui helpers Comes with backends for Vulkan, Metal, Direct3D 11.1, and OpenGL (ES). All APIs are private for now. Shader conditioning (i.e. generating a QRhiShader in memory or on disk from some shader source code) is done via the tools and APIs provided by qt-labs/qtshadertools. The OpenGL support follows the cross-platform tradition of requiring ES 2.0 only, while optionally using some (ES) 3.x features. It can operate in core profile contexts as well. Task-number: QTBUG-70287 Change-Id: I246f2e36d562e404012c05db2aa72487108aa7cc Reviewed-by: Lars Knoll --- src/gui/rhi/qrhi_p.h | 1375 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1375 insertions(+) create mode 100644 src/gui/rhi/qrhi_p.h (limited to 'src/gui/rhi/qrhi_p.h') diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h new file mode 100644 index 0000000000..a0f57819e4 --- /dev/null +++ b/src/gui/rhi/qrhi_p.h @@ -0,0 +1,1375 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Gui module +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRHI_H +#define QRHI_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWindow; +class QRhiImplementation; +class QRhiBuffer; +class QRhiRenderBuffer; +class QRhiTexture; +class QRhiSampler; +class QRhiCommandBuffer; +class QRhiResourceUpdateBatch; +class QRhiResourceUpdateBatchPrivate; +class QRhiProfiler; +class QRhiShaderResourceBindingPrivate; + +class Q_GUI_EXPORT QRhiDepthStencilClearValue +{ +public: + QRhiDepthStencilClearValue() = default; + QRhiDepthStencilClearValue(float d, quint32 s); + + float depthClearValue() const { return m_d; } + void setDepthClearValue(float d) { m_d = d; } + + quint32 stencilClearValue() const { return m_s; } + void setStencilClearValue(quint32 s) { m_s = s; } + +private: + float m_d = 1.0f; + quint32 m_s = 0; +}; + +Q_DECLARE_TYPEINFO(QRhiDepthStencilClearValue, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiDepthStencilClearValue &v, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDepthStencilClearValue &); +#endif + +class Q_GUI_EXPORT QRhiViewport +{ +public: + QRhiViewport() = default; + QRhiViewport(float x, float y, float w, float h, float minDepth = 0.0f, float maxDepth = 1.0f); + + std::array viewport() const { return m_rect; } + void setViewport(float x, float y, float w, float h) { + m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h; + } + + float minDepth() const { return m_minDepth; } + void setMinDepth(float minDepth) { m_minDepth = minDepth; } + + float maxDepth() const { return m_maxDepth; } + void setMaxDepth(float maxDepth) { m_maxDepth = maxDepth; } + +private: + std::array m_rect { { 0.0f, 0.0f, 0.0f, 0.0f } }; + float m_minDepth = 0.0f; + float m_maxDepth = 1.0f; +}; + +Q_DECLARE_TYPEINFO(QRhiViewport, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiViewport &v, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiViewport &); +#endif + +class Q_GUI_EXPORT QRhiScissor +{ +public: + QRhiScissor() = default; + QRhiScissor(int x, int y, int w, int h); + + std::array scissor() const { return m_rect; } + void setScissor(int x, int y, int w, int h) { + m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h; + } + +private: + std::array m_rect { { 0, 0, 0, 0 } }; +}; + +Q_DECLARE_TYPEINFO(QRhiScissor, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiScissor &v, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiScissor &); +#endif + +class Q_GUI_EXPORT QRhiVertexInputBinding +{ +public: + enum Classification { + PerVertex, + PerInstance + }; + + QRhiVertexInputBinding() = default; + QRhiVertexInputBinding(quint32 stride, Classification cls = PerVertex, int stepRate = 1); + + quint32 stride() const { return m_stride; } + void setStride(quint32 s) { m_stride = s; } + + Classification classification() const { return m_classification; } + void setClassification(Classification c) { m_classification = c; } + + int instanceStepRate() const { return m_instanceStepRate; } + void setInstanceStepRate(int rate) { m_instanceStepRate = rate; } + +private: + quint32 m_stride = 0; + Classification m_classification = PerVertex; + int m_instanceStepRate = 1; +}; + +Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiVertexInputBinding &v, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputBinding &); +#endif + +class Q_GUI_EXPORT QRhiVertexInputAttribute +{ +public: + enum Format { + Float4, + Float3, + Float2, + Float, + UNormByte4, + UNormByte2, + UNormByte + }; + + QRhiVertexInputAttribute() = default; + QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset); + + int binding() const { return m_binding; } + void setBinding(int b) { m_binding = b; } + + int location() const { return m_location; } + void setLocation(int loc) { m_location = loc; } + + Format format() const { return m_format; } + void setFormt(Format f) { m_format = f; } + + quint32 offset() const { return m_offset; } + void setOffset(quint32 ofs) { m_offset = ofs; } + +private: + int m_binding = 0; + int m_location = 0; + Format m_format = Float4; + quint32 m_offset = 0; +}; + +Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiVertexInputAttribute &v, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputAttribute &); +#endif + +class Q_GUI_EXPORT QRhiVertexInputLayout +{ +public: + QRhiVertexInputLayout() = default; + + QVector bindings() const { return m_bindings; } + void setBindings(const QVector &v) { m_bindings = v; } + + QVector attributes() const { return m_attributes; } + void setAttributes(const QVector &v) { m_attributes = v; } + +private: + QVector m_bindings; + QVector m_attributes; +}; + +Q_DECLARE_TYPEINFO(QRhiVertexInputLayout, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiVertexInputLayout &v, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &); +#endif + +class Q_GUI_EXPORT QRhiGraphicsShaderStage +{ +public: + enum Type { + Vertex, + Fragment + }; + + QRhiGraphicsShaderStage() = default; + QRhiGraphicsShaderStage(Type type, const QShader &shader, + QShader::Variant v = QShader::StandardShader); + + Type type() const { return m_type; } + void setType(Type t) { m_type = t; } + + QShader shader() const { return m_shader; } + void setShader(const QShader &s) { m_shader = s; } + + QShader::Variant shaderVariant() const { return m_shaderVariant; } + void setShaderVariant(QShader::Variant v) { m_shaderVariant = v; } + +private: + Type m_type = Vertex; + QShader m_shader; + QShader::Variant m_shaderVariant = QShader::StandardShader; +}; + +Q_DECLARE_TYPEINFO(QRhiGraphicsShaderStage, Q_MOVABLE_TYPE); + +Q_GUI_EXPORT bool operator==(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiGraphicsShaderStage &s, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiGraphicsShaderStage &); +#endif + +class Q_GUI_EXPORT QRhiShaderResourceBinding +{ +public: + enum Type { + UniformBuffer, + SampledTexture + }; + + enum StageFlag { + VertexStage = 1 << 0, + FragmentStage = 1 << 1 + }; + Q_DECLARE_FLAGS(StageFlags, StageFlag) + + QRhiShaderResourceBinding(); + QRhiShaderResourceBinding(const QRhiShaderResourceBinding &other); + QRhiShaderResourceBinding &operator=(const QRhiShaderResourceBinding &other); + ~QRhiShaderResourceBinding(); + void detach(); + + bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const; + + static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf); + static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size); + static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, int size); + static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler); + +private: + QRhiShaderResourceBindingPrivate *d; + friend class QRhiShaderResourceBindingPrivate; + friend Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &, const QRhiShaderResourceBinding &) Q_DECL_NOTHROW; + friend Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &, const QRhiShaderResourceBinding &) Q_DECL_NOTHROW; + friend Q_GUI_EXPORT uint qHash(const QRhiShaderResourceBinding &, uint) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM + friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &); +#endif +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags) + +Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiShaderResourceBinding &b, uint seed = 0) Q_DECL_NOTHROW; +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &); +#endif + +class Q_GUI_EXPORT QRhiColorAttachment +{ +public: + QRhiColorAttachment() = default; + QRhiColorAttachment(QRhiTexture *texture); + QRhiColorAttachment(QRhiRenderBuffer *renderBuffer); + + QRhiTexture *texture() const { return m_texture; } + void setTexture(QRhiTexture *tex) { m_texture = tex; } + + QRhiRenderBuffer *renderBuffer() const { return m_renderBuffer; } + void setRenderBuffer(QRhiRenderBuffer *rb) { m_renderBuffer = rb; } + + int layer() const { return m_layer; } + void setLayer(int layer) { m_layer = layer; } + + int level() const { return m_level; } + void setLevel(int level) { m_level = level; } + + QRhiTexture *resolveTexture() const { return m_resolveTexture; } + void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; } + + int resolveLayer() const { return m_resolveLayer; } + void setResolveLayer(int layer) { m_resolveLayer = layer; } + + int resolveLevel() const { return m_resolveLevel; } + void setResolveLevel(int level) { m_resolveLevel = level; } + +private: + QRhiTexture *m_texture = nullptr; + QRhiRenderBuffer *m_renderBuffer = nullptr; + int m_layer = 0; + int m_level = 0; + QRhiTexture *m_resolveTexture = nullptr; + int m_resolveLayer = 0; + int m_resolveLevel = 0; +}; + +Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiTextureRenderTargetDescription +{ +public: + QRhiTextureRenderTargetDescription() = default; + QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment); + QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer); + QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture); + + QVector colorAttachments() const { return m_colorAttachments; } + void setColorAttachments(const QVector &att) { m_colorAttachments = att; } + + QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; } + void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; } + + QRhiTexture *depthTexture() const { return m_depthTexture; } + void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; } + +private: + QVector m_colorAttachments; + QRhiRenderBuffer *m_depthStencilBuffer = nullptr; + QRhiTexture *m_depthTexture = nullptr; +}; + +Q_DECLARE_TYPEINFO(QRhiTextureRenderTargetDescription, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiTextureSubresourceUploadDescription +{ +public: + QRhiTextureSubresourceUploadDescription() = default; + QRhiTextureSubresourceUploadDescription(const QImage &image); + QRhiTextureSubresourceUploadDescription(const void *data, int size); + + QImage image() const { return m_image; } + void setImage(const QImage &image) { m_image = image; } + + QByteArray data() const { return m_data; } + void setData(const QByteArray &data) { m_data = data; } + + QPoint destinationTopLeft() const { return m_destinationTopLeft; } + void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; } + + QSize sourceSize() const { return m_sourceSize; } + void setSourceSize(const QSize &size) { m_sourceSize = size; } + + QPoint sourceTopLeft() const { return m_sourceTopLeft; } + void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; } + +private: + QImage m_image; + QByteArray m_data; + QPoint m_destinationTopLeft; + QSize m_sourceSize; + QPoint m_sourceTopLeft; +}; + +Q_DECLARE_TYPEINFO(QRhiTextureSubresourceUploadDescription, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiTextureUploadEntry +{ +public: + QRhiTextureUploadEntry() = default; + QRhiTextureUploadEntry(int layer, int level, const QRhiTextureSubresourceUploadDescription &desc); + + int layer() const { return m_layer; } + void setLayer(int layer) { m_layer = layer; } + + int level() const { return m_level; } + void setLevel(int level) { m_level = level; } + + QRhiTextureSubresourceUploadDescription description() const { return m_desc; } + void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; } + +private: + int m_layer = 0; + int m_level = 0; + QRhiTextureSubresourceUploadDescription m_desc; +}; + +Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiTextureUploadDescription +{ +public: + QRhiTextureUploadDescription() = default; + QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry); + QRhiTextureUploadDescription(const QVector &entries); + + QVector entries() const { return m_entries; } + void setEntries(const QVector &entries) { m_entries = entries; } + void append(const QRhiTextureUploadEntry &entry); + +private: + QVector m_entries; +}; + +Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiTextureCopyDescription +{ +public: + QRhiTextureCopyDescription() = default; + + QSize pixelSize() const { return m_pixelSize; } + void setPixelSize(const QSize &sz) { m_pixelSize = sz; } + + int sourceLayer() const { return m_sourceLayer; } + void setSourceLayer(int layer) { m_sourceLayer = layer; } + + int sourceLevel() const { return m_sourceLevel; } + void setSourceLevel(int level) { m_sourceLevel = level; } + + QPoint sourceTopLeft() const { return m_sourceTopLeft; } + void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; } + + int destinationLayer() const { return m_destinationLayer; } + void setDestinationLayer(int layer) { m_destinationLayer = layer; } + + int destinationLevel() const { return m_destinationLevel; } + void setDestinationLevel(int level) { m_destinationLevel = level; } + + QPoint destinationTopLeft() const { return m_destinationTopLeft; } + void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; } + +private: + QSize m_pixelSize; + int m_sourceLayer = 0; + int m_sourceLevel = 0; + QPoint m_sourceTopLeft; + int m_destinationLayer = 0; + int m_destinationLevel = 0; + QPoint m_destinationTopLeft; +}; + +Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiReadbackDescription +{ +public: + QRhiReadbackDescription() = default; + QRhiReadbackDescription(QRhiTexture *texture); + + QRhiTexture *texture() const { return m_texture; } + void setTexture(QRhiTexture *tex) { m_texture = tex; } + + int layer() const { return m_layer; } + void setLayer(int layer) { m_layer = layer; } + + int level() const { return m_level; } + void setLevel(int level) { m_level = level; } + +private: + QRhiTexture *m_texture = nullptr; + int m_layer = 0; + int m_level = 0; +}; + +Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_MOVABLE_TYPE); + +struct Q_GUI_EXPORT QRhiNativeHandles +{ +}; + +class Q_GUI_EXPORT QRhiResource +{ +public: + enum Type { + Buffer, + Texture, + Sampler, + RenderBuffer, + RenderPassDescriptor, + RenderTarget, + TextureRenderTarget, + ShaderResourceBindings, + GraphicsPipeline, + SwapChain, + CommandBuffer + }; + + virtual ~QRhiResource(); + + virtual Type resourceType() const = 0; + + virtual void release() = 0; + void releaseAndDestroyLater(); + + QByteArray name() const; + void setName(const QByteArray &name); + + quint64 globalResourceId() const; + +protected: + QRhiResource(QRhiImplementation *rhi); + Q_DISABLE_COPY(QRhiResource) + friend class QRhiImplementation; + QRhiImplementation *m_rhi = nullptr; + quint64 m_id; + QByteArray m_objectName; +}; + +class Q_GUI_EXPORT QRhiBuffer : public QRhiResource +{ +public: + enum Type { + Immutable, + Static, + Dynamic + }; + + enum UsageFlag { + VertexBuffer = 1 << 0, + IndexBuffer = 1 << 1, + UniformBuffer = 1 << 2 + }; + Q_DECLARE_FLAGS(UsageFlags, UsageFlag) + + QRhiResource::Type resourceType() const override; + + Type type() const { return m_type; } + void setType(Type t) { m_type = t; } + + UsageFlags usage() const { return m_usage; } + void setUsage(UsageFlags u) { m_usage = u; } + + int size() const { return m_size; } + void setSize(int sz) { m_size = sz; } + + virtual bool build() = 0; + +protected: + QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_); + Type m_type; + UsageFlags m_usage; + int m_size; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags) + +class Q_GUI_EXPORT QRhiTexture : public QRhiResource +{ +public: + enum Flag { + RenderTarget = 1 << 0, + CubeMap = 1 << 2, + MipMapped = 1 << 3, + sRGB = 1 << 4, + UsedAsTransferSource = 1 << 5, + UsedWithGenerateMips = 1 << 6 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + enum Format { + UnknownFormat, + + RGBA8, + BGRA8, + R8, + R16, + RED_OR_ALPHA8, + + RGBA16F, + RGBA32F, + + D16, + D32F, + + BC1, + BC2, + BC3, + BC4, + BC5, + BC6H, + BC7, + + ETC2_RGB8, + ETC2_RGB8A1, + ETC2_RGBA8, + + ASTC_4x4, + ASTC_5x4, + ASTC_5x5, + ASTC_6x5, + ASTC_6x6, + ASTC_8x5, + ASTC_8x6, + ASTC_8x8, + ASTC_10x5, + ASTC_10x6, + ASTC_10x8, + ASTC_10x10, + ASTC_12x10, + ASTC_12x12 + }; + + QRhiResource::Type resourceType() const override; + + Format format() const { return m_format; } + void setFormat(Format fmt) { m_format = fmt; } + + QSize pixelSize() const { return m_pixelSize; } + void setPixelSize(const QSize &sz) { m_pixelSize = sz; } + + Flags flags() const { return m_flags; } + void setFlags(Flags f) { m_flags = f; } + + int sampleCount() const { return m_sampleCount; } + void setSampleCount(int s) { m_sampleCount = s; } + + virtual bool build() = 0; + virtual const QRhiNativeHandles *nativeHandles(); + virtual bool buildFrom(const QRhiNativeHandles *src); + +protected: + QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, + int sampleCount_, Flags flags_); + Format m_format; + QSize m_pixelSize; + int m_sampleCount; + Flags m_flags; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags) + +class Q_GUI_EXPORT QRhiSampler : public QRhiResource +{ +public: + enum Filter { + None, + Nearest, + Linear + }; + + enum AddressMode { + Repeat, + ClampToEdge, + Border, + Mirror, + MirrorOnce + }; + + enum CompareOp { + Never, + Less, + Equal, + LessOrEqual, + Greater, + NotEqual, + GreaterOrEqual, + Always + }; + + QRhiResource::Type resourceType() const override; + + Filter magFilter() const { return m_magFilter; } + void setMagFilter(Filter f) { m_magFilter = f; } + + Filter minFilter() const { return m_minFilter; } + void setMinFilter(Filter f) { m_minFilter = f; } + + Filter mipmapMode() const { return m_mipmapMode; } + void setMipmapMode(Filter f) { m_mipmapMode = f; } + + AddressMode addressU() const { return m_addressU; } + void setAddressU(AddressMode mode) { m_addressU = mode; } + + AddressMode addressV() const { return m_addressV; } + void setAddressV(AddressMode mode) { m_addressV = mode; } + + AddressMode addressW() const { return m_addressW; } + void setAddressW(AddressMode mode) { m_addressW = mode; } + + CompareOp textureCompareOp() const { return m_compareOp; } + void setTextureCompareOp(CompareOp op) { m_compareOp = op; } + + virtual bool build() = 0; + +protected: + QRhiSampler(QRhiImplementation *rhi, + Filter magFilter_, Filter minFilter_, Filter mipmapMode_, + AddressMode u_, AddressMode v_); + Filter m_magFilter; + Filter m_minFilter; + Filter m_mipmapMode; + AddressMode m_addressU; + AddressMode m_addressV; + AddressMode m_addressW; + CompareOp m_compareOp; +}; + +class Q_GUI_EXPORT QRhiRenderBuffer : public QRhiResource +{ +public: + enum Type { + DepthStencil, + Color + }; + + enum Flag { + UsedWithSwapChainOnly = 1 << 0 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + QRhiResource::Type resourceType() const override; + + Type type() const { return m_type; } + void setType(Type t) { m_type = t; } + + QSize pixelSize() const { return m_pixelSize; } + void setPixelSize(const QSize &sz) { m_pixelSize = sz; } + + int sampleCount() const { return m_sampleCount; } + void setSampleCount(int s) { m_sampleCount = s; } + + Flags flags() const { return m_flags; } + void setFlags(Flags h) { m_flags = h; } + + virtual bool build() = 0; + + virtual QRhiTexture::Format backingFormat() const = 0; + +protected: + QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_, + int sampleCount_, Flags flags_); + Type m_type; + QSize m_pixelSize; + int m_sampleCount; + Flags m_flags; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags) + +class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource +{ +public: + QRhiResource::Type resourceType() const override; + +protected: + QRhiRenderPassDescriptor(QRhiImplementation *rhi); +}; + +class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource +{ +public: + QRhiResource::Type resourceType() const override; + + virtual QSize pixelSize() const = 0; + virtual float devicePixelRatio() const = 0; + virtual int sampleCount() const = 0; + + QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; } + void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; } + +protected: + QRhiRenderTarget(QRhiImplementation *rhi); + QRhiRenderPassDescriptor *m_renderPassDesc = nullptr; +}; + +class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget +{ +public: + enum Flag { + PreserveColorContents = 1 << 0, + PreserveDepthStencilContents = 1 << 1 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + QRhiResource::Type resourceType() const override; + + QRhiTextureRenderTargetDescription description() const { return m_desc; } + void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; } + + Flags flags() const { return m_flags; } + void setFlags(Flags f) { m_flags = f; } + + virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0; + + virtual bool build() = 0; + +protected: + QRhiTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc_, Flags flags_); + QRhiTextureRenderTargetDescription m_desc; + Flags m_flags; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags) + +class Q_GUI_EXPORT QRhiShaderResourceBindings : public QRhiResource +{ +public: + QRhiResource::Type resourceType() const override; + + QVector bindings() const { return m_bindings; } + void setBindings(const QVector &b) { m_bindings = b; } + + bool isLayoutCompatible(const QRhiShaderResourceBindings *other) const; + + virtual bool build() = 0; + +protected: + QRhiShaderResourceBindings(QRhiImplementation *rhi); + QVector m_bindings; +#ifndef QT_NO_DEBUG_STREAM + friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &); +#endif +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &); +#endif + +class Q_GUI_EXPORT QRhiGraphicsPipeline : public QRhiResource +{ +public: + enum Flag { + UsesBlendConstants = 1 << 0, + UsesStencilRef = 1 << 1, + UsesScissor = 1 << 2 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + enum Topology { + Triangles, + TriangleStrip, + Lines, + LineStrip, + Points + }; + + enum CullMode { + None, + Front, + Back + }; + + enum FrontFace { + CCW, + CW + }; + + enum ColorMaskComponent { + R = 1 << 0, + G = 1 << 1, + B = 1 << 2, + A = 1 << 3 + }; + Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent) + + enum BlendFactor { + Zero, + One, + SrcColor, + OneMinusSrcColor, + DstColor, + OneMinusDstColor, + SrcAlpha, + OneMinusSrcAlpha, + DstAlpha, + OneMinusDstAlpha, + ConstantColor, + OneMinusConstantColor, + ConstantAlpha, + OneMinusConstantAlpha, + SrcAlphaSaturate, + Src1Color, + OneMinusSrc1Color, + Src1Alpha, + OneMinusSrc1Alpha + }; + + enum BlendOp { + Add, + Subtract, + ReverseSubtract, + Min, + Max + }; + + struct TargetBlend { + ColorMask colorWrite = ColorMask(0xF); // R | G | B | A + bool enable = false; + BlendFactor srcColor = One; + BlendFactor dstColor = OneMinusSrcAlpha; + BlendOp opColor = Add; + BlendFactor srcAlpha = One; + BlendFactor dstAlpha = OneMinusSrcAlpha; + BlendOp opAlpha = Add; + }; + + enum CompareOp { + Never, + Less, + Equal, + LessOrEqual, + Greater, + NotEqual, + GreaterOrEqual, + Always + }; + + enum StencilOp { + StencilZero, + Keep, + Replace, + IncrementAndClamp, + DecrementAndClamp, + Invert, + IncrementAndWrap, + DecrementAndWrap + }; + + struct StencilOpState { + StencilOp failOp = Keep; + StencilOp depthFailOp = Keep; + StencilOp passOp = Keep; + CompareOp compareOp = Always; + }; + + QRhiResource::Type resourceType() const override; + + Flags flags() const { return m_flags; } + void setFlags(Flags f) { m_flags = f; } + + Topology topology() const { return m_topology; } + void setTopology(Topology t) { m_topology = t; } + + CullMode cullMode() const { return m_cullMode; } + void setCullMode(CullMode mode) { m_cullMode = mode; } + + FrontFace frontFace() const { return m_frontFace; } + void setFrontFace(FrontFace f) { m_frontFace = f; } + + QVector targetBlends() const { return m_targetBlends; } + void setTargetBlends(const QVector &blends) { m_targetBlends = blends; } + + bool hasDepthTest() const { return m_depthTest; } + void setDepthTest(bool enable) { m_depthTest = enable; } + + bool hasDepthWrite() const { return m_depthWrite; } + void setDepthWrite(bool enable) { m_depthWrite = enable; } + + CompareOp depthOp() const { return m_depthOp; } + void setDepthOp(CompareOp op) { m_depthOp = op; } + + bool hasStencilTest() const { return m_stencilTest; } + void setStencilTest(bool enable) { m_stencilTest = enable; } + + StencilOpState stencilFront() const { return m_stencilFront; } + void setStencilFront(const StencilOpState &state) { m_stencilFront = state; } + + StencilOpState stencilBack() const { return m_stencilBack; } + void setStencilBack(const StencilOpState &state) { m_stencilBack = state; } + + quint32 stencilReadMask() const { return m_stencilReadMask; } + void setStencilReadMask(quint32 mask) { m_stencilReadMask = mask; } + + quint32 stencilWriteMask() const { return m_stencilWriteMask; } + void setStencilWriteMask(quint32 mask) { m_stencilWriteMask = mask; } + + int sampleCount() const { return m_sampleCount; } + void setSampleCount(int s) { m_sampleCount = s; } + + QVector shaderStages() const { return m_shaderStages; } + void setShaderStages(const QVector &stages) { m_shaderStages = stages; } + + QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; } + void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; } + + QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; } + void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; } + + QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; } + void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; } + + virtual bool build() = 0; + +protected: + QRhiGraphicsPipeline(QRhiImplementation *rhi); + Flags m_flags; + Topology m_topology = Triangles; + CullMode m_cullMode = None; + FrontFace m_frontFace = CCW; + QVector m_targetBlends; + bool m_depthTest = false; + bool m_depthWrite = false; + CompareOp m_depthOp = Less; + bool m_stencilTest = false; + StencilOpState m_stencilFront; + StencilOpState m_stencilBack; + quint32 m_stencilReadMask = 0xFF; + quint32 m_stencilWriteMask = 0xFF; + int m_sampleCount = 1; + QVector m_shaderStages; + QRhiVertexInputLayout m_vertexInputLayout; + QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr; + QRhiRenderPassDescriptor *m_renderPassDesc = nullptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::Flags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::ColorMask) +Q_DECLARE_TYPEINFO(QRhiGraphicsPipeline::TargetBlend, Q_MOVABLE_TYPE); + +class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource +{ +public: + enum Flag { + SurfaceHasPreMulAlpha = 1 << 0, + SurfaceHasNonPreMulAlpha = 1 << 1, + sRGB = 1 << 2, + UsedAsTransferSource = 1 << 3, + NoVSync = 1 << 4, + MinimalBufferCount = 1 << 5 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + QRhiResource::Type resourceType() const override; + + QWindow *window() const { return m_window; } + void setWindow(QWindow *window) { m_window = window; } + + Flags flags() const { return m_flags; } + void setFlags(Flags f) { m_flags = f; } + + QRhiRenderBuffer *depthStencil() const { return m_depthStencil; } + void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; } + + int sampleCount() const { return m_sampleCount; } + void setSampleCount(int samples) { m_sampleCount = samples; } + + QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; } + void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; } + + QSize currentPixelSize() const { return m_currentPixelSize; } + + virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0; + virtual QRhiRenderTarget *currentFrameRenderTarget() = 0; + virtual QSize surfacePixelSize() = 0; + virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0; + virtual bool buildOrResize() = 0; + +protected: + QRhiSwapChain(QRhiImplementation *rhi); + QWindow *m_window = nullptr; + Flags m_flags; + QRhiRenderBuffer *m_depthStencil = nullptr; + int m_sampleCount = 1; + QRhiRenderPassDescriptor *m_renderPassDesc = nullptr; + QSize m_currentPixelSize; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags) + +class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource +{ +public: + enum IndexFormat { + IndexUInt16, + IndexUInt32 + }; + + QRhiResource::Type resourceType() const override; + + void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates); + + void beginPass(QRhiRenderTarget *rt, + const QColor &colorClearValue, + const QRhiDepthStencilClearValue &depthStencilClearValue, + QRhiResourceUpdateBatch *resourceUpdates = nullptr); + void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr); + + void setGraphicsPipeline(QRhiGraphicsPipeline *ps); + using DynamicOffset = QPair; // binding, offset + void setShaderResources(QRhiShaderResourceBindings *srb = nullptr, + int dynamicOffsetCount = 0, + const DynamicOffset *dynamicOffsets = nullptr); + using VertexInput = QPair; // buffer, offset + void setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings, + QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0, + IndexFormat indexFormat = IndexUInt16); + + void setViewport(const QRhiViewport &viewport); + void setScissor(const QRhiScissor &scissor); + void setBlendConstants(const QColor &c); + void setStencilRef(quint32 refValue); + + void draw(quint32 vertexCount, + quint32 instanceCount = 1, + quint32 firstVertex = 0, + quint32 firstInstance = 0); + + void drawIndexed(quint32 indexCount, + quint32 instanceCount = 1, + quint32 firstIndex = 0, + qint32 vertexOffset = 0, + quint32 firstInstance = 0); + + void debugMarkBegin(const QByteArray &name); + void debugMarkEnd(); + void debugMarkMsg(const QByteArray &msg); + + const QRhiNativeHandles *nativeHandles(); + void beginExternal(); + void endExternal(); + +protected: + QRhiCommandBuffer(QRhiImplementation *rhi); +}; + +struct Q_GUI_EXPORT QRhiReadbackResult +{ + std::function completed = nullptr; + QRhiTexture::Format format; + QSize pixelSize; + QByteArray data; +}; // non-movable due to the std::function + +class Q_GUI_EXPORT QRhiResourceUpdateBatch +{ +public: + ~QRhiResourceUpdateBatch(); + + void release(); + + void merge(QRhiResourceUpdateBatch *other); + + void updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data); + void uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data); + void uploadStaticBuffer(QRhiBuffer *buf, const void *data); + void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc); + void uploadTexture(QRhiTexture *tex, const QImage &image); + void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription()); + void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result); + void generateMips(QRhiTexture *tex, int layer = 0); + +private: + QRhiResourceUpdateBatch(QRhiImplementation *rhi); + Q_DISABLE_COPY(QRhiResourceUpdateBatch) + QRhiResourceUpdateBatchPrivate *d; + friend class QRhiResourceUpdateBatchPrivate; + friend class QRhi; +}; + +struct Q_GUI_EXPORT QRhiInitParams +{ +}; + +class Q_GUI_EXPORT QRhi +{ +public: + enum Implementation { + Null, + Vulkan, + OpenGLES2, + D3D11, + Metal + }; + + enum Flag { + EnableProfiling = 1 << 0, + EnableDebugMarkers = 1 << 1 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + enum FrameOpResult { + FrameOpSuccess = 0, + FrameOpError, + FrameOpSwapChainOutOfDate, + FrameOpDeviceLost + }; + + enum Feature { + MultisampleTexture = 1, + MultisampleRenderBuffer, + DebugMarkers, + Timestamps, + Instancing, + CustomInstanceStepRate, + PrimitiveRestart, + NonDynamicUniformBuffers, + NonFourAlignedEffectiveIndexBufferOffset, + NPOTTextureRepeat, + RedOrAlpha8IsRed, + ElementIndexUint + }; + + enum BeginFrameFlag { + }; + Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag) + + enum EndFrameFlag { + SkipPresent = 1 << 0 + }; + Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag) + + enum ResourceLimit { + TextureSizeMin = 1, + TextureSizeMax, + MaxColorAttachments, + FramesInFlight + }; + + ~QRhi(); + + static QRhi *create(Implementation impl, + QRhiInitParams *params, + Flags flags = Flags(), + QRhiNativeHandles *importDevice = nullptr); + + Implementation backend() const; + QThread *thread() const; + + using CleanupCallback = std::function; + void addCleanupCallback(const CleanupCallback &callback); + void runCleanup(); + + QRhiGraphicsPipeline *newGraphicsPipeline(); + QRhiShaderResourceBindings *newShaderResourceBindings(); + + QRhiBuffer *newBuffer(QRhiBuffer::Type type, + QRhiBuffer::UsageFlags usage, + int size); + + QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type, + const QSize &pixelSize, + int sampleCount = 1, + QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags()); + + QRhiTexture *newTexture(QRhiTexture::Format format, + const QSize &pixelSize, + int sampleCount = 1, + QRhiTexture::Flags flags = QRhiTexture::Flags()); + + QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler::Filter mipmapMode, + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v); + + QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, + QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags()); + + QRhiSwapChain *newSwapChain(); + FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = BeginFrameFlags()); + FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = EndFrameFlags()); + bool isRecordingFrame() const; + int currentFrameSlot() const; + + FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb); + FrameOpResult endOffscreenFrame(); + + QRhi::FrameOpResult finish(); + + QRhiResourceUpdateBatch *nextResourceUpdateBatch(); + + QVector supportedSampleCounts() const; + + int ubufAlignment() const; + int ubufAligned(int v) const; + + int mipLevelsForSize(const QSize &size) const; + QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const; + + bool isYUpInFramebuffer() const; + bool isYUpInNDC() const; + bool isClipDepthZeroToOne() const; + + QMatrix4x4 clipSpaceCorrMatrix() const; + + bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = QRhiTexture::Flags()) const; + bool isFeatureSupported(QRhi::Feature feature) const; + int resourceLimit(ResourceLimit limit) const; + + const QRhiNativeHandles *nativeHandles(); + + QRhiProfiler *profiler(); + + static const int MAX_LAYERS = 6; // cubemaps only + static const int MAX_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone + +protected: + QRhi(); + +private: + Q_DISABLE_COPY(QRhi) + QRhiImplementation *d = nullptr; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::Flags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::BeginFrameFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::EndFrameFlags) + +QT_END_NAMESPACE + +#endif -- cgit v1.2.3 From 4c297bdca8da543c582d129f12413d29a2a520eb Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Jun 2019 12:17:19 +0200 Subject: rhi: Make it possible to request making the context current on GL Needed by Qt Quick to handle cases where the application (or other Qt) code contains OpenGL calls, and Qt Quick facilitates this by ensuring the scenegraph's GL context is current. The expectation is that when running with the GL backend of the rhi, all such code remains fully functional. So add a makeCurrent type of call into the QRhi API that is a no-op with anything other than OpenGL. Change-Id: I6f774bf828e31802bdab0c3fef9421cdc0cebe5c Reviewed-by: Lars Knoll --- src/gui/rhi/qrhi_p.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gui/rhi/qrhi_p.h') diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index a0f57819e4..b7515cb17a 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1352,6 +1352,7 @@ public: int resourceLimit(ResourceLimit limit) const; const QRhiNativeHandles *nativeHandles(); + void makeThreadLocalNativeContextCurrent(); QRhiProfiler *profiler(); -- cgit v1.2.3 From 6f4aa5413183f3f18dd1b15dbc90bcee9ef85bdd Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 12 Jun 2019 14:22:33 +0200 Subject: rhi: Add compute api and implement for Vulkan and Metal D3D11 and GL (4.3+, ES 3.1+) will come separately at a later time. Change-Id: If30f2f3d062fa27e57e9912674669225b82a7b93 Reviewed-by: Lars Knoll --- src/gui/rhi/qrhi_p.h | 86 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 18 deletions(-) (limited to 'src/gui/rhi/qrhi_p.h') diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index b7515cb17a..0d296d370c 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -259,17 +259,18 @@ Q_GUI_EXPORT uint qHash(const QRhiVertexInputLayout &v, uint seed = 0) Q_DECL_NO Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &); #endif -class Q_GUI_EXPORT QRhiGraphicsShaderStage +class Q_GUI_EXPORT QRhiShaderStage { public: enum Type { Vertex, - Fragment + Fragment, + Compute }; - QRhiGraphicsShaderStage() = default; - QRhiGraphicsShaderStage(Type type, const QShader &shader, - QShader::Variant v = QShader::StandardShader); + QRhiShaderStage() = default; + QRhiShaderStage(Type type, const QShader &shader, + QShader::Variant v = QShader::StandardShader); Type type() const { return m_type; } void setType(Type t) { m_type = t; } @@ -286,26 +287,35 @@ private: QShader::Variant m_shaderVariant = QShader::StandardShader; }; -Q_DECLARE_TYPEINFO(QRhiGraphicsShaderStage, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QRhiShaderStage, Q_MOVABLE_TYPE); -Q_GUI_EXPORT bool operator==(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW; -Q_GUI_EXPORT bool operator!=(const QRhiGraphicsShaderStage &a, const QRhiGraphicsShaderStage &b) Q_DECL_NOTHROW; -Q_GUI_EXPORT uint qHash(const QRhiGraphicsShaderStage &s, uint seed = 0) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) Q_DECL_NOTHROW; +Q_GUI_EXPORT uint qHash(const QRhiShaderStage &s, uint seed = 0) Q_DECL_NOTHROW; #ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiGraphicsShaderStage &); +Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderStage &); #endif +using QRhiGraphicsShaderStage = QRhiShaderStage; + class Q_GUI_EXPORT QRhiShaderResourceBinding { public: enum Type { UniformBuffer, - SampledTexture + SampledTexture, + ImageLoad, + ImageStore, + ImageLoadStore, + BufferLoad, + BufferStore, + BufferLoadStore }; enum StageFlag { VertexStage = 1 << 0, - FragmentStage = 1 << 1 + FragmentStage = 1 << 1, + ComputeStage = 1 << 2 }; Q_DECLARE_FLAGS(StageFlags, StageFlag) @@ -320,8 +330,20 @@ public: static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf); static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size); static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, int size); + static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler); + static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level); + static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level); + static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level); + + static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf); + static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size); + static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf); + static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size); + static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf); + static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size); + private: QRhiShaderResourceBindingPrivate *d; friend class QRhiShaderResourceBindingPrivate; @@ -558,6 +580,7 @@ public: ShaderResourceBindings, GraphicsPipeline, SwapChain, + ComputePipeline, CommandBuffer }; @@ -594,7 +617,8 @@ public: enum UsageFlag { VertexBuffer = 1 << 0, IndexBuffer = 1 << 1, - UniformBuffer = 1 << 2 + UniformBuffer = 1 << 2, + StorageBuffer = 1 << 3 }; Q_DECLARE_FLAGS(UsageFlags, UsageFlag) @@ -629,7 +653,8 @@ public: MipMapped = 1 << 3, sRGB = 1 << 4, UsedAsTransferSource = 1 << 5, - UsedWithGenerateMips = 1 << 6 + UsedWithGenerateMips = 1 << 6, + UsedWithLoadStore = 1 << 7 }; Q_DECLARE_FLAGS(Flags, Flag) @@ -1043,8 +1068,8 @@ public: int sampleCount() const { return m_sampleCount; } void setSampleCount(int s) { m_sampleCount = s; } - QVector shaderStages() const { return m_shaderStages; } - void setShaderStages(const QVector &stages) { m_shaderStages = stages; } + QVector shaderStages() const { return m_shaderStages; } + void setShaderStages(const QVector &stages) { m_shaderStages = stages; } QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; } void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; } @@ -1073,7 +1098,7 @@ protected: quint32 m_stencilReadMask = 0xFF; quint32 m_stencilWriteMask = 0xFF; int m_sampleCount = 1; - QVector m_shaderStages; + QVector m_shaderStages; QRhiVertexInputLayout m_vertexInputLayout; QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr; QRhiRenderPassDescriptor *m_renderPassDesc = nullptr; @@ -1133,6 +1158,24 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags) +class Q_GUI_EXPORT QRhiComputePipeline : public QRhiResource +{ +public: + QRhiResource::Type resourceType() const override; + virtual bool build() = 0; + + QRhiShaderStage shaderStage() const { return m_shaderStage; } + void setShaderStage(const QRhiShaderStage &stage) { m_shaderStage = stage; } + + QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; } + void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; } + +protected: + QRhiComputePipeline(QRhiImplementation *rhi); + QRhiShaderStage m_shaderStage; + QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr; +}; + class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource { public: @@ -1181,6 +1224,11 @@ public: void debugMarkEnd(); void debugMarkMsg(const QByteArray &msg); + void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr); + void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr); + void setComputePipeline(QRhiComputePipeline *ps); + void dispatch(int x, int y, int z); + const QRhiNativeHandles *nativeHandles(); void beginExternal(); void endExternal(); @@ -1263,7 +1311,8 @@ public: NonFourAlignedEffectiveIndexBufferOffset, NPOTTextureRepeat, RedOrAlpha8IsRed, - ElementIndexUint + ElementIndexUint, + Compute }; enum BeginFrameFlag { @@ -1297,6 +1346,7 @@ public: void runCleanup(); QRhiGraphicsPipeline *newGraphicsPipeline(); + QRhiComputePipeline *newComputePipeline(); QRhiShaderResourceBindings *newShaderResourceBindings(); QRhiBuffer *newBuffer(QRhiBuffer::Type type, -- cgit v1.2.3 From 854ddb0301ae677a31286da4476318f4e6b74e3f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 24 Jun 2019 10:22:50 +0200 Subject: rhi: Enhance line width and point size support ...but this will vary between backends, or in some cases even between implementations of the same API. Point size is settable only via the vertex shader (gl_PointSize). It is silently ignored with D3D and HLSL. Line widths other than 1 are supported only on OpenGL and Vulkan. (but this is in fact deprecated with GL and optional with Vulkan) Add QRhi::Feature values for both. The line width is now settable on QRhiGraphicsPipeline. It is not a dynamic state since the static, per-pipeline width is good enough for most cases. (and the feature is not supported on half of the backends anyways so it will get limited use in practice). Change-Id: I6d3a32269527c452b794b2cb8b0f03101eab40b2 Reviewed-by: Lars Knoll --- src/gui/rhi/qrhi_p.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/gui/rhi/qrhi_p.h') diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 0d296d370c..fb8727b265 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1068,6 +1068,9 @@ public: int sampleCount() const { return m_sampleCount; } void setSampleCount(int s) { m_sampleCount = s; } + float lineWidth() const { return m_lineWidth; } + void setLineWidth(float width) { m_lineWidth = width; } + QVector shaderStages() const { return m_shaderStages; } void setShaderStages(const QVector &stages) { m_shaderStages = stages; } @@ -1098,6 +1101,7 @@ protected: quint32 m_stencilReadMask = 0xFF; quint32 m_stencilWriteMask = 0xFF; int m_sampleCount = 1; + float m_lineWidth = 1.0f; QVector m_shaderStages; QRhiVertexInputLayout m_vertexInputLayout; QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr; @@ -1312,7 +1316,9 @@ public: NPOTTextureRepeat, RedOrAlpha8IsRed, ElementIndexUint, - Compute + Compute, + WideLines, + VertexShaderPointSize }; enum BeginFrameFlag { -- cgit v1.2.3 From 058c52fc2a6476f688d4b07d6f24516e26d0a8f5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 28 Jun 2019 15:06:06 +0200 Subject: rhi: Improve base vertex/instance support Have feature flags as appropriate. OpenGL is causing a mess here but let's support what we can since some of this will become relevant in more sophisticated mesh drawing cases with 3D in particular. Change-Id: Idfa7b4642ec87147978e03d78d6233efbd151491 Reviewed-by: Lars Knoll --- src/gui/rhi/qrhi_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/gui/rhi/qrhi_p.h') diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index fb8727b265..df30817ef4 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1318,7 +1318,9 @@ public: ElementIndexUint, Compute, WideLines, - VertexShaderPointSize + VertexShaderPointSize, + BaseVertex, + BaseInstance }; enum BeginFrameFlag { -- cgit v1.2.3