diff options
8 files changed, 243 insertions, 120 deletions
diff --git a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine.cpp b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine.cpp index a623956e72..c26bcfdd9e 100644 --- a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine.cpp +++ b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine.cpp @@ -286,6 +286,11 @@ void QSGD3D12Engine::setConstantBuffer(const quint8 *data, int size) d->setConstantBuffer(data, size); } +void QSGD3D12Engine::markConstantBufferDirty(int offset, int size) +{ + d->markConstantBufferDirty(offset, size); +} + void QSGD3D12Engine::queueViewport(const QRect &rect) { d->queueViewport(rect); @@ -333,6 +338,59 @@ quint32 QSGD3D12Engine::alignedConstantBufferSize(quint32 size) return (size + D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1); } +QSGD3D12Format QSGD3D12Engine::toDXGIFormat(QSGGeometry::Type sgtype, int tupleSize, int *size) +{ + QSGD3D12Format format = FmtUnknown; + + static const QSGD3D12Format formatMap_ub[] = { FmtUnknown, + FmtUNormByte, + FmtUNormByte2, + FmtUnknown, + FmtUNormByte4 }; + + static const QSGD3D12Format formatMap_f[] = { FmtUnknown, + FmtFloat, + FmtFloat2, + FmtFloat3, + FmtFloat4 }; + + switch (sgtype) { + case QSGGeometry::TypeUnsignedByte: + format = formatMap_ub[tupleSize]; + if (size) + *size = tupleSize; + break; + case QSGGeometry::TypeFloat: + format = formatMap_f[tupleSize]; + if (size) + *size = sizeof(float) * tupleSize; + break; + + case QSGGeometry::TypeUnsignedShort: + format = FmtUnsignedShort; + if (size) + *size = sizeof(ushort) * tupleSize; + break; + case QSGGeometry::TypeUnsignedInt: + format = FmtUnsignedInt; + if (size) + *size = sizeof(uint) * tupleSize; + break; + + case QSGGeometry::TypeByte: + case QSGGeometry::TypeInt: + case QSGGeometry::TypeShort: + qWarning("no mapping for GL type 0x%x", sgtype); + break; + + default: + qWarning("unknown GL type 0x%x", sgtype); + break; + } + + return format; +} + void QSGD3D12EnginePrivate::releaseResources() { if (!initialized) @@ -661,10 +719,33 @@ void QSGD3D12EnginePrivate::beginFrame() transitionResource(backBufferRT(), commandList.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); } +void QSGD3D12EnginePrivate::updateBuffer(StagingBufferRef *br, ID3D12Resource *r, const char *dbgstr) +{ + quint8 *p = nullptr; + const D3D12_RANGE readRange = { 0, 0 }; + if (!br->dirty.isEmpty()) { + if (FAILED(r->Map(0, &readRange, reinterpret_cast<void **>(&p)))) { + qWarning("Map failed for %s buffer of size %d", dbgstr, br->size); + return; + } + for (const auto &r : qAsConst(br->dirty)) { + qDebug("%s o %d s %d", dbgstr, r.first, r.second); + memcpy(p + r.first, br->p + r.first, r.second); + } + r->Unmap(0, nullptr); + br->dirty.clear(); + } +} + void QSGD3D12EnginePrivate::endFrame() { qDebug() << "***** end frame"; + // Now is the time to sync all the changed areas in the buffers. + updateBuffer(&vertexData, vertexBuffer.Get(), "vertex"); + updateBuffer(&indexData, indexBuffer.Get(), "index"); + updateBuffer(&constantData, constantBuffer.Get(), "constant"); + transitionResource(backBufferRT(), commandList.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); HRESULT hr = commandList->Close(); @@ -754,17 +835,21 @@ void QSGD3D12EnginePrivate::setPipelineState(const QSGD3D12PipelineState &pipeli psoDesc.RasterizerState = rastDesc; - // ### this is wrong - const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = { - TRUE, FALSE, - D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, - D3D12_BLEND_ZERO, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD, - D3D12_LOGIC_OP_NOOP, - D3D12_COLOR_WRITE_ENABLE_ALL - }; D3D12_BLEND_DESC blendDesc = {}; - blendDesc.RenderTarget[0] = defaultRenderTargetBlendDesc; - + if (pipelineState.premulBlend) { + const D3D12_RENDER_TARGET_BLEND_DESC premulBlendDesc = { + TRUE, FALSE, + D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, + D3D12_BLEND_INV_DEST_ALPHA, D3D12_BLEND_ONE, D3D12_BLEND_OP_ADD, + D3D12_LOGIC_OP_NOOP, + D3D12_COLOR_WRITE_ENABLE_ALL + }; + blendDesc.RenderTarget[0] = premulBlendDesc; + } else { + D3D12_RENDER_TARGET_BLEND_DESC noBlendDesc = {}; + noBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + blendDesc.RenderTarget[0] = noBlendDesc; + } psoDesc.BlendState = blendDesc; psoDesc.DepthStencilState.DepthEnable = pipelineState.depthEnable; @@ -796,21 +881,26 @@ void QSGD3D12EnginePrivate::setVertexBuffer(const quint8 *data, int size) { vertexData.p = data; vertexData.size = size; - vertexData.changed = true; + vertexData.fullChange = true; } void QSGD3D12EnginePrivate::setIndexBuffer(const quint8 *data, int size) { indexData.p = data; indexData.size = size; - indexData.changed = true; + indexData.fullChange = true; } void QSGD3D12EnginePrivate::setConstantBuffer(const quint8 *data, int size) { constantData.p = data; constantData.size = size; - constantData.changed = true; + constantData.fullChange = true; +} + +void QSGD3D12EnginePrivate::markConstantBufferDirty(int offset, int size) +{ + constantData.dirty.append(qMakePair(offset, size)); } void QSGD3D12EnginePrivate::queueViewport(const QRect &rect) @@ -847,72 +937,52 @@ void QSGD3D12EnginePrivate::queueDraw(QSGGeometry::DrawingMode mode, int count, int cboOffset, int startIndexIndex, QSGD3D12Format indexFormat) { - // Due to the simplistic way our current renderer works, we can just upload the - // entire vertex/index data in case it was rebuilt. - - if (vertexData.changed) { - vertexData.changed = false; - qDebug("upload vertex"); + // Ensure buffers are created but do not copy the data here, leave that to endFrame(). + if (vertexData.fullChange) { + vertexData.fullChange = false; // Only enlarge, never shrink const bool newBufferNeeded = vertexBuffer ? (vertexData.size > vertexBuffer->GetDesc().Width) : true; if (newBufferNeeded) { qDebug("new vertex buffer of size %d", vertexData.size); vertexBuffer.Attach(createBuffer(vertexData.size)); } - if (!vertexBuffer) - return; - quint8 *p = nullptr; - D3D12_RANGE readRange = { 0, 0 }; - if (FAILED(vertexBuffer->Map(0, &readRange, reinterpret_cast<void **>(&p)))) { - qWarning("Map failed for buffer of size %d", vertexData.size); + vertexData.dirty.clear(); + if (vertexBuffer) + vertexData.dirty.append(qMakePair(0, vertexData.size)); + else return; - } - memcpy(p, vertexData.p, vertexData.size); - vertexBuffer->Unmap(0, nullptr); } - if (indexData.changed) { - indexData.changed = false; + if (indexData.fullChange) { + indexData.fullChange = false; if (indexData.size > 0) { - qDebug("upload index"); const bool newBufferNeeded = indexBuffer ? (indexData.size > indexBuffer->GetDesc().Width) : true; if (newBufferNeeded) { qDebug("new index buffer of size %d", indexData.size); indexBuffer.Attach(createBuffer(indexData.size)); } - if (!indexBuffer) + indexData.dirty.clear(); + if (indexBuffer) + indexData.dirty.append(qMakePair(0, indexData.size)); + else return; - quint8 *p = nullptr; - D3D12_RANGE readRange = { 0, 0 }; - if (FAILED(indexBuffer->Map(0, &readRange, reinterpret_cast<void **>(&p)))) { - qWarning("Map failed for buffer of size %d", indexData.size); - return; - } - memcpy(p, indexData.p, indexData.size); - indexBuffer->Unmap(0, nullptr); } else { indexBuffer = nullptr; } } - if (constantData.changed) { - constantData.changed = false; - qDebug("upload constant"); + if (constantData.fullChange) { + constantData.fullChange = false; const bool newBufferNeeded = constantBuffer ? (constantData.size > constantBuffer->GetDesc().Width) : true; if (newBufferNeeded) { qDebug("new constant buffer of size %d", constantData.size); constantBuffer.Attach(createBuffer(constantData.size)); } - if (!constantBuffer) - return; - quint8 *p = nullptr; - D3D12_RANGE readRange = { 0, 0 }; - if (FAILED(constantBuffer->Map(0, &readRange, reinterpret_cast<void **>(&p)))) { - qWarning("Map failed for buffer of size %d", constantData.size); + constantData.dirty.clear(); + if (constantBuffer) + constantData.dirty.append(qMakePair(0, constantData.size)); + else return; - } - memcpy(p, constantData.p, constantData.size); - constantBuffer->Unmap(0, nullptr); } if (cboOffset >= 0 && constantBuffer) diff --git a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p.h b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p.h index d5f038fd0c..52ca80a002 100644 --- a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p.h +++ b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p.h @@ -200,6 +200,7 @@ public: void setVertexBuffer(const quint8 *data, int size); void setIndexBuffer(const quint8 *data, int size); void setConstantBuffer(const quint8 *data, int size); + void markConstantBufferDirty(int offset, int size); void queueViewport(const QRect &rect); void queueScissor(const QRect &rect); @@ -215,6 +216,7 @@ public: void waitGPU(); static quint32 alignedConstantBufferSize(quint32 size); + static QSGD3D12Format toDXGIFormat(QSGGeometry::Type sgtype, int tupleSize = 1, int *size = nullptr); private: QSGD3D12EnginePrivate *d; diff --git a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p_p.h b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p_p.h index 733444339c..fd72c4f064 100644 --- a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p_p.h +++ b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p_p.h @@ -150,6 +150,7 @@ public: void setVertexBuffer(const quint8 *data, int size); void setIndexBuffer(const quint8 *data, int size); void setConstantBuffer(const quint8 *data, int size); + void markConstantBufferDirty(int offset, int size); void queueViewport(const QRect &rect); void queueScissor(const QRect &rect); @@ -188,9 +189,13 @@ private: struct StagingBufferRef { const quint8 *p = nullptr; int size = 0; - bool changed = true; + bool fullChange = true; + QVector<QPair<int, int> > dirty; + StagingBufferRef() { dirty.reserve(256); } }; + void updateBuffer(StagingBufferRef *br, ID3D12Resource *r, const char *dbgstr); + bool initialized = false; QWindow *window = nullptr; int swapChainBufferCount = 2; diff --git a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12material.cpp b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12material.cpp index e7cee712d3..d5b5861280 100644 --- a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12material.cpp +++ b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12material.cpp @@ -40,8 +40,8 @@ #include "qsgd3d12material_p.h" #include <private/qsgrenderer_p.h> -#include "hlsl_vs_vertexcolor.h" -#include "hlsl_ps_vertexcolor.h" +#include "vs_vertexcolor.hlslh" +#include "ps_vertexcolor.hlslh" QT_BEGIN_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer.cpp b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer.cpp index b063138d74..2e55f7ec0e 100644 --- a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer.cpp +++ b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer.cpp @@ -39,7 +39,6 @@ #include "qsgd3d12renderer_p.h" #include "qsgd3d12rendercontext_p.h" -#include "qsgd3d12material_p.h" #include <private/qsgnodeupdater_p.h> QT_BEGIN_NAMESPACE @@ -81,15 +80,15 @@ void QSGD3D12Renderer::renderScene(GLuint fboId) QSGRenderer::renderScene(bindable); } -// Search through the node set and remove nodes that are leaves of other +// Search through the node set and remove nodes that are descendants of other // nodes in the same set. -static QSet<QSGNode *> qsg_filterSubTree(const QSet<QSGNode *> &nodes, QSGRootNode *root) +static QSet<QSGNode *> qsg_removeDescendants(const QSet<QSGNode *> &nodes, QSGRootNode *root) { QSet<QSGNode *> result = nodes; for (QSGNode *node : nodes) { QSGNode *n = node; while (n != root) { - if (result.contains(n)) { + if (n != node && result.contains(n)) { result.remove(node); break; } @@ -112,16 +111,42 @@ void QSGD3D12Renderer::updateMatrices(QSGNode *node, QSGTransformNode *xform) tn->setCombinedMatrix(tn->matrix()); QSGNODE_TRAVERSE(node) updateMatrices(child, tn); - } else { if (node->type() == QSGNode::GeometryNodeType || node->type() == QSGNode::ClipNodeType) { - static_cast<QSGBasicGeometryNode *>(node)->setMatrix(xform ? &xform->combinedMatrix() : 0); + m_nodeDirtyMap[node] |= QSGD3D12Material::RenderState::DirtyMatrix; + QSGBasicGeometryNode *gnode = static_cast<QSGBasicGeometryNode *>(node); + const QMatrix4x4 *newMatrix = xform ? &xform->combinedMatrix() : nullptr; + // NB the newMatrix ptr is usually the same as before as it just + // references the transform node's own matrix. + gnode->setMatrix(newMatrix); } QSGNODE_TRAVERSE(node) updateMatrices(child, xform); } } +void QSGD3D12Renderer::updateOpacities(QSGNode *node, float inheritedOpacity) +{ + if (node->isSubtreeBlocked()) + return; + + if (node->type() == QSGNode::OpacityNodeType) { + QSGOpacityNode *on = static_cast<QSGOpacityNode *>(node); + float combined = inheritedOpacity * on->opacity(); + on->setCombinedOpacity(combined); + QSGNODE_TRAVERSE(node) + updateOpacities(child, combined); + } else { + if (node->type() == QSGNode::GeometryNodeType) { + m_nodeDirtyMap[node] |= QSGD3D12Material::RenderState::DirtyOpacity; + QSGGeometryNode *gn = static_cast<QSGGeometryNode *>(node); + gn->setInheritedOpacity(inheritedOpacity); + } + QSGNODE_TRAVERSE(node) + updateOpacities(child, inheritedOpacity); + } +} + void QSGD3D12Renderer::buildRenderList(QSGNode *node, QSGClipNode *clip) { if (node->isSubtreeBlocked()) @@ -174,10 +199,12 @@ void QSGD3D12Renderer::render() m_engine->beginFrame(); if (m_rebuild) { - // This changes everything, so discard all cached states m_rebuild = false; + m_dirtyTransformNodes.clear(); m_dirtyTransformNodes.insert(rootNode()); + m_dirtyOpacityNodes.clear(); + m_dirtyOpacityNodes.insert(rootNode()); m_renderList.reset(); m_vboData.reset(); @@ -188,6 +215,7 @@ void QSGD3D12Renderer::render() m_engine->setVertexBuffer(m_vboData.data(), m_vboData.size()); m_engine->setIndexBuffer(m_iboData.data(), m_iboData.size()); + m_engine->setConstantBuffer(m_cboData.data(), m_cboData.size()); if (Q_UNLIKELY(debug_build())) { qDebug("renderList: %d elements in total", m_renderList.size()); @@ -199,7 +227,7 @@ void QSGD3D12Renderer::render() } if (m_dirtyTransformNodes.size()) { - const QSet<QSGNode *> subTreeRoots = qsg_filterSubTree(m_dirtyTransformNodes, rootNode()); + const QSet<QSGNode *> subTreeRoots = qsg_removeDescendants(m_dirtyTransformNodes, rootNode()); for (QSGNode *node : subTreeRoots) { // First find the parent transform so we have the accumulated // matrix up until this point. @@ -217,6 +245,23 @@ void QSGD3D12Renderer::render() } } + if (m_dirtyOpacityNodes.size()) { + const QSet<QSGNode *> subTreeRoots = qsg_removeDescendants(m_dirtyOpacityNodes, rootNode()); + for (QSGNode *node : subTreeRoots) { + float opacity = 1.0f; + QSGNode *n = node; + if (n->type() == QSGNode::OpacityNodeType) + n = node->parent(); + while (n != rootNode() && n->type() != QSGNode::OpacityNodeType) + n = n->parent(); + if (n != rootNode()) + opacity = static_cast<QSGOpacityNode *>(n)->combinedOpacity(); + + updateOpacities(node, opacity); + } + m_dirtyOpaqueElements = true; + } + if (m_dirtyOpaqueElements) { m_dirtyOpaqueElements = false; m_opaqueElements.clear(); @@ -231,9 +276,17 @@ void QSGD3D12Renderer::render() } } + // Build pipeline state and draw calls. renderElements(); + m_dirtyTransformNodes.clear(); + m_dirtyOpacityNodes.clear(); + m_dirtyOpaqueElements = false; + m_nodeDirtyMap.clear(); + + // Finalize buffers and execute commands. m_engine->endFrame(); + m_engine = nullptr; } @@ -279,6 +332,9 @@ void QSGD3D12Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) if (state & QSGNode::DirtyMatrix) m_dirtyTransformNodes << node; + if (state & QSGNode::DirtyOpacity) + m_dirtyOpacityNodes << node; + if (state & QSGNode::DirtyMaterial) m_dirtyOpaqueElements = true; @@ -302,11 +358,10 @@ void QSGD3D12Renderer::renderElements() m_current_projection_matrix = projectionMatrix(); // First do opaque... - // The algorithm is quite simple. We traverse the list back-to-from - // and for every item, we start a second traversal from this point - // and draw all elements which have identical material. Then we clear - // the bit for this in the rendered list so we don't draw it again - // when we come to that index. + // The algorithm is quite simple. We traverse the list back-to-front, and + // for every item we start a second traversal and draw all elements which + // have identical material. Then we clear the bit for this in the rendered + // list so we don't draw it again when we come to that index. QBitArray rendered = m_opaqueElements; for (int i = m_renderList.size() - 1; i >= 0; --i) { if (rendered.testBit(i)) { @@ -360,17 +415,16 @@ void QSGD3D12Renderer::renderElement(int elementIndex) if (gn->inheritedOpacity() < 0.001f) // pretty much invisible, don't draw it return; - QSGD3D12Material::RenderState::DirtyStates dirtyState = QSGD3D12Material::RenderState::DirtyMatrix; + // Update the QSGRenderer members which the materials will access. m_current_projection_matrix = projectionMatrix(); - qreal scale = 1.0 / m_renderList.size(); + const float scale = 1.0 / m_renderList.size(); m_current_projection_matrix(2, 2) = scale; m_current_projection_matrix(2, 3) = 1.0f - (elementIndex + 1) * scale; m_current_model_view_matrix = gn->matrix() ? *gn->matrix() : QMatrix4x4(); m_current_determinant = m_current_model_view_matrix.determinant(); - if (gn->inheritedOpacity() != m_current_opacity) { - m_current_opacity = gn->inheritedOpacity(); - dirtyState |= QSGD3D12Material::RenderState::DirtyOpacity; - } + m_current_opacity = gn->inheritedOpacity(); + + QSGD3D12Material::RenderState::DirtyStates dirtyState = m_nodeDirtyMap.value(e.node); const QSGGeometry *g = gn->geometry(); QSGD3D12Material *m = static_cast<QSGD3D12Material *>(gn->activeMaterial()); @@ -387,7 +441,7 @@ void QSGD3D12Renderer::renderElement(int elementIndex) if (e.cboSize > 0) cboPtr = m_cboData.data() + e.cboOffset; - qDebug() << "ds" << dirtyState; + qDebug() << "dirtystate for" << e.node << "is" << dirtyState; QSGD3D12Material::UpdateResults updRes = m->updatePipeline(QSGD3D12Material::makeRenderState(this, dirtyState), &m_pipelineState.shaders, cboPtr); @@ -396,7 +450,7 @@ void QSGD3D12Renderer::renderElement(int elementIndex) // root signature and communicate the need for SRVs or UAVs to the engine. if (updRes.testFlag(QSGD3D12Material::UpdatedConstantBuffer)) - m_engine->setConstantBuffer(m_cboData.data(), m_cboData.size()); + m_engine->markConstantBufferDirty(e.cboOffset, e.cboSize); // Input element layout m_pipelineState.inputElements.resize(g->attributeCount()); @@ -409,37 +463,11 @@ void QSGD3D12Renderer::renderElement(int elementIndex) const int tupleSize = attrs[i].tupleSize; ie.name = semanticNames[attrs[i].semantic]; ie.offset = offset; - // ### move format mapping to engine - static const QSGD3D12Format formatMap_ub[] = { FmtUnknown, - FmtUNormByte, - FmtUNormByte2, - FmtUnknown, - FmtUNormByte4 }; - static const QSGD3D12Format formatMap_f[] = { FmtUnknown, - FmtFloat, - FmtFloat2, - FmtFloat3, - FmtFloat4 }; - switch (attrs[i].type) { - case QSGGeometry::TypeUnsignedByte: - ie.format = formatMap_ub[tupleSize]; - offset += tupleSize; - break; - case QSGGeometry::TypeFloat: - ie.format = formatMap_f[tupleSize]; - offset += sizeof(float) * tupleSize; - break; - case QSGGeometry::TypeByte: - case QSGGeometry::TypeInt: - case QSGGeometry::TypeUnsignedInt: - case QSGGeometry::TypeShort: - case QSGGeometry::TypeUnsignedShort: - qFatal("QSGD3D12Renderer: attribute type 0x%x is not currently supported", attrs[i].type); - break; - } + int bytesPerTuple = 0; + ie.format = QSGD3D12Engine::toDXGIFormat(QSGGeometry::Type(attrs[i].type), tupleSize, &bytesPerTuple); if (ie.format == FmtUnknown) qFatal("QSGD3D12Renderer: unsupported tuple size for attribute type 0x%x", attrs[i].type); - + offset += bytesPerTuple; // There is one buffer with interleaved data so the slot is always 0. ie.slot = 0; } @@ -451,20 +479,10 @@ void QSGD3D12Renderer::renderElement(int elementIndex) m_engine->setPipelineState(m_pipelineState); if (e.iboOffset >= 0) { - // ### move format mapping to engine - QSGD3D12Format indexFormat; const QSGGeometry::Type indexType = QSGGeometry::Type(g->indexType()); - switch (indexType) { - case QSGGeometry::TypeUnsignedShort: - indexFormat = FmtUnsignedShort; - break; - case QSGGeometry::TypeUnsignedInt: - indexFormat = FmtUnsignedInt; - break; - default: - qFatal("QSGD3D12Renderer: unsupported index data type 0x%x", indexType); - break; - }; + const QSGD3D12Format indexFormat = QSGD3D12Engine::toDXGIFormat(indexType); + if (indexFormat == FmtUnknown) + qFatal("QSGD3D12Renderer: unsupported index type 0x%x", indexType); m_engine->queueDraw(QSGGeometry::DrawingMode(g->drawingMode()), g->indexCount(), e.vboOffset, g->sizeOfVertex(), e.cboOffset, e.iboOffset / e.iboStride, indexFormat); diff --git a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer_p.h b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer_p.h index a0ae99a2e0..e637dbbb9c 100644 --- a/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer_p.h +++ b/src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer_p.h @@ -54,6 +54,7 @@ #include <private/qsgrenderer_p.h> #include <QtGui/private/qdatabuffer_p.h> #include "qsgd3d12engine_p.h" +#include "qsgd3d12material_p.h" QT_BEGIN_NAMESPACE @@ -68,6 +69,7 @@ public: private: void updateMatrices(QSGNode *node, QSGTransformNode *xform); + void updateOpacities(QSGNode *node, float inheritedOpacity); void buildRenderList(QSGNode *node, QSGClipNode *clip); void renderElements(); void renderElement(int elementIndex); @@ -83,6 +85,7 @@ private: }; QSet<QSGNode *> m_dirtyTransformNodes; + QSet<QSGNode *> m_dirtyOpacityNodes; QBitArray m_opaqueElements; bool m_rebuild = true; bool m_dirtyOpaqueElements = true; @@ -94,6 +97,9 @@ private: QSGMaterialType *m_lastMaterialType = nullptr; QSGD3D12PipelineState m_pipelineState; + + typedef QHash<QSGNode *, QSGD3D12Material::RenderState::DirtyStates> NodeDirtyMap; + NodeDirtyMap m_nodeDirtyMap; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/d3d12/shaders/shaders.pri b/src/quick/scenegraph/adaptations/d3d12/shaders/shaders.pri index c3745cc682..6fc591cb33 100644 --- a/src/quick/scenegraph/adaptations/d3d12/shaders/shaders.pri +++ b/src/quick/scenegraph/adaptations/d3d12/shaders/shaders.pri @@ -1,10 +1,10 @@ vertexcolor_VSPS = $$PWD/vertexcolor.hlsl vertexcolor_vshader.input = vertexcolor_VSPS -vertexcolor_vshader.header = hlsl_vs_vertexcolor.h +vertexcolor_vshader.header = vs_vertexcolor.hlslh vertexcolor_vshader.entry = VS_VertexColor vertexcolor_vshader.type = vs_5_0 vertexcolor_pshader.input = vertexcolor_VSPS -vertexcolor_pshader.header = hlsl_ps_vertexcolor.h +vertexcolor_pshader.header = ps_vertexcolor.hlslh vertexcolor_pshader.entry = PS_VertexColor vertexcolor_pshader.type = ps_5_0 diff --git a/tests/manual/nodetypes/main.qml b/tests/manual/nodetypes/main.qml index c4d0a5266d..81d1e63ead 100644 --- a/tests/manual/nodetypes/main.qml +++ b/tests/manual/nodetypes/main.qml @@ -47,6 +47,28 @@ Item { anchors.centerIn: parent color: "red" NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; } + + Rectangle { + color: "gray" + width: 50 + height: 50 + anchors.centerIn: parent + + SequentialAnimation on opacity { + loops: Animation.Infinite + NumberAnimation { + from: 1.0 + to: 0.0 + duration: 4000 + } + NumberAnimation { + from: 0.0 + to: 1.0 + duration: 4000 + easing.type: Easing.InOutQuad + } + } + } } Rectangle { |