diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/qml/qml.pro | 12 | ||||
-rw-r--r-- | examples/quick/quick.pro | 11 | ||||
-rw-r--r-- | examples/quick/scenegraph/customgeometry/beziercurve.cpp | 2 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/customrenderitem.cpp | 79 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/customrenderitem.h | 55 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/d3d12renderer.cpp | 260 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/d3d12renderer.h | 80 | ||||
-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 | 154 | ||||
-rw-r--r-- | examples/quick/scenegraph/rendernode/openglrenderer.h | 74 | ||||
-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 | 28 | ||||
-rw-r--r-- | examples/quick/scenegraph/scenegraph.pro | 23 |
15 files changed, 959 insertions, 16 deletions
diff --git a/examples/qml/qml.pro b/examples/qml/qml.pro index eb4c98e5c4..4ed935f92f 100644 --- a/examples/qml/qml.pro +++ b/examples/qml/qml.pro @@ -1,9 +1,13 @@ TEMPLATE = subdirs -qtHaveModule(quick): SUBDIRS += \ - networkaccessmanagerfactory \ - qmlextensionplugins \ - xmlhttprequest +qtHaveModule(quick) { + SUBDIRS += \ + qmlextensionplugins \ + xmlhttprequest + + !no_network: SUBDIRS += \ + networkaccessmanagerfactory +} SUBDIRS += \ referenceexamples \ diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro index 63730e53da..b164bf4f5b 100644 --- a/examples/quick/quick.pro +++ b/examples/quick/quick.pro @@ -16,7 +16,6 @@ SUBDIRS = quick-accessibility \ scenegraph \ shadereffects \ text \ - textureprovider \ threading \ touchinteraction \ tutorials \ @@ -25,8 +24,14 @@ SUBDIRS = quick-accessibility \ imageresponseprovider \ window \ particles \ - demos \ - rendercontrol + demos + +#OpenGL Support Required +contains(QT_CONFIG, opengl(es1|es2)?) { + SUBDIRS += \ + textureprovider \ + rendercontrol +} # Widget dependent examples qtHaveModule(widgets) { 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..433f3c5a1e --- /dev/null +++ b/examples/quick/scenegraph/rendernode/customrenderitem.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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" + +CustomRenderItem::CustomRenderItem(QQuickItem *parent) + : QQuickItem(parent) +{ + // Our item shows something so set the flag. + setFlag(ItemHasContents); +} + +QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) +{ + 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; +} diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.h b/examples/quick/scenegraph/rendernode/customrenderitem.h new file mode 100644 index 0000000000..43b0b00ed5 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/customrenderitem.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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> + +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..bc03720407 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** 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 <QQuickItem> +#include <QQuickWindow> +#include <QSGRendererInterface> + +#ifdef HAS_D3D12 + +#include "vs_shader.hlslh" +#include "ps_shader.hlslh" + +D3D12RenderNode::D3D12RenderNode(QQuickItem *item) + : m_item(item) +{ +} + +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)); + Q_ASSERT(m_device); + + D3D12_ROOT_PARAMETER rootParameter; + rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + 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 + + // Enable color write and blending (premultiplied alpha). The latter is + // needed because the example changes the item's opacity and we pass + // inheritedOpacity() into the pixel shader. If that wasn't the case, + // blending could have stayed disabled. + const D3D12_RENDER_TARGET_BLEND_DESC premulBlendDesc = { + TRUE, FALSE, + D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, + D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL + }; + D3D12_BLEND_DESC blendDesc = {}; + blendDesc.RenderTarget[0] = premulBlendDesc; + + 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 = vertexBufferSize / 3; + 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; + } + + float *vp = reinterpret_cast<float *>(vbPtr); + vp += 2; + *vp++ = 1.0f; *vp++ = 0.0f; *vp++ = 0.0f; + vp += 2; + *vp++ = 0.0f; *vp++ = 1.0f; *vp++ = 0.0f; + vp += 2; + *vp++ = 0.0f; *vp++ = 0.0f; *vp++ = 1.0f; +} + +void D3D12RenderNode::render(const RenderState *state) +{ + if (!m_device) + init(); + + 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, matrix()->constData(), msize); + memcpy(cbPtr + msize, state->projectionMatrix()->constData(), msize); + const float opacity = inheritedOpacity(); + memcpy(cbPtr + 2 * msize, &opacity, sizeof(float)); + + 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 += 3; + *vp++ = p1.x(); + *vp++ = p1.y(); + vp += 3; + *vp++ = p2.x(); + *vp++ = p2.y(); + + 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); +} + +// No need to reimplement changedStates() because no relevant commands are +// added to the command list in render(). + +#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..a81db0f398 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/d3d12renderer.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 <qsgrendernode.h> + +#ifdef HAS_D3D12 + +class QQuickItem; + +#include <d3d12.h> +#include <wrl/client.h> + +using namespace Microsoft::WRL; + +class D3D12RenderNode : public QSGRenderNode +{ +public: + D3D12RenderNode(QQuickItem *item); + ~D3D12RenderNode(); + + void render(const RenderState *state) override; + void releaseResources() override; + +private: + void init(); + + QQuickItem *m_item; + ID3D12Device *m_device = nullptr; + ComPtr<ID3D12PipelineState> pipelineState; + ComPtr<ID3D12RootSignature> rootSignature; + ComPtr<ID3D12Resource> vertexBuffer; + ComPtr<ID3D12Resource> constantBuffer; + D3D12_VERTEX_BUFFER_VIEW vertexBufferView; + quint8 *vbPtr = nullptr; + quint8 *cbPtr = nullptr; +}; + +#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..a91656dfaa --- /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 +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.1; duration: 1000; easing.type: Easing.InOutCubic } + PauseAnimation { duration: 1000 } + NumberAnimation { target: renderer; property: "opacity"; to: 1.0; 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: GraphicsInfo.api + text: "Custom rendering via the graphics API " + (api === GraphicsInfo.OpenGL ? "OpenGL" : (api === GraphicsInfo.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..3eff70cb42 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** 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" +#include <QQuickItem> + +#ifndef QT_NO_OPENGL + +#include <QOpenGLShaderProgram> +#include <QOpenGLBuffer> +#include <QOpenGLFunctions> + +OpenGLRenderNode::OpenGLRenderNode(QQuickItem *item) + : m_item(item) +{ +} + +OpenGLRenderNode::~OpenGLRenderNode() +{ + releaseResources(); +} + +void OpenGLRenderNode::releaseResources() +{ + delete m_program; + m_program = nullptr; + delete m_vbo; + m_vbo = nullptr; +} + +void OpenGLRenderNode::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" + "uniform lowp float opacity;\n" + "void main() {\n" + " gl_FragColor = col * opacity;\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"); + m_opacityUniform = m_program->uniformLocation("opacity"); + + 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(); +} + +void OpenGLRenderNode::render(const RenderState *state) +{ + if (!m_program) + init(); + + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + + m_program->bind(); + m_program->setUniformValue(m_matrixUniform, *state->projectionMatrix() * *matrix()); + m_program->setUniformValue(m_opacityUniform, float(inheritedOpacity())); + + 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->glEnable(GL_BLEND); + f->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + f->glDrawArrays(GL_TRIANGLES, 0, 3); +} + +QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const +{ + return BlendState; +} + +#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..28d528e617 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/openglrenderer.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 <qsgrendernode.h> + +#ifndef QT_NO_OPENGL + +class QQuickItem; +class QOpenGLShaderProgram; +class QOpenGLBuffer; + +class OpenGLRenderNode : public QSGRenderNode +{ +public: + OpenGLRenderNode(QQuickItem *item); + ~OpenGLRenderNode(); + + void render(const RenderState *state) override; + void releaseResources() override; + StateFlags changedStates() const override; + +private: + void init(); + + QQuickItem *m_item; + QOpenGLShaderProgram *m_program = nullptr; + int m_matrixUniform; + int m_opacityUniform; + 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..f300fe7aa5 --- /dev/null +++ b/examples/quick/scenegraph/rendernode/shader.hlsl @@ -0,0 +1,28 @@ +cbuffer ConstantBuffer : register(b0) +{ + float4x4 modelview; + float4x4 projection; + float opacity; +}; + +struct PSInput +{ + float4 position : SV_POSITION; + float3 color : COLOR; +}; + +PSInput VS_Simple(float4 position : POSITION, float3 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 float4(input.color, 1.0) * opacity; +} 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 |