aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick/scenegraph
diff options
context:
space:
mode:
Diffstat (limited to 'examples/quick/scenegraph')
-rw-r--r--examples/quick/scenegraph/rendernode/customrenderitem.cpp158
-rw-r--r--examples/quick/scenegraph/rendernode/customrenderitem.h93
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.cpp229
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.h77
-rw-r--r--examples/quick/scenegraph/rendernode/main.cpp58
-rw-r--r--examples/quick/scenegraph/rendernode/main.qml96
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.cpp133
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.h70
-rw-r--r--examples/quick/scenegraph/rendernode/rendernode.pro37
-rw-r--r--examples/quick/scenegraph/rendernode/rendernode.qrc5
-rw-r--r--examples/quick/scenegraph/rendernode/shader.hlsl27
11 files changed, 983 insertions, 0 deletions
diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.cpp b/examples/quick/scenegraph/rendernode/customrenderitem.cpp
new file mode 100644
index 0000000000..124a57a5d6
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/customrenderitem.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "customrenderitem.h"
+#include <QQuickWindow>
+#include <QSGRendererInterface>
+
+#include "openglrenderer.h"
+#include "d3d12renderer.h"
+
+CustomRenderNode::~CustomRenderNode()
+{
+ releaseResources();
+}
+
+void CustomRenderNode::render(const RenderState *state)
+{
+ QSGRendererInterface *ri = m_item->window()->rendererInterface();
+ if (!ri)
+ return;
+
+ m_api = ri->graphicsAPI();
+
+ if (!m_renderer) {
+ switch (m_api) {
+ 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)
+{
+ // Our item shows something so set the flag.
+ setFlag(ItemHasContents);
+
+ // We want the graphics API type to be exposed to QML. The value is easy to
+ // get during rendering on the render thread in CustomRenderNode::render(),
+ // but is more tricky here since the item gets a window associated later,
+ // which in turn will get the underlying scenegraph started at some later
+ // point. So defer.
+ connect(this, &QQuickItem::windowChanged, this, &CustomRenderItem::onWindowChanged);
+}
+
+QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
+{
+ CustomRenderNode *n = static_cast<CustomRenderNode *>(node);
+ if (!node)
+ n = new CustomRenderNode(this);
+
+ return n;
+}
+
+void CustomRenderItem::onWindowChanged(QQuickWindow *w)
+{
+ if (w) {
+ if (w->isSceneGraphInitialized())
+ updateGraphicsAPI();
+ else
+ connect(w, &QQuickWindow::sceneGraphInitialized, this, &CustomRenderItem::updateGraphicsAPI);
+ } else {
+ updateGraphicsAPI();
+ }
+}
+
+void CustomRenderItem::updateGraphicsAPI()
+{
+ QString newAPI;
+ if (!window()) {
+ newAPI = QLatin1String("[no window]");
+ } else {
+ QSGRendererInterface *ri = window()->rendererInterface();
+ if (!ri) {
+ newAPI = QLatin1String("[no renderer interface]");
+ } else {
+ switch (ri->graphicsAPI()) {
+ case QSGRendererInterface::OpenGL:
+ newAPI = QLatin1String("OpenGL");
+ break;
+ case QSGRendererInterface::Direct3D12:
+ newAPI = QLatin1String("D3D12");
+ break;
+ default:
+ newAPI = QString(QLatin1String("[unsupported graphics API %1]")).arg(ri->graphicsAPI());
+ break;
+ }
+ }
+ }
+
+ if (newAPI != m_api) {
+ m_api = newAPI;
+ emit graphicsAPIChanged();
+ }
+}
diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.h b/examples/quick/scenegraph/rendernode/customrenderitem.h
new file mode 100644
index 0000000000..fb4c392148
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/customrenderitem.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOMRENDERITEM_H
+#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;
+ int m_api;
+ CustomRenderer *m_renderer = nullptr;
+};
+
+class CustomRenderItem : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QString graphicsAPI READ graphicsAPI NOTIFY graphicsAPIChanged)
+
+public:
+ CustomRenderItem(QQuickItem *parent = nullptr);
+
+ QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override;
+
+ QString graphicsAPI() const { return m_api; }
+
+private slots:
+ void onWindowChanged(QQuickWindow *w);
+ void updateGraphicsAPI();
+
+signals:
+ void graphicsAPIChanged();
+
+private:
+ QString m_api;
+};
+
+#endif
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
new file mode 100644
index 0000000000..a48719e5dd
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "d3d12renderer.h"
+#include <QQuickWindow>
+#include <QSGRendererInterface>
+
+#ifdef HAS_D3D12
+
+#include "vs_shader.hlslh"
+#include "ps_shader.hlslh"
+
+D3D12Renderer::D3D12Renderer(QQuickItem *item, QSGRenderNode *node)
+ : m_item(item),
+ m_node(node),
+ vbPtr(nullptr),
+ cbPtr(nullptr)
+{
+}
+
+void D3D12Renderer::init()
+{
+ QSGRendererInterface *rif = m_item->window()->rendererInterface();
+ m_device = static_cast<ID3D12Device *>(rif->getResource(QSGRendererInterface::Device));
+ Q_ASSERT(m_device);
+
+ D3D12_ROOT_PARAMETER rootParameter;
+ rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+ rootParameter.Descriptor.ShaderRegister = 0; // b0
+ rootParameter.Descriptor.RegisterSpace = 0;
+
+ D3D12_ROOT_SIGNATURE_DESC desc;
+ desc.NumParameters = 1;
+ desc.pParameters = &rootParameter;
+ desc.NumStaticSamplers = 0;
+ desc.pStaticSamplers = nullptr;
+ desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+
+ ComPtr<ID3DBlob> signature;
+ ComPtr<ID3DBlob> error;
+ if (FAILED(D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error))) {
+ qWarning("Failed to serialize root signature");
+ return;
+ }
+ if (FAILED(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(),
+ IID_PPV_ARGS(&rootSignature)))) {
+ qWarning("Failed to create root signature");
+ return;
+ }
+
+ D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
+ };
+
+ D3D12_SHADER_BYTECODE vshader;
+ vshader.pShaderBytecode = g_VS_Simple;
+ vshader.BytecodeLength = sizeof(g_VS_Simple);
+ D3D12_SHADER_BYTECODE pshader;
+ pshader.pShaderBytecode = g_PS_Simple;
+ pshader.BytecodeLength = sizeof(g_PS_Simple);
+
+ D3D12_RASTERIZER_DESC rastDesc = {};
+ rastDesc.FillMode = D3D12_FILL_MODE_SOLID;
+ rastDesc.CullMode = D3D12_CULL_MODE_BACK;
+ rastDesc.FrontCounterClockwise = TRUE; // Vertices are given CCW
+
+ // No blending, just enable color write.
+ D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = {};
+ defaultRenderTargetBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ D3D12_BLEND_DESC blendDesc = {};
+ blendDesc.RenderTarget[0] = defaultRenderTargetBlendDesc;
+
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+ psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
+ psoDesc.pRootSignature = rootSignature.Get();
+ psoDesc.VS = vshader;
+ psoDesc.PS = pshader;
+ psoDesc.RasterizerState = rastDesc;
+ psoDesc.BlendState = blendDesc;
+ // No depth. The correct stacking of the item is ensured by the projection matrix.
+ // Do not bother with stencil since we do not apply clipping in the
+ // example. If clipping is desired, render() needs to set a different PSO
+ // with stencil enabled whenever the RenderState indicates so.
+ psoDesc.SampleMask = UINT_MAX;
+ psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ psoDesc.NumRenderTargets = 1;
+ psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
+ psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; // not in use due to !DepthEnable, but this would be the correct format otherwise
+ psoDesc.SampleDesc.Count = 1;
+ if (FAILED(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)))) {
+ qWarning("Failed to create graphics pipeline state");
+ return;
+ }
+
+ const UINT vertexBufferSize = (2 + 3) * 3 * sizeof(float);
+
+ D3D12_HEAP_PROPERTIES heapProp = {};
+ heapProp.Type = D3D12_HEAP_TYPE_UPLOAD;
+
+ D3D12_RESOURCE_DESC bufDesc;
+ bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ bufDesc.Alignment = 0;
+ bufDesc.Width = vertexBufferSize;
+ bufDesc.Height = 1;
+ bufDesc.DepthOrArraySize = 1;
+ bufDesc.MipLevels = 1;
+ bufDesc.Format = DXGI_FORMAT_UNKNOWN;
+ bufDesc.SampleDesc.Count = 1;
+ bufDesc.SampleDesc.Quality = 0;
+ bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ bufDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ if (FAILED(m_device->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE, &bufDesc,
+ D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
+ IID_PPV_ARGS(&vertexBuffer)))) {
+ qWarning("Failed to create committed resource (vertex buffer)");
+ return;
+ }
+
+ vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
+ vertexBufferView.StrideInBytes = (2 + 3) * sizeof(float);
+ vertexBufferView.SizeInBytes = vertexBufferSize;
+
+ bufDesc.Width = 256;
+ if (FAILED(m_device->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE, &bufDesc,
+ D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
+ IID_PPV_ARGS(&constantBuffer)))) {
+ qWarning("Failed to create committed resource (constant buffer)");
+ return;
+ }
+
+ const D3D12_RANGE readRange = { 0, 0 };
+ if (FAILED(vertexBuffer->Map(0, &readRange, reinterpret_cast<void **>(&vbPtr)))) {
+ qWarning("Map failed");
+ return;
+ }
+
+ if (FAILED(constantBuffer->Map(0, &readRange, reinterpret_cast<void **>(&cbPtr)))) {
+ qWarning("Map failed (constant buffer)");
+ return;
+ }
+}
+
+D3D12Renderer::~D3D12Renderer()
+{
+ if (vbPtr)
+ vertexBuffer->Unmap(0, nullptr);
+ if (cbPtr)
+ constantBuffer->Unmap(0, nullptr);
+}
+
+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 + msize, state->projectionMatrix()->constData(), msize);
+
+ const QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ const QPointF p1(0, 0);
+ const QPointF p2(0, m_item->height() - 1);
+
+ float *vp = reinterpret_cast<float *>(vbPtr);
+ *vp++ = p0.x();
+ *vp++ = p0.y();
+ *vp++ = 1.0f; *vp++ = 0.0f; *vp++ = 0.0f;
+
+ *vp++ = p1.x();
+ *vp++ = p1.y();
+ *vp++ = 0.0f; *vp++ = 1.0f; *vp++ = 0.0f;
+
+ *vp++ = p2.x();
+ *vp++ = p2.y();
+ *vp++ = 0.0f; *vp++ = 0.0f; *vp++ = 1.0f;
+
+ commandList->SetPipelineState(pipelineState.Get());
+ commandList->SetGraphicsRootSignature(rootSignature.Get());
+ commandList->SetGraphicsRootConstantBufferView(0, constantBuffer->GetGPUVirtualAddress());
+ commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ commandList->IASetVertexBuffers(0, 1, &vertexBufferView);
+
+ commandList->DrawInstanced(3, 1, 0, 0);
+
+ // we won't implement changedStates() since no viewport/scissor/stencil/blend related commands were added
+}
+
+#endif // HAS_D3D12
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.h b/examples/quick/scenegraph/rendernode/d3d12renderer.h
new file mode 100644
index 0000000000..365b483422
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef D3D12RENDERER_H
+#define D3D12RENDERER_H
+
+#include "customrenderitem.h"
+#include <qsgrendernode.h>
+
+#ifdef HAS_D3D12
+
+#include <d3d12.h>
+#include <wrl/client.h>
+
+using namespace Microsoft::WRL;
+
+class D3D12Renderer : public CustomRenderer
+{
+public:
+ D3D12Renderer(QQuickItem *item, QSGRenderNode *node);
+ ~D3D12Renderer();
+ void init() override;
+ void render(const QSGRenderNode::RenderState *state) override;
+
+private:
+ QQuickItem *m_item;
+ QSGRenderNode *m_node;
+ ID3D12Device *m_device;
+ ComPtr<ID3D12PipelineState> pipelineState;
+ ComPtr<ID3D12RootSignature> rootSignature;
+ ComPtr<ID3D12Resource> vertexBuffer;
+ ComPtr<ID3D12Resource> constantBuffer;
+ D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
+ quint8 *vbPtr;
+ quint8 *cbPtr;
+};
+
+#endif // HAS_D3D12
+
+#endif
diff --git a/examples/quick/scenegraph/rendernode/main.cpp b/examples/quick/scenegraph/rendernode/main.cpp
new file mode 100644
index 0000000000..9128cdc5be
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+#include "customrenderitem.h"
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<CustomRenderItem>("SceneGraphRendering", 2, 0, "CustomRenderItem");
+
+ QQuickView view;
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:///scenegraph/rendernode/main.qml"));
+ view.resize(1024, 768);
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/quick/scenegraph/rendernode/main.qml b/examples/quick/scenegraph/rendernode/main.qml
new file mode 100644
index 0000000000..32154cc930
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/main.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import SceneGraphRendering 2.0
+
+Item {
+ Rectangle {
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ CustomRenderItem {
+ id: renderer
+ anchors.fill: parent
+ anchors.margins: 10
+
+ transform: [
+ Rotation { id: rotation; axis.x: 0; axis.z: 0; axis.y: 1; angle: 0; origin.x: renderer.width / 2; origin.y: renderer.height / 2; },
+ Translate { id: txOut; x: -renderer.width / 2; y: -renderer.height / 2 },
+ Scale { id: scale; },
+ Translate { id: txIn; x: renderer.width / 2; y: renderer.height / 2 }
+ ]
+ }
+
+ SequentialAnimation {
+ PauseAnimation { duration: 3000 }
+ ParallelAnimation {
+ NumberAnimation { target: scale; property: "xScale"; to: 0.6; duration: 1000; easing.type: Easing.InOutBack }
+ NumberAnimation { target: scale; property: "yScale"; to: 0.6; duration: 1000; easing.type: Easing.InOutBack }
+ }
+ NumberAnimation { target: rotation; property: "angle"; to: 80; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: rotation; property: "angle"; to: -80; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: rotation; property: "angle"; to: 0; duration: 1000; easing.type: Easing.InOutCubic }
+ NumberAnimation { target: renderer; property: "opacity"; to: 0.5; duration: 1000; easing.type: Easing.InOutCubic }
+ PauseAnimation { duration: 1000 }
+ NumberAnimation { target: renderer; property: "opacity"; to: 0.8; duration: 1000; easing.type: Easing.InOutCubic }
+ ParallelAnimation {
+ NumberAnimation { target: scale; property: "xScale"; to: 1; duration: 1000; easing.type: Easing.InOutBack }
+ NumberAnimation { target: scale; property: "yScale"; to: 1; duration: 1000; easing.type: Easing.InOutBack }
+ }
+ running: true
+ loops: Animation.Infinite
+ }
+
+ Text {
+ id: label
+ anchors.bottom: renderer.bottom
+ anchors.left: renderer.left
+ anchors.right: renderer.right
+ anchors.margins: 20
+ wrapMode: Text.WordWrap
+ text: "Custom rendering via the graphics API " + renderer.graphicsAPI
+ color: "yellow"
+ }
+ }
+}
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
new file mode 100644
index 0000000000..e9c1be071c
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "openglrenderer.h"
+
+#ifndef QT_NO_OPENGL
+
+#include <QOpenGLShaderProgram>
+#include <QOpenGLBuffer>
+#include <QOpenGLFunctions>
+
+OpenGLRenderer::OpenGLRenderer(QQuickItem *item, QSGRenderNode *node)
+ : m_item(item),
+ m_node(node)
+{
+}
+
+void OpenGLRenderer::init()
+{
+ m_program = new QOpenGLShaderProgram;
+
+ static const char *vertexShaderSource =
+ "attribute highp vec4 posAttr;\n"
+ "attribute lowp vec4 colAttr;\n"
+ "varying lowp vec4 col;\n"
+ "uniform highp mat4 matrix;\n"
+ "void main() {\n"
+ " col = colAttr;\n"
+ " gl_Position = matrix * posAttr;\n"
+ "}\n";
+
+ static const char *fragmentShaderSource =
+ "varying lowp vec4 col;\n"
+ "void main() {\n"
+ " gl_FragColor = col;\n"
+ "}\n";
+
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
+ m_program->bindAttributeLocation("posAttr", 0);
+ m_program->bindAttributeLocation("colAttr", 1);
+ m_program->link();
+
+ m_matrixUniform = m_program->uniformLocation("matrix");
+
+ const int VERTEX_SIZE = 6 * sizeof(GLfloat);
+
+ // A fully featured renderer should also take inheritedOpacity() into account
+ // and blend, but ignore that for now.
+ static GLfloat colors[] = {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f
+ };
+
+ m_vbo = new QOpenGLBuffer;
+ m_vbo->create();
+ m_vbo->bind();
+ m_vbo->allocate(VERTEX_SIZE + sizeof(colors));
+ m_vbo->write(VERTEX_SIZE, colors, sizeof(colors));
+ m_vbo->release();
+}
+
+OpenGLRenderer::~OpenGLRenderer()
+{
+ delete m_program;
+ delete m_vbo;
+}
+
+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_vbo->bind();
+
+ QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ QPointF p1(0, 0);
+ QPointF p2(0, m_item->height() - 1);
+
+ GLfloat vertices[6] = { GLfloat(p0.x()), GLfloat(p0.y()),
+ GLfloat(p1.x()), GLfloat(p1.y()),
+ GLfloat(p2.x()), GLfloat(p2.y()) };
+ m_vbo->write(0, vertices, sizeof(vertices));
+
+ m_program->setAttributeBuffer(0, GL_FLOAT, 0, 2);
+ m_program->setAttributeBuffer(1, GL_FLOAT, sizeof(vertices), 3);
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+
+ f->glDrawArrays(GL_TRIANGLES, 0, 3);
+}
+
+#endif // QT_NO_OPENGL
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.h b/examples/quick/scenegraph/rendernode/openglrenderer.h
new file mode 100644
index 0000000000..d445b35c1e
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OPENGLRENDERER_H
+#define OPENGLRENDERER_H
+
+#include "customrenderitem.h"
+#include <qsgrendernode.h>
+
+#ifndef QT_NO_OPENGL
+
+class QOpenGLShaderProgram;
+class QOpenGLBuffer;
+
+class OpenGLRenderer : public CustomRenderer
+{
+public:
+ OpenGLRenderer(QQuickItem *item, QSGRenderNode *node);
+ ~OpenGLRenderer();
+ void init() override;
+ void render(const QSGRenderNode::RenderState *state) override;
+
+private:
+ QQuickItem *m_item;
+ QSGRenderNode *m_node;
+ QOpenGLShaderProgram *m_program = nullptr;
+ int m_matrixUniform;
+ QOpenGLBuffer *m_vbo = nullptr;
+};
+
+#endif // QT_NO_OPENGL
+
+#endif
diff --git a/examples/quick/scenegraph/rendernode/rendernode.pro b/examples/quick/scenegraph/rendernode/rendernode.pro
new file mode 100644
index 0000000000..d7ae715a7d
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/rendernode.pro
@@ -0,0 +1,37 @@
+QT += qml quick
+
+HEADERS += customrenderitem.h \
+ openglrenderer.h
+
+SOURCES += customrenderitem.cpp \
+ openglrenderer.cpp \
+ main.cpp
+
+RESOURCES += rendernode.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/rendernode
+INSTALLS += target
+
+OTHER_FILES += \
+ main.qml \
+ shader.hlsl
+
+config_d3d12 {
+ DEFINES += HAS_D3D12
+ HEADERS += d3d12renderer.h
+ SOURCES += d3d12renderer.cpp
+ LIBS += -ld3d12
+
+ VSPS = shader.hlsl
+ vshader.input = VSPS
+ vshader.header = vs_shader.hlslh
+ vshader.entry = VS_Simple
+ vshader.type = vs_5_0
+ pshader.input = VSPS
+ pshader.header = ps_shader.hlslh
+ pshader.entry = PS_Simple
+ pshader.type = ps_5_0
+
+ HLSL_SHADERS = vshader pshader
+ load(hlsl_bytecode_header)
+}
diff --git a/examples/quick/scenegraph/rendernode/rendernode.qrc b/examples/quick/scenegraph/rendernode/rendernode.qrc
new file mode 100644
index 0000000000..3674baccd8
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/rendernode.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/scenegraph/rendernode">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/scenegraph/rendernode/shader.hlsl b/examples/quick/scenegraph/rendernode/shader.hlsl
new file mode 100644
index 0000000000..8b9b9ff9d8
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/shader.hlsl
@@ -0,0 +1,27 @@
+cbuffer ConstantBuffer : register(b0)
+{
+ float4x4 modelview;
+ float4x4 projection;
+};
+
+struct PSInput
+{
+ float4 position : SV_POSITION;
+ float4 color : COLOR;
+};
+
+PSInput VS_Simple(float4 position : POSITION, float4 color : COLOR)
+{
+ PSInput result;
+
+ float4x4 mvp = mul(projection, modelview);
+ result.position = mul(mvp, position);
+ result.color = color;
+
+ return result;
+}
+
+float4 PS_Simple(PSInput input) : SV_TARGET
+{
+ return input.color;
+}