diff options
Diffstat (limited to 'examples/quick/scenegraph')
-rw-r--r-- | examples/quick/scenegraph/customgeometry/beziercurve.cpp | 2 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/customrenderitem.cpp | 107 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/customrenderitem.h | 78 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/d3d12renderer.cpp | 229 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/d3d12renderer.h | 77 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/main.cpp | 58 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/main.qml | 97 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/openglrenderer.cpp | 133 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/openglrenderer.h | 70 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/rendernode.pro | 37 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/rendernode.qrc | 5 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/shader.hlsl | 27 | ||||
-rw-r--r-- | examples/quick/scenegraph/scenegraph.pro | 23 |
13 files changed, 934 insertions, 9 deletions
diff --git a/examples/quick/scenegraph/customgeometry/beziercurve.cpp b/examples/quick/scenegraph/customgeometry/beziercurve.cpp index 14e78f8d21..ca3c6f524b 100644 --- a/examples/quick/scenegraph/customgeometry/beziercurve.cpp +++ b/examples/quick/scenegraph/customgeometry/beziercurve.cpp @@ -135,7 +135,7 @@ QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) //! [4] //! [5] geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount); geometry->setLineWidth(2); - geometry->setDrawingMode(GL_LINE_STRIP); + geometry->setDrawingMode(QSGGeometry::DrawLineStrip); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); //! [5] //! [6] diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.cpp b/examples/quick/scenegraph/rendernode/customrenderitem.cpp new file mode 100644 index 0000000000..dbb9ee79e8 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/customrenderitem.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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; + + 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) +{ + // Our item shows something so set the flag. + setFlag(ItemHasContents); +} + +QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) +{ + CustomRenderNode *n = static_cast<CustomRenderNode *>(node); + if (!node) + n = new CustomRenderNode(this); + + return n; +} diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.h b/examples/quick/scenegraph/rendernode/customrenderitem.h new file mode 100644 index 0000000000..b9828adaeb --- /dev/null +++ b/examples/quick/scenegraph/rendernode/customrenderitem.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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; + CustomRenderer *m_renderer = nullptr; +}; + +class CustomRenderItem : public QQuickItem +{ + Q_OBJECT + +public: + CustomRenderItem(QQuickItem *parent = nullptr); + QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override; +}; + +#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..bae77aabd3 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/main.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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.8 // for RendererInfo +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 + property int api: RendererInfo.api + text: "Custom rendering via the graphics API " + (api === RendererInfo.OpenGL ? "OpenGL" : (api === RendererInfo.Direct3D12 ? "Direct3D 12" : "")) + 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; +} diff --git a/examples/quick/scenegraph/scenegraph.pro b/examples/quick/scenegraph/scenegraph.pro index cf50cdb903..1015d7be3d 100644 --- a/examples/quick/scenegraph/scenegraph.pro +++ b/examples/quick/scenegraph/scenegraph.pro @@ -1,14 +1,21 @@ TEMPLATE = subdirs + +contains(QT_CONFIG, opengl(es1|es2)?) { + SUBDIRS += \ + graph \ + simplematerial \ + sgengine \ + textureinsgnode \ + openglunderqml \ + textureinsgnode \ + textureinthread \ + twotextureproviders +} + SUBDIRS += \ customgeometry \ - graph \ - openglunderqml \ - sgengine \ - simplematerial \ - textureinsgnode \ - textureinthread \ - threadedanimation \ - twotextureproviders + rendernode \ + threadedanimation EXAMPLE_FILES += \ shared |