aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine.cpp174
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/qsgd3d12engine_p_p.h7
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/qsgd3d12material.cpp4
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer.cpp144
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/qsgd3d12renderer_p.h6
-rw-r--r--src/quick/scenegraph/adaptations/d3d12/shaders/shaders.pri4
-rw-r--r--tests/manual/nodetypes/main.qml22
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 {