aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/scenegraph
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-04-29 13:27:02 +0200
committerAndy Nichols <andy.nichols@qt.io>2016-04-30 20:22:20 +0000
commitdc5b2fd31ccf36f5f6e0ec3a7222bda023c6b1eb (patch)
tree72900fdd6fc301a72ec7cc527d64cf456212acc3 /src/plugins/scenegraph
parent5568a79fdd742761bae660137b3e6d4795100ff0 (diff)
D3D12: qt_SubRect_<name> support
Change-Id: I2b5d1211ed97909a03d92d115eb057ce9e710d12 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/plugins/scenegraph')
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp90
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h7
2 files changed, 87 insertions, 10 deletions
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp
index 856b49d2ac..dbdc876930 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp
@@ -73,6 +73,7 @@ void QSGD3D12ShaderLinker::reset(const QByteArray &vertBlob, const QByteArray &f
constants.clear();
samplers.clear();
textures.clear();
+ textureNameMap.clear();
}
void QSGD3D12ShaderLinker::feedVertexInput(const QSGShaderEffectNode::ShaderData &shader)
@@ -113,7 +114,12 @@ void QSGD3D12ShaderLinker::feedConstants(const QSGShaderEffectNode::ShaderData &
Constant c;
c.size = var.size;
c.specialType = vd.specialType;
- c.value = vd.value;
+ if (c.specialType != QSGShaderEffectNode::VariableData::SubRect) {
+ c.value = vd.value;
+ } else {
+ Q_ASSERT(var.name.startsWith(QByteArrayLiteral("qt_SubRect_")));
+ c.value = var.name.mid(11);
+ }
constants[var.offset] = c;
}
}
@@ -144,11 +150,33 @@ void QSGD3D12ShaderLinker::feedTextures(const QSGShaderEffectNode::ShaderData &s
if (var.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Texture) {
Q_ASSERT(vd.specialType == QSGShaderEffectNode::VariableData::Source);
textures.insert(var.bindPoint, vd.value);
+ textureNameMap.insert(var.name, var.bindPoint);
}
}
} else {
- for (int idx : *dirtyIndices)
- textures.insert(shader.shaderInfo.variables.at(idx).bindPoint, shader.varData.at(idx).value);
+ for (int idx : *dirtyIndices) {
+ const auto &var(shader.shaderInfo.variables.at(idx));
+ const auto &vd(shader.varData.at(idx));
+ textures.insert(var.bindPoint, vd.value);
+ textureNameMap.insert(var.name, var.bindPoint);
+ }
+ }
+}
+
+void QSGD3D12ShaderLinker::linkTextureSubRects()
+{
+ // feedConstants stores <name> in Constant::value for subrect entries. Now
+ // that both constants and textures are known, replace the name with the
+ // texture bind point.
+ for (Constant &c : constants) {
+ if (c.specialType == QSGShaderEffectNode::VariableData::SubRect) {
+ if (c.value.type() == QMetaType::QByteArray) {
+ const QByteArray name = c.value.toByteArray();
+ if (!textureNameMap.contains(name))
+ qWarning("ShaderEffect: qt_SubRect_%s refers to unknown source texture", qPrintable(name));
+ c.value = textureNameMap[name];
+ }
+ }
}
}
@@ -234,6 +262,16 @@ QSGMaterialType *QSGD3D12ShaderEffectMaterial::type() const
return mtype;
}
+static bool hasAtlasTexture(const QVector<QSGTextureProvider *> &textureProviders)
+{
+ for (int i = 0; i < textureProviders.count(); ++i) {
+ QSGTextureProvider *t = textureProviders.at(i);
+ if (t && t->texture() && t->texture()->isAtlasTexture())
+ return true;
+ }
+ return false;
+}
+
int QSGD3D12ShaderEffectMaterial::compare(const QSGMaterial *other) const
{
Q_ASSERT(other && type() == other->type());
@@ -248,6 +286,10 @@ int QSGD3D12ShaderEffectMaterial::compare(const QSGMaterial *other) const
if (linker.constants != o->linker.constants)
return 1;
+ if ((hasAtlasTexture(textureProviders) && !geometryUsesTextureSubRect)
+ || (hasAtlasTexture(o->textureProviders) && !o->geometryUsesTextureSubRect))
+ return 1;
+
for (int i = 0; i < textureProviders.count(); ++i) {
QSGTextureProvider *tp1 = textureProviders.at(i);
QSGTextureProvider *tp2 = o->textureProviders.at(i);
@@ -309,6 +351,16 @@ QSGD3D12Material::UpdateResults QSGD3D12ShaderEffectMaterial::updatePipeline(con
memcpy(dst, state.combinedMatrix().constData(), sz);
r |= UpdatedConstantBuffer;
}
+ } else if (c.specialType == QSGShaderEffectNode::VariableData::SubRect) {
+ // float4
+ QRectF subRect(0, 0, 1, 1);
+ int srcBindPoint = c.value.toInt(); // filled in by linkTextureSubRects
+ if (QSGTexture *t = textureProviders.at(srcBindPoint)->texture())
+ subRect = t->normalizedTextureSubRect();
+ const float f[4] = { float(subRect.x()), float(subRect.y()),
+ float(subRect.width()), float(subRect.height()) };
+ Q_ASSERT(sizeof(f) == c.size);
+ memcpy(dst, f, sizeof(f));
} else if (c.specialType == QSGShaderEffectNode::VariableData::None) {
r |= UpdatedConstantBuffer;
switch (c.value.type()) {
@@ -424,6 +476,11 @@ QSGD3D12Material::UpdateResults QSGD3D12ShaderEffectMaterial::updatePipeline(con
QSGD3D12TextureView &tv(pipelineState->shaders.rootSig.textureViews[i]);
if (tp) {
if (QSGTexture *t = tp->texture()) {
+ if (t->isAtlasTexture() && !geometryUsesTextureSubRect) {
+ QSGTexture *newTexture = t->removedFromAtlas();
+ if (newTexture)
+ t = newTexture;
+ }
tv.filter = t->filtering() == QSGTexture::Linear
? QSGD3D12TextureView::FilterLinear : QSGD3D12TextureView::FilterNearest;
tv.addressModeHoriz = t->horizontalWrapMode() == QSGTexture::ClampToEdge
@@ -518,12 +575,27 @@ QSGD3D12ShaderEffectNode::QSGD3D12ShaderEffectNode(QSGD3D12RenderContext *rc, QS
setMaterial(&m_material);
}
-QRectF QSGD3D12ShaderEffectNode::normalizedTextureSubRect() const
+QRectF QSGD3D12ShaderEffectNode::updateNormalizedTextureSubRect(bool supportsAtlasTextures)
{
- return QRectF(0, 0, 1, 1);
+ QRectF srcRect(0, 0, 1, 1);
+ bool geometryUsesTextureSubRect = false;
+ if (supportsAtlasTextures && m_material.textureProviders.count() == 1) {
+ QSGTextureProvider *provider = m_material.textureProviders.at(0);
+ if (provider->texture()) {
+ srcRect = provider->texture()->normalizedTextureSubRect();
+ geometryUsesTextureSubRect = true;
+ }
+ }
+
+ if (m_material.geometryUsesTextureSubRect != geometryUsesTextureSubRect) {
+ m_material.geometryUsesTextureSubRect = geometryUsesTextureSubRect;
+ markDirty(QSGNode::DirtyMaterial);
+ }
+
+ return srcRect;
}
-void QSGD3D12ShaderEffectNode::sync(SyncData *syncData)
+void QSGD3D12ShaderEffectNode::syncMaterial(SyncData *syncData)
{
if (Q_UNLIKELY(debug_render()))
qDebug() << "shadereffect node sync" << syncData->dirty;
@@ -636,7 +708,10 @@ void QSGD3D12ShaderEffectNode::sync(SyncData *syncData)
m_material.linker.feedSamplers(*syncData->fragment.shader);
m_material.linker.feedTextures(*syncData->fragment.shader);
+ m_material.linker.linkTextureSubRects();
+
m_material.updateTextureProviders(true);
+
markDirty(QSGNode::DirtyMaterial);
if (Q_UNLIKELY(debug_render()))
@@ -657,6 +732,7 @@ void QSGD3D12ShaderEffectNode::sync(SyncData *syncData)
m_material.linker.feedTextures(*syncData->vertex.shader, syncData->vertex.dirtyTextures);
if (!syncData->fragment.dirtyTextures->isEmpty())
m_material.linker.feedTextures(*syncData->fragment.shader, syncData->fragment.dirtyTextures);
+ m_material.linker.linkTextureSubRects();
m_material.updateTextureProviders(false);
markDirty(QSGNode::DirtyMaterial);
if (Q_UNLIKELY(debug_render()))
@@ -668,8 +744,6 @@ void QSGD3D12ShaderEffectNode::sync(SyncData *syncData)
m_material.setFlag(QSGMaterial::RequiresFullMatrix, m_material.hasCustomVertexShader);
markDirty(QSGNode::DirtyMaterial);
}
-
- // ### texture subrect
}
void QSGD3D12ShaderEffectNode::handleTextureChange()
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h
index d3e51e5dce..c8994a78dd 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode_p.h
@@ -70,6 +70,7 @@ public:
void feedConstants(const QSGShaderEffectNode::ShaderData &shader, const QSet<int> *dirtyIndices = nullptr);
void feedSamplers(const QSGShaderEffectNode::ShaderData &shader);
void feedTextures(const QSGShaderEffectNode::ShaderData &shader, const QSet<int> *dirtyIndices = nullptr);
+ void linkTextureSubRects();
void dump();
@@ -90,6 +91,7 @@ public:
QHash<uint, Constant> constants; // offset -> Constant
QSet<int> samplers; // bindpoint
QHash<int, QVariant> textures; // bindpoint -> value (source ref)
+ QHash<QByteArray, int> textureNameMap; // name -> bindpoint
};
QDebug operator<<(QDebug debug, const QSGD3D12ShaderLinker::Constant &c);
@@ -121,6 +123,7 @@ public:
QSGMaterialType *mtype = nullptr;
QVector<QSGTextureProvider *> textureProviders;
QSGD3D12Texture *dummy = nullptr;
+ bool geometryUsesTextureSubRect = false;
};
class QSGD3D12ShaderEffectNode : public QObject, public QSGShaderEffectNode
@@ -130,8 +133,8 @@ class QSGD3D12ShaderEffectNode : public QObject, public QSGShaderEffectNode
public:
QSGD3D12ShaderEffectNode(QSGD3D12RenderContext *rc, QSGD3D12GuiThreadShaderEffectManager *mgr);
- QRectF normalizedTextureSubRect() const override;
- void sync(SyncData *syncData) override;
+ QRectF updateNormalizedTextureSubRect(bool supportsAtlasTextures) override;
+ void syncMaterial(SyncData *syncData) override;
static void cleanupMaterialTypeCache();