aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h')
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h253
1 files changed, 230 insertions, 23 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 12b48c1451..9dec203e73 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -58,11 +58,14 @@
#include <private/qsgnodeupdater_p.h>
#include <private/qsgrendernode_p.h>
#include <private/qdatabuffer_p.h>
+#include <private/qsgtexture_p.h>
#include <QtCore/QBitArray>
-
+#include <QtCore/QStack>
#include <QtGui/QOpenGLFunctions>
+#include <QtGui/private/qrhi_p.h>
+
QT_BEGIN_NAMESPACE
class QOpenGLVertexArrayObject;
@@ -300,10 +303,11 @@ struct Buffer {
// Data is only valid while preparing the upload. Exception is if we are using the
// broken IBO workaround or we are using a visualization mode.
char *data;
+ QRhiBuffer *buf;
+ uint nonDynamicChangeCount;
};
struct Element {
-
Element()
: boundsComputed(false)
, boundsOutsideFloatRange(false)
@@ -334,6 +338,8 @@ struct Element {
Rect bounds; // in device coordinates
int order = 0;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
uint boundsComputed : 1;
uint boundsOutsideFloatRange : 1;
@@ -390,6 +396,48 @@ enum BatchCompatibility
BatchIsCompatible
};
+struct ClipState
+{
+ enum ClipTypeBit
+ {
+ NoClip = 0x00,
+ ScissorClip = 0x01,
+ StencilClip = 0x02
+ };
+ Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
+
+ const QSGClipNode *clipList;
+ ClipType type;
+ QRhiScissor scissor;
+ int stencilRef;
+
+ inline void reset();
+};
+
+struct StencilClipState
+{
+ StencilClipState() : drawCalls(1) { }
+
+ bool updateStencilBuffer = false;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+
+ struct StencilDrawCall {
+ int stencilRef;
+ int vertexCount;
+ int indexCount;
+ QRhiCommandBuffer::IndexFormat indexFormat;
+ quint32 vbufOffset;
+ quint32 ibufOffset;
+ quint32 ubufOffset;
+ };
+ QDataBuffer<StencilDrawCall> drawCalls;
+
+ inline void reset();
+};
+
struct Batch
{
Batch() : drawSets(1) {}
@@ -403,6 +451,7 @@ struct Batch
// pseudo-constructor...
void init() {
+ // Only non-reusable members are reset here. See Renderer::newBatch().
first = nullptr;
root = nullptr;
vertexCount = 0;
@@ -413,6 +462,9 @@ struct Batch
positionAttribute = -1;
uploadedThisFrame = false;
isRenderNode = false;
+ ubufDataValid = false;
+ clipState.reset();
+ blendConstant = QColor();
}
Element *first;
@@ -429,16 +481,21 @@ struct Batch
uint needsUpload : 1;
uint merged : 1;
uint isRenderNode : 1;
+ uint ubufDataValid : 1;
mutable uint uploadedThisFrame : 1; // solely for debugging purposes
Buffer vbo;
Buffer ibo;
+ QRhiBuffer *ubuf;
+ ClipState clipState;
+ StencilClipState stencilClipState;
+ QColor blendConstant;
QDataBuffer<DrawSet> drawSets;
};
-// NOTE: Node is zero-allocated by the Allocator.
+// NOTE: Node is zero-initialized by the Allocator.
struct Node
{
QSGNode *sgNode;
@@ -574,10 +631,19 @@ class ShaderManager : public QObject
Q_OBJECT
public:
struct Shader {
- ~Shader() { delete program; }
- int id_zRange;
- int pos_order;
- QSGMaterialShader *program;
+ ~Shader() {
+ delete programRhi.program;
+ delete programGL.program;
+ }
+ struct {
+ QSGMaterialShader *program = nullptr;
+ int pos_order;
+ } programGL;
+ struct {
+ QSGMaterialRhiShader *program = nullptr;
+ QRhiVertexInputLayout inputLayout;
+ QVector<QRhiGraphicsShaderStage> shaderStages;
+ } programRhi;
float lastOpacity;
};
@@ -588,12 +654,16 @@ public:
qDeleteAll(stockShaders);
}
+ void clearCachedRendererData();
+
+ QRhiShaderResourceBindings *srb(const QVector<QRhiShaderResourceBinding> &bindings);
+
public Q_SLOTS:
void invalidated();
public:
- Shader *prepareMaterial(QSGMaterial *material);
- Shader *prepareMaterialNoRewrite(QSGMaterial *material);
+ Shader *prepareMaterial(QSGMaterial *material, bool enableRhiShaders = false, const QSGGeometry *geometry = nullptr);
+ Shader *prepareMaterialNoRewrite(QSGMaterial *material, bool enableRhiShaders = false, const QSGGeometry *geometry = nullptr);
QOpenGLShaderProgram *visualizeProgram;
@@ -603,6 +673,50 @@ private:
QOpenGLShaderProgram *blitProgram;
QSGDefaultRenderContext *context;
+
+ QHash<QVector<QRhiShaderResourceBinding>, QRhiShaderResourceBindings *> srbCache;
+};
+
+struct GraphicsState
+{
+ bool depthTest = false;
+ bool depthWrite = false;
+ QRhiGraphicsPipeline::CompareOp depthFunc = QRhiGraphicsPipeline::Less;
+ bool blending = false;
+ QRhiGraphicsPipeline::BlendFactor srcColor = QRhiGraphicsPipeline::One;
+ QRhiGraphicsPipeline::BlendFactor dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
+ QRhiGraphicsPipeline::ColorMask colorWrite = QRhiGraphicsPipeline::ColorMask(0xF);
+ QRhiGraphicsPipeline::CullMode cullMode = QRhiGraphicsPipeline::None;
+ bool usesScissor = false;
+ bool stencilTest = false;
+ int sampleCount = 1;
+ QSGGeometry::DrawingMode drawMode = QSGGeometry::DrawTriangles;
+ float lineWidth = 1.0f;
+};
+
+bool operator==(const GraphicsState &a, const GraphicsState &b) Q_DECL_NOTHROW;
+bool operator!=(const GraphicsState &a, const GraphicsState &b) Q_DECL_NOTHROW;
+uint qHash(const GraphicsState &s, uint seed = 0) Q_DECL_NOTHROW;
+
+struct GraphicsPipelineStateKey
+{
+ GraphicsState state;
+ const ShaderManager::Shader *sms;
+ const QRhiRenderPassDescriptor *rpDesc;
+ const QRhiShaderResourceBindings *layoutCompatibleSrb;
+};
+
+bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) Q_DECL_NOTHROW;
+bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) Q_DECL_NOTHROW;
+uint qHash(const GraphicsPipelineStateKey &k, uint seed = 0) Q_DECL_NOTHROW;
+
+struct RenderPassState
+{
+ QRhiViewport viewport;
+ QColor clearColor;
+ QRhiDepthStencilClearValue dsClear;
+ bool viewportSet;
+ bool scissorSet;
};
class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer, public QOpenGLFunctions
@@ -625,14 +739,6 @@ protected:
void releaseCachedResources() override;
private:
- enum ClipTypeBit
- {
- NoClip = 0x00,
- ScissorClip = 0x01,
- StencilClip = 0x02
- };
- Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
-
enum RebuildFlag {
BuildRenderListsForTaggedRoots = 0x0001,
BuildRenderLists = 0x0002,
@@ -642,6 +748,7 @@ private:
friend class Updater;
+ void destroyGraphicsResources();
void map(Buffer *buffer, int size, bool isIndexBuf = false);
void unmap(Buffer *buffer, bool isIndexBuf = false);
@@ -658,16 +765,39 @@ private:
void invalidateBatchAndOverlappingRenderOrders(Batch *batch);
void uploadBatch(Batch *b);
- void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, quint16 *iBase, int *indexCount);
+ void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, void *iBasePtr, int *indexCount);
+
+ struct PreparedRenderBatch {
+ const Batch *batch;
+ ShaderManager::Shader *sms;
+ };
void renderBatches();
- void renderMergedBatch(const Batch *batch);
- void renderUnmergedBatch(const Batch *batch);
- ClipType updateStencilClip(const QSGClipNode *clip);
+ bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms);
+ QRhiTexture *dummyTexture();
+ void updateMaterialDynamicData(ShaderManager::Shader *sms, const QSGMaterialRhiShader::RenderState &renderState,
+ QSGMaterial *material, QVector<QRhiShaderResourceBinding> *bindings,
+ const Batch *batch, int ubufOffset, int ubufRegionSize);
+ void updateMaterialStaticData(ShaderManager::Shader *sms, const QSGMaterialRhiShader::RenderState &renderState,
+ QSGMaterial *material, Batch *batch, bool *gstateChanged);
+ void checkLineWidth(QSGGeometry *g);
+ bool prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *renderBatch);
+ void renderMergedBatch(PreparedRenderBatch *renderBatch);
+ bool prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *renderBatch);
+ void renderUnmergedBatch(PreparedRenderBatch *renderBatch);
+ void setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, Element *e);
+ void renderMergedBatch(const Batch *batch); // GL
+ void renderUnmergedBatch(const Batch *batch); // GL
+ ClipState::ClipType updateStencilClip(const QSGClipNode *clip);
void updateClip(const QSGClipNode *clipList, const Batch *batch);
+ void applyClipStateToGraphicsState();
+ QRhiGraphicsPipeline *buildStencilPipeline(const Batch *batch, bool firstStencilClipInBatch);
+ void updateClipState(const QSGClipNode *clipList, Batch *batch);
+ void enqueueStencilDraw(const Batch *batch);
const QMatrix4x4 &matrixForRoot(Node *node);
void renderRenderNode(Batch *batch);
void setActiveShader(QSGMaterialShader *program, ShaderManager::Shader *shader);
+ void setActiveRhiShader(QSGMaterialRhiShader *program, ShaderManager::Shader *shader);
bool changeBatchRoot(Node *node, Node *newRoot);
void registerBatchRoot(Node *childRoot, Node *parentRoot);
@@ -723,17 +853,21 @@ private:
int m_batchVertexThreshold;
// Stuff used during rendering only...
- ShaderManager *m_shaderManager;
+ ShaderManager *m_shaderManager; // per rendercontext, shared
QSGMaterial *m_currentMaterial;
QSGMaterialShader *m_currentProgram;
+ QSGMaterialRhiShader *m_currentRhiProgram;
ShaderManager::Shader *m_currentShader;
+ ClipState m_currentClipState;
+ // *** legacy (GL) only
QRect m_currentScissorRect;
int m_currentStencilValue;
QOpenGLShaderProgram m_clipProgram;
int m_clipMatrixId;
const QSGClipNode *m_currentClip;
- ClipType m_currentClipType;
+ ClipState::ClipType m_currentClipType;
+ // ***
QDataBuffer<char> m_vertexUploadPool;
QDataBuffer<char> m_indexUploadPool;
@@ -745,6 +879,28 @@ private:
Allocator<Node, 256> m_nodeAllocator;
Allocator<Element, 64> m_elementAllocator;
+
+ QRhiResourceUpdateBatch *m_resourceUpdates = nullptr;
+ uint m_ubufAlignment;
+ bool m_uint32IndexForRhi;
+ GraphicsState m_gstate;
+ RenderPassState m_pstate;
+ QStack<GraphicsState> m_gstateStack;
+ QHash<GraphicsPipelineStateKey, QRhiGraphicsPipeline *> m_pipelines;
+ QHash<QSGSamplerDescription, QRhiSampler *> m_samplers;
+ QRhiTexture *m_dummyTexture = nullptr;
+
+ struct StencilClipCommonData {
+ QRhiGraphicsPipeline *replacePs = nullptr;
+ QRhiGraphicsPipeline *incrPs = nullptr;
+ QShader vs;
+ QShader fs;
+ QRhiVertexInputLayout inputLayout;
+ QRhiGraphicsPipeline::Topology topology;
+ inline void reset();
+ } m_stencilClipCommon;
+
+ inline int mergedIndexElemSize() const;
};
Batch *Renderer::newBatch()
@@ -753,18 +909,69 @@ Batch *Renderer::newBatch()
int size = m_batchPool.size();
if (size) {
b = m_batchPool.at(size - 1);
+ // vbo, ibo, ubuf, stencil-related buffers are reused
m_batchPool.resize(size - 1);
} else {
b = new Batch();
Q_ASSERT(offsetof(Batch, ibo) == sizeof(Buffer) + offsetof(Batch, vbo));
memset(&b->vbo, 0, sizeof(Buffer) * 2); // Clear VBO & IBO
+ b->ubuf = nullptr;
+ b->stencilClipState.reset();
}
+ // initialize (when new batch) or reset (when reusing a batch) the non-reusable fields
b->init();
return b;
}
+int Renderer::mergedIndexElemSize() const
+{
+ return m_uint32IndexForRhi ? sizeof(quint32) : sizeof(quint16);
}
+void Renderer::StencilClipCommonData::reset()
+{
+ delete replacePs;
+ replacePs = nullptr;
+
+ delete incrPs;
+ incrPs = nullptr;
+
+ vs = QShader();
+ fs = QShader();
+}
+
+void ClipState::reset()
+{
+ clipList = nullptr;
+ type = NoClip;
+ stencilRef = 0;
+}
+
+void StencilClipState::reset()
+{
+ updateStencilBuffer = false;
+
+ delete srb;
+ srb = nullptr;
+
+ delete vbuf;
+ vbuf = nullptr;
+
+ delete ibuf;
+ ibuf = nullptr;
+
+ delete ubuf;
+ ubuf = nullptr;
+
+ drawCalls.reset();
+}
+
+}
+
+Q_DECLARE_TYPEINFO(QSGBatchRenderer::GraphicsState, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSGBatchRenderer::GraphicsPipelineStateKey, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QSGBatchRenderer::RenderPassState, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
#endif // QSGBATCHRENDERER_P_H