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:
Laszlo Agocs 2016-05-26 14:34:00 +02:00
parent 519032e9e0
commit e1682b84bb
6 changed files with 96 additions and 114 deletions

View File

@ -45,51 +45,6 @@
#include "openglrenderer.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)
: QQuickItem(parent)
{
@ -99,9 +54,26 @@ CustomRenderItem::CustomRenderItem(QQuickItem *parent)
QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
CustomRenderNode *n = static_cast<CustomRenderNode *>(node);
if (!node)
n = new CustomRenderNode(this);
QSGRenderNode *n = static_cast<QSGRenderNode *>(node);
if (!n) {
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;
}

View File

@ -42,29 +42,6 @@
#define CUSTOMRENDERITEM_H
#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
{

View File

@ -39,6 +39,7 @@
****************************************************************************/
#include "d3d12renderer.h"
#include <QQuickItem>
#include <QQuickWindow>
#include <QSGRendererInterface>
@ -47,15 +48,34 @@
#include "vs_shader.hlslh"
#include "ps_shader.hlslh"
D3D12Renderer::D3D12Renderer(QQuickItem *item, QSGRenderNode *node)
: m_item(item),
m_node(node),
vbPtr(nullptr),
cbPtr(nullptr)
D3D12RenderNode::D3D12RenderNode(QQuickItem *item)
: m_item(item)
{
}
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();
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)
vertexBuffer->Unmap(0, nullptr);
if (cbPtr)
constantBuffer->Unmap(0, nullptr);
}
if (!m_device)
init();
void D3D12Renderer::render(const QSGRenderNode::RenderState *state)
{
QSGRendererInterface *rif = m_item->window()->rendererInterface();
ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(rif->getResource(QSGRendererInterface::CommandList));
Q_ASSERT(commandList);
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);
const QPointF p0(m_item->width() - 1, m_item->height() - 1);

View File

@ -41,35 +41,38 @@
#ifndef D3D12RENDERER_H
#define D3D12RENDERER_H
#include "customrenderitem.h"
#include <qsgrendernode.h>
#ifdef HAS_D3D12
class QQuickItem;
#include <d3d12.h>
#include <wrl/client.h>
using namespace Microsoft::WRL;
class D3D12Renderer : public CustomRenderer
class D3D12RenderNode : public QSGRenderNode
{
public:
D3D12Renderer(QQuickItem *item, QSGRenderNode *node);
~D3D12Renderer();
void init() override;
void render(const QSGRenderNode::RenderState *state) override;
D3D12RenderNode(QQuickItem *item);
~D3D12RenderNode();
void render(const RenderState *state) override;
void releaseResources() override;
private:
void init();
QQuickItem *m_item;
QSGRenderNode *m_node;
ID3D12Device *m_device;
ID3D12Device *m_device = nullptr;
ComPtr<ID3D12PipelineState> pipelineState;
ComPtr<ID3D12RootSignature> rootSignature;
ComPtr<ID3D12Resource> vertexBuffer;
ComPtr<ID3D12Resource> constantBuffer;
D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
quint8 *vbPtr;
quint8 *cbPtr;
quint8 *vbPtr = nullptr;
quint8 *cbPtr = nullptr;
};
#endif // HAS_D3D12

View File

@ -39,6 +39,7 @@
****************************************************************************/
#include "openglrenderer.h"
#include <QQuickItem>
#ifndef QT_NO_OPENGL
@ -46,13 +47,28 @@
#include <QOpenGLBuffer>
#include <QOpenGLFunctions>
OpenGLRenderer::OpenGLRenderer(QQuickItem *item, QSGRenderNode *node)
: m_item(item),
m_node(node)
OpenGLRenderNode::OpenGLRenderNode(QQuickItem *item)
: m_item(item)
{
}
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;
@ -98,18 +114,15 @@ void OpenGLRenderer::init()
m_vbo->release();
}
OpenGLRenderer::~OpenGLRenderer()
void OpenGLRenderNode::render(const RenderState *state)
{
delete m_program;
delete m_vbo;
}
if (!m_program)
init();
void OpenGLRenderer::render(const QSGRenderNode::RenderState *state)
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
m_program->bind();
m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *m_node->matrix());
m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *matrix());
m_vbo->bind();

View File

@ -41,25 +41,27 @@
#ifndef OPENGLRENDERER_H
#define OPENGLRENDERER_H
#include "customrenderitem.h"
#include <qsgrendernode.h>
#ifndef QT_NO_OPENGL
class QQuickItem;
class QOpenGLShaderProgram;
class QOpenGLBuffer;
class OpenGLRenderer : public CustomRenderer
class OpenGLRenderNode : public QSGRenderNode
{
public:
OpenGLRenderer(QQuickItem *item, QSGRenderNode *node);
~OpenGLRenderer();
void init() override;
void render(const QSGRenderNode::RenderState *state) override;
OpenGLRenderNode(QQuickItem *item);
~OpenGLRenderNode();
void render(const RenderState *state) override;
void releaseResources() override;
private:
void init();
QQuickItem *m_item;
QSGRenderNode *m_node;
QOpenGLShaderProgram *m_program = nullptr;
int m_matrixUniform;
QOpenGLBuffer *m_vbo = nullptr;