summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhimetal.mm
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2021-12-21 13:26:45 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2022-01-06 14:56:25 +0100
commit0a59101495634a02e7b893682904f4cfc5898624 (patch)
treeaadaf9ee66173de05d85579dc85338daa48a4a84 /src/gui/rhi/qrhimetal.mm
parentc20b213eabd8138f8566c7a1fd0633625c47b520 (diff)
rhi: Add support for separate image and sampler objects
For Direct 3D, Metal, and Vulkan this is natively supported. (and makes no difference in particular for D3D and Metal because they do not have the legacy combined image sampler concept anyways) With OpenGL it will work too, but this relies on SPIR-Cross magic and is still using a combined sampler (e.g. a sampler2D) in the GLSL shader. The GL backend walks back and forth in the mapping tables from the shader baker in order to make this work, which is presumably slightly more expensive than combined image samplers. Do note that combined image samplers (i.e. sampler2D in the shader and QRhiShaderResourceBinding::sampledTexture() in code) continue to be the primary, recommended way for any user of the rhi for the time being. Change-Id: I194721bc657b1ffbcc1bb79e6eadebe569a25087 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhimetal.mm')
-rw-r--r--src/gui/rhi/qrhimetal.mm78
1 files changed, 48 insertions, 30 deletions
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 4e7f092c54..3a1eaccc92 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -835,34 +835,43 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
for (int elem = 0; elem < data->count; ++elem) {
QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.texSamplers[elem].tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.texSamplers[elem].sampler);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
- const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler);
- if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[VERTEX].textures.append({ nativeBindingTexture + elem, texD->d->tex });
- res[VERTEX].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
- }
+ // Must handle all three cases (combined, separate, separate):
+ // first = texture binding, second = sampler binding
+ // first = texture binding
+ // first = sampler binding (i.e. BindingType::Texture...)
+ const int textureBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
+ const int samplerBinding = texD && samplerD ? mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler)
+ : (samplerD ? mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture) : -1);
+ if (textureBinding >= 0 && texD)
+ res[VERTEX].textures.append({ textureBinding + elem, texD->d->tex });
+ if (samplerBinding >= 0)
+ res[VERTEX].samplers.append({ samplerBinding + elem, samplerD->d->samplerState });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
- const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler);
- if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[FRAGMENT].textures.append({ nativeBindingTexture + elem, texD->d->tex });
- res[FRAGMENT].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
- }
+ const int textureBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
+ const int samplerBinding = texD && samplerD ? mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler)
+ : (samplerD ? mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture) : -1);
+ if (textureBinding >= 0 && texD)
+ res[FRAGMENT].textures.append({ textureBinding + elem, texD->d->tex });
+ if (samplerBinding >= 0)
+ res[FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->d->samplerState });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
- const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler);
- if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[COMPUTE].textures.append({ nativeBindingTexture + elem, texD->d->tex });
- res[COMPUTE].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
- }
+ const int textureBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
+ const int samplerBinding = texD && samplerD ? mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler)
+ : (samplerD ? mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture) : -1);
+ if (textureBinding >= 0 && texD)
+ res[COMPUTE].textures.append({ textureBinding + elem, texD->d->tex });
+ if (samplerBinding >= 0)
+ res[COMPUTE].samplers.append({ samplerBinding + elem, samplerD->d->samplerState });
}
}
}
@@ -1110,8 +1119,10 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
if (bd.stex.count != data->count) {
bd.stex.count = data->count;
resNeedsRebind = true;
@@ -1119,19 +1130,26 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
for (int elem = 0; elem < data->count; ++elem) {
QMetalTexture *texD = QRHI_RES(QMetalTexture, data->texSamplers[elem].tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, data->texSamplers[elem].sampler);
- if (texD->generation != bd.stex.d[elem].texGeneration
- || texD->m_id != bd.stex.d[elem].texId
- || samplerD->generation != bd.stex.d[elem].samplerGeneration
- || samplerD->m_id != bd.stex.d[elem].samplerId)
+ Q_ASSERT(texD || samplerD);
+ const quint64 texId = texD ? texD->m_id : 0;
+ const uint texGen = texD ? texD->generation : 0;
+ const quint64 samplerId = samplerD ? samplerD->m_id : 0;
+ const uint samplerGen = samplerD ? samplerD->generation : 0;
+ if (texGen != bd.stex.d[elem].texGeneration
+ || texId != bd.stex.d[elem].texId
+ || samplerGen != bd.stex.d[elem].samplerGeneration
+ || samplerId != bd.stex.d[elem].samplerId)
{
resNeedsRebind = true;
- bd.stex.d[elem].texId = texD->m_id;
- bd.stex.d[elem].texGeneration = texD->generation;
- bd.stex.d[elem].samplerId = samplerD->m_id;
- bd.stex.d[elem].samplerGeneration = samplerD->generation;
+ bd.stex.d[elem].texId = texId;
+ bd.stex.d[elem].texGeneration = texGen;
+ bd.stex.d[elem].samplerId = samplerId;
+ bd.stex.d[elem].samplerGeneration = samplerGen;
}
- texD->lastActiveFrameSlot = currentFrameSlot;
- samplerD->lastActiveFrameSlot = currentFrameSlot;
+ if (texD)
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ if (samplerD)
+ samplerD->lastActiveFrameSlot = currentFrameSlot;
}
}
break;