Refactor the rendernode example
By removing the Renderer abstraction it becomes easier to follow and understand. Change-Id: Iddacb461d51a75864983850660c5480985b3524f Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
519032e9e0
commit
e1682b84bb
|
@ -45,51 +45,6 @@
|
||||||
#include "openglrenderer.h"
|
#include "openglrenderer.h"
|
||||||
#include "d3d12renderer.h"
|
#include "d3d12renderer.h"
|
||||||
|
|
||||||
CustomRenderNode::~CustomRenderNode()
|
|
||||||
{
|
|
||||||
releaseResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomRenderNode::render(const RenderState *state)
|
|
||||||
{
|
|
||||||
QSGRendererInterface *ri = m_item->window()->rendererInterface();
|
|
||||||
if (!ri)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!m_renderer) {
|
|
||||||
switch (ri->graphicsAPI()) {
|
|
||||||
case QSGRendererInterface::OpenGL:
|
|
||||||
#ifndef QT_NO_OPENGL
|
|
||||||
m_renderer = new OpenGLRenderer(m_item, this);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case QSGRendererInterface::Direct3D12:
|
|
||||||
#ifdef HAS_D3D12
|
|
||||||
m_renderer = new D3D12Renderer(m_item, this);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Q_ASSERT(m_renderer);
|
|
||||||
m_renderer->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_renderer->render(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to reimplement changedStates() since our rendering is so simple,
|
|
||||||
// without involving any state changes.
|
|
||||||
|
|
||||||
void CustomRenderNode::releaseResources()
|
|
||||||
{
|
|
||||||
if (!m_renderer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete m_renderer;
|
|
||||||
m_renderer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomRenderItem::CustomRenderItem(QQuickItem *parent)
|
CustomRenderItem::CustomRenderItem(QQuickItem *parent)
|
||||||
: QQuickItem(parent)
|
: QQuickItem(parent)
|
||||||
{
|
{
|
||||||
|
@ -99,9 +54,26 @@ CustomRenderItem::CustomRenderItem(QQuickItem *parent)
|
||||||
|
|
||||||
QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
|
QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
|
||||||
{
|
{
|
||||||
CustomRenderNode *n = static_cast<CustomRenderNode *>(node);
|
QSGRenderNode *n = static_cast<QSGRenderNode *>(node);
|
||||||
if (!node)
|
if (!n) {
|
||||||
n = new CustomRenderNode(this);
|
QSGRendererInterface *ri = window()->rendererInterface();
|
||||||
|
if (!ri)
|
||||||
|
return nullptr;
|
||||||
|
switch (ri->graphicsAPI()) {
|
||||||
|
case QSGRendererInterface::OpenGL:
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
n = new OpenGLRenderNode(this);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case QSGRendererInterface::Direct3D12:
|
||||||
|
#ifdef HAS_D3D12
|
||||||
|
n = new D3D12RenderNode(this);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,29 +42,6 @@
|
||||||
#define CUSTOMRENDERITEM_H
|
#define CUSTOMRENDERITEM_H
|
||||||
|
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QSGRenderNode>
|
|
||||||
|
|
||||||
class CustomRenderer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~CustomRenderer() { }
|
|
||||||
virtual void init() = 0;
|
|
||||||
virtual void render(const QSGRenderNode::RenderState *state) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CustomRenderNode : public QSGRenderNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CustomRenderNode(QQuickItem *item) : m_item(item) { }
|
|
||||||
~CustomRenderNode();
|
|
||||||
|
|
||||||
void render(const RenderState *state) override;
|
|
||||||
void releaseResources() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QQuickItem *m_item;
|
|
||||||
CustomRenderer *m_renderer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CustomRenderItem : public QQuickItem
|
class CustomRenderItem : public QQuickItem
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "d3d12renderer.h"
|
#include "d3d12renderer.h"
|
||||||
|
#include <QQuickItem>
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
#include <QSGRendererInterface>
|
#include <QSGRendererInterface>
|
||||||
|
|
||||||
|
@ -47,15 +48,34 @@
|
||||||
#include "vs_shader.hlslh"
|
#include "vs_shader.hlslh"
|
||||||
#include "ps_shader.hlslh"
|
#include "ps_shader.hlslh"
|
||||||
|
|
||||||
D3D12Renderer::D3D12Renderer(QQuickItem *item, QSGRenderNode *node)
|
D3D12RenderNode::D3D12RenderNode(QQuickItem *item)
|
||||||
: m_item(item),
|
: m_item(item)
|
||||||
m_node(node),
|
|
||||||
vbPtr(nullptr),
|
|
||||||
cbPtr(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12Renderer::init()
|
D3D12RenderNode::~D3D12RenderNode()
|
||||||
|
{
|
||||||
|
releaseResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D12RenderNode::releaseResources()
|
||||||
|
{
|
||||||
|
if (vbPtr) {
|
||||||
|
vertexBuffer->Unmap(0, nullptr);
|
||||||
|
vbPtr = nullptr;
|
||||||
|
}
|
||||||
|
if (cbPtr) {
|
||||||
|
constantBuffer->Unmap(0, nullptr);
|
||||||
|
cbPtr = nullptr;
|
||||||
|
}
|
||||||
|
constantBuffer = nullptr;
|
||||||
|
vertexBuffer = nullptr;
|
||||||
|
rootSignature = nullptr;
|
||||||
|
pipelineState = nullptr;
|
||||||
|
m_device = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D12RenderNode::init()
|
||||||
{
|
{
|
||||||
QSGRendererInterface *rif = m_item->window()->rendererInterface();
|
QSGRendererInterface *rif = m_item->window()->rendererInterface();
|
||||||
m_device = static_cast<ID3D12Device *>(rif->getResource(QSGRendererInterface::Device));
|
m_device = static_cast<ID3D12Device *>(rif->getResource(QSGRendererInterface::Device));
|
||||||
|
@ -180,22 +200,17 @@ void D3D12Renderer::init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12Renderer::~D3D12Renderer()
|
void D3D12RenderNode::render(const RenderState *state)
|
||||||
{
|
{
|
||||||
if (vbPtr)
|
if (!m_device)
|
||||||
vertexBuffer->Unmap(0, nullptr);
|
init();
|
||||||
if (cbPtr)
|
|
||||||
constantBuffer->Unmap(0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3D12Renderer::render(const QSGRenderNode::RenderState *state)
|
|
||||||
{
|
|
||||||
QSGRendererInterface *rif = m_item->window()->rendererInterface();
|
QSGRendererInterface *rif = m_item->window()->rendererInterface();
|
||||||
ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(rif->getResource(QSGRendererInterface::CommandList));
|
ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(rif->getResource(QSGRendererInterface::CommandList));
|
||||||
Q_ASSERT(commandList);
|
Q_ASSERT(commandList);
|
||||||
|
|
||||||
const int msize = 16 * sizeof(float);
|
const int msize = 16 * sizeof(float);
|
||||||
memcpy(cbPtr, m_node->matrix()->constData(), msize);
|
memcpy(cbPtr, matrix()->constData(), msize);
|
||||||
memcpy(cbPtr + msize, state->projectionMatrix()->constData(), msize);
|
memcpy(cbPtr + msize, state->projectionMatrix()->constData(), msize);
|
||||||
|
|
||||||
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
|
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
|
||||||
|
|
|
@ -41,35 +41,38 @@
|
||||||
#ifndef D3D12RENDERER_H
|
#ifndef D3D12RENDERER_H
|
||||||
#define D3D12RENDERER_H
|
#define D3D12RENDERER_H
|
||||||
|
|
||||||
#include "customrenderitem.h"
|
|
||||||
#include <qsgrendernode.h>
|
#include <qsgrendernode.h>
|
||||||
|
|
||||||
#ifdef HAS_D3D12
|
#ifdef HAS_D3D12
|
||||||
|
|
||||||
|
class QQuickItem;
|
||||||
|
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
class D3D12Renderer : public CustomRenderer
|
class D3D12RenderNode : public QSGRenderNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
D3D12Renderer(QQuickItem *item, QSGRenderNode *node);
|
D3D12RenderNode(QQuickItem *item);
|
||||||
~D3D12Renderer();
|
~D3D12RenderNode();
|
||||||
void init() override;
|
|
||||||
void render(const QSGRenderNode::RenderState *state) override;
|
void render(const RenderState *state) override;
|
||||||
|
void releaseResources() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init();
|
||||||
|
|
||||||
QQuickItem *m_item;
|
QQuickItem *m_item;
|
||||||
QSGRenderNode *m_node;
|
ID3D12Device *m_device = nullptr;
|
||||||
ID3D12Device *m_device;
|
|
||||||
ComPtr<ID3D12PipelineState> pipelineState;
|
ComPtr<ID3D12PipelineState> pipelineState;
|
||||||
ComPtr<ID3D12RootSignature> rootSignature;
|
ComPtr<ID3D12RootSignature> rootSignature;
|
||||||
ComPtr<ID3D12Resource> vertexBuffer;
|
ComPtr<ID3D12Resource> vertexBuffer;
|
||||||
ComPtr<ID3D12Resource> constantBuffer;
|
ComPtr<ID3D12Resource> constantBuffer;
|
||||||
D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
|
D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
|
||||||
quint8 *vbPtr;
|
quint8 *vbPtr = nullptr;
|
||||||
quint8 *cbPtr;
|
quint8 *cbPtr = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HAS_D3D12
|
#endif // HAS_D3D12
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "openglrenderer.h"
|
#include "openglrenderer.h"
|
||||||
|
#include <QQuickItem>
|
||||||
|
|
||||||
#ifndef QT_NO_OPENGL
|
#ifndef QT_NO_OPENGL
|
||||||
|
|
||||||
|
@ -46,13 +47,28 @@
|
||||||
#include <QOpenGLBuffer>
|
#include <QOpenGLBuffer>
|
||||||
#include <QOpenGLFunctions>
|
#include <QOpenGLFunctions>
|
||||||
|
|
||||||
OpenGLRenderer::OpenGLRenderer(QQuickItem *item, QSGRenderNode *node)
|
OpenGLRenderNode::OpenGLRenderNode(QQuickItem *item)
|
||||||
: m_item(item),
|
: m_item(item)
|
||||||
m_node(node)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderer::init()
|
OpenGLRenderNode::~OpenGLRenderNode()
|
||||||
|
{
|
||||||
|
releaseResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to reimplement changedStates() since our rendering is so simple,
|
||||||
|
// without involving any state changes.
|
||||||
|
|
||||||
|
void OpenGLRenderNode::releaseResources()
|
||||||
|
{
|
||||||
|
delete m_program;
|
||||||
|
m_program = nullptr;
|
||||||
|
delete m_vbo;
|
||||||
|
m_vbo = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLRenderNode::init()
|
||||||
{
|
{
|
||||||
m_program = new QOpenGLShaderProgram;
|
m_program = new QOpenGLShaderProgram;
|
||||||
|
|
||||||
|
@ -98,18 +114,15 @@ void OpenGLRenderer::init()
|
||||||
m_vbo->release();
|
m_vbo->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLRenderer::~OpenGLRenderer()
|
void OpenGLRenderNode::render(const RenderState *state)
|
||||||
{
|
{
|
||||||
delete m_program;
|
if (!m_program)
|
||||||
delete m_vbo;
|
init();
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLRenderer::render(const QSGRenderNode::RenderState *state)
|
|
||||||
{
|
|
||||||
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
||||||
|
|
||||||
m_program->bind();
|
m_program->bind();
|
||||||
m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *m_node->matrix());
|
m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *matrix());
|
||||||
|
|
||||||
m_vbo->bind();
|
m_vbo->bind();
|
||||||
|
|
||||||
|
|
|
@ -41,25 +41,27 @@
|
||||||
#ifndef OPENGLRENDERER_H
|
#ifndef OPENGLRENDERER_H
|
||||||
#define OPENGLRENDERER_H
|
#define OPENGLRENDERER_H
|
||||||
|
|
||||||
#include "customrenderitem.h"
|
|
||||||
#include <qsgrendernode.h>
|
#include <qsgrendernode.h>
|
||||||
|
|
||||||
#ifndef QT_NO_OPENGL
|
#ifndef QT_NO_OPENGL
|
||||||
|
|
||||||
|
class QQuickItem;
|
||||||
class QOpenGLShaderProgram;
|
class QOpenGLShaderProgram;
|
||||||
class QOpenGLBuffer;
|
class QOpenGLBuffer;
|
||||||
|
|
||||||
class OpenGLRenderer : public CustomRenderer
|
class OpenGLRenderNode : public QSGRenderNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenGLRenderer(QQuickItem *item, QSGRenderNode *node);
|
OpenGLRenderNode(QQuickItem *item);
|
||||||
~OpenGLRenderer();
|
~OpenGLRenderNode();
|
||||||
void init() override;
|
|
||||||
void render(const QSGRenderNode::RenderState *state) override;
|
void render(const RenderState *state) override;
|
||||||
|
void releaseResources() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init();
|
||||||
|
|
||||||
QQuickItem *m_item;
|
QQuickItem *m_item;
|
||||||
QSGRenderNode *m_node;
|
|
||||||
QOpenGLShaderProgram *m_program = nullptr;
|
QOpenGLShaderProgram *m_program = nullptr;
|
||||||
int m_matrixUniform;
|
int m_matrixUniform;
|
||||||
QOpenGLBuffer *m_vbo = nullptr;
|
QOpenGLBuffer *m_vbo = nullptr;
|
||||||
|
|
Loading…
Reference in New Issue