summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2022-08-12 14:23:44 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2022-08-15 10:51:17 +0200
commit5eacc974c705d3cf0041847a5dac5890cda200d3 (patch)
treec57eec28415c0a5ce2af532b415c2714463f8d2e /src/gui/rhi
parent6c9f4f5ebcd35dc1a68c442d9fbf3ec48f30baca (diff)
rhi: d3d11: Enable tessellation and geometry with some caveats
The caveat being having to manually create HLSL versions of the hull, domain, and geometry shaders in parallel with the Vulkan GLSL ones, while keeping the interfaces intact (stage inputs and outputs, cbuffer layouts, binding points/registers). This is not always trivial but typically doable in not very complicated case after inspecting the SPIRV-Cross-generated vertex/fragment code in the .qsb files. Once written, the HLSL files can be injected into a .qsb file with qsb -r. or the corresponding CMake syntax. Conceptually this is no different from how samplerExternalOES support is implemented for Multimedia. (there the problem is that the shaders cannot be compiled to SPIR-V to begin with, here it is that we cannot translate from SPIR-V, but in the end the workaround for both problems is effectively the same) The manual tests demonstrate this, both the tessellation and geometry apps work now with D3D out of the box. On the bright side, the implementation here in the the D3D backend of QRhi does not need to know about how the shaders got there in the QShader. So none of the implementation is dependent on this manual process. If some day qsb would start translating to these kind of shaders as well, it would all still work as-is. Change-Id: I32d9ab94e00174e4bd5b59ac814dfedef9f93ad1 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r--src/gui/rhi/qrhi.cpp30
-rw-r--r--src/gui/rhi/qrhid3d11.cpp549
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h98
3 files changed, 380 insertions, 297 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 94367fbcd5..3cc6a8da83 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -677,23 +677,27 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
can be set via
\l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
and shaders for tessellation control and evaluation can be specified in the
- QRhiShaderStage list. \b{Tessellation is considered an experimental feature
- in QRhi and can only be expected to be supported with Vulkan, OpenGL and
- OpenGL ES for the time being}, assuming the implementation reports it as
- supported at run time. Tessellation shaders have portability issues between
- APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
- the way hull shaders are structured, whereas Metal uses a somewhat
- different tessellation pipeline than others), and therefore no guarantees
- can be given for a universal solution for now.
+ QRhiShaderStage list. Tessellation is considered an experimental feature in
+ QRhi and can only be expected to be supported with Vulkan, OpenGL (ES), and
+ Direct 3D, assuming the implementation reports it as supported at run time.
+ Tessellation shaders have portability issues between APIs (for example,
+ translating GLSL/SPIR-V to HLSL is problematic due to the way hull shaders
+ are structured, whereas Metal uses a somewhat different tessellation
+ pipeline than others), and therefore no guarantees can be given for a
+ universal solution for now. (for Direct 3D in particular, handwritten HLSL
+ hull and domain shaders must be injected into each QShader since qsb cannot
+ generate these from SPIR-V)
\value GeometryShader Indicates that the geometry shader stage is
supported. When supported, a geometry shader can be specified in the
- QRhiShaderStage list. \b{Geometry Shaders are considered an experimental
+ QRhiShaderStage list. Geometry Shaders are considered an experimental
feature in QRhi and can only be expected to be supported with Vulkan,
- OpenGL (3.2+) and OpenGL ES (3.2+) for the time being}, assuming the
- implementation reports it as supported at run time. Geometry shaders have
- portability issues between APIs, and therefore no guarantees can be given
- for a universal solution for now.
+ Direct 3D, OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation
+ reports it as supported at run time. Geometry shaders have portability
+ issues between APIs, and therefore no guarantees can be given for a
+ universal solution for now. (for Direct 3D in particular, a handwritten
+ HLSL geometry shader must be injected into each QShader since qsb cannot
+ generate this from SPIR-V)
\value TextureArrayRange Indicates that for
\l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 7c45b9c561..2a69474433 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -537,9 +537,9 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
case QRhi::TextureArrays:
return true;
case QRhi::Tessellation:
- return false;
+ return true;
case QRhi::GeometryShader:
- return false;
+ return true;
case QRhi::TextureArrayRange:
return true;
case QRhi::NonFillPolygonMode:
@@ -840,10 +840,13 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
-static const int RBM_SUPPORTED_STAGES = 3;
+static const int RBM_SUPPORTED_STAGES = 6;
static const int RBM_VERTEX = 0;
-static const int RBM_FRAGMENT = 1;
-static const int RBM_COMPUTE = 2;
+static const int RBM_HULL = 1;
+static const int RBM_DOMAIN = 2;
+static const int RBM_GEOMETRY = 3;
+static const int RBM_FRAGMENT = 4;
+static const int RBM_COMPUTE = 5;
void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
@@ -952,6 +955,9 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
memset(resBindMaps, 0, sizeof(resBindMaps));
if (gfxPsD) {
resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
+ resBindMaps[RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
+ resBindMaps[RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
+ resBindMaps[RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
} else {
resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
@@ -2077,7 +2083,7 @@ static inline QPair<int, int> mapBinding(int binding,
{
const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
if (!map || map->isEmpty())
- return { binding, binding }; // old QShader versions do not have this map, assume 1:1 mapping then
+ return { binding, binding }; // assume 1:1 mapping
auto it = map->constFind(binding);
if (it != map->cend())
@@ -2092,31 +2098,21 @@ static inline QPair<int, int> mapBinding(int binding,
void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
- srbD->vsubufs.clear();
- srbD->vsubuforigbindings.clear();
- srbD->vsubufoffsets.clear();
- srbD->vsubufsizes.clear();
-
- srbD->fsubufs.clear();
- srbD->fsubuforigbindings.clear();
- srbD->fsubufoffsets.clear();
- srbD->fsubufsizes.clear();
-
- srbD->csubufs.clear();
- srbD->csubuforigbindings.clear();
- srbD->csubufoffsets.clear();
- srbD->csubufsizes.clear();
-
- srbD->vssamplers.clear();
- srbD->vsshaderresources.clear();
+ srbD->vsUniformBufferBatches.clear();
+ srbD->hsUniformBufferBatches.clear();
+ srbD->dsUniformBufferBatches.clear();
+ srbD->gsUniformBufferBatches.clear();
+ srbD->fsUniformBufferBatches.clear();
+ srbD->csUniformBufferBatches.clear();
- srbD->fssamplers.clear();
- srbD->fsshaderresources.clear();
+ srbD->vsSamplerBatches.clear();
+ srbD->hsSamplerBatches.clear();
+ srbD->dsSamplerBatches.clear();
+ srbD->gsSamplerBatches.clear();
+ srbD->fsSamplerBatches.clear();
+ srbD->csSamplerBatches.clear();
- srbD->cssamplers.clear();
- srbD->csshaderresources.clear();
-
- srbD->csUAVs.clear();
+ srbD->csUavBatches.clear();
struct Stage {
struct Buffer {
@@ -2142,6 +2138,30 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
QVarLengthArray<Texture, 8> textures;
QVarLengthArray<Sampler, 8> samplers;
QVarLengthArray<Uav, 8> uavs;
+ void buildBufferBatches(QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches) const
+ {
+ for (const Buffer &buf : buffers) {
+ batches.ubufs.feed(buf.breg, buf.buffer);
+ batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
+ batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
+ batches.finish();
+ }
+ void buildSamplerBatches(QD3D11ShaderResourceBindings::StageSamplerBatches &batches) const
+ {
+ for (const Texture &t : textures)
+ batches.shaderresources.feed(t.treg, t.srv);
+ for (const Sampler &s : samplers)
+ batches.samplers.feed(s.sreg, s.sampler);
+ batches.finish();
+ }
+ void buildUavBatches(QD3D11ShaderResourceBindings::StageUavBatches &batches) const
+ {
+ for (const Stage::Uav &u : uavs)
+ batches.uavs.feed(u.ureg, u.uav);
+ batches.finish();
+ }
} res[RBM_SUPPORTED_STAGES];
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
@@ -2170,6 +2190,21 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
if (nativeBinding.first >= 0)
res[RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
+ }
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
if (nativeBinding.first >= 0)
@@ -2189,6 +2224,9 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
bd.stex.count = data->count;
const QPair<int, int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ const QPair<int, int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
+ const QPair<int, int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
+ const QPair<int, int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
const QPair<int, int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
const QPair<int, int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
// if SPIR-V binding b is mapped to tN and sN in HLSL, and it
@@ -2201,11 +2239,11 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
+ // Must handle all three cases (combined, separate, separate):
+ // first = texture binding, second = sampler binding
+ // first = texture binding
+ // first = sampler binding
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- // Must handle all three cases (combined, separate, separate):
- // first = texture binding, second = sampler binding
- // first = texture binding
- // first = sampler binding
const int samplerBinding = texD && samplerD ? nativeBindingVert.second
: (samplerD ? nativeBindingVert.first : -1);
if (nativeBindingVert.first >= 0 && texD)
@@ -2213,9 +2251,33 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
if (samplerBinding >= 0)
res[RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
}
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
+ const int samplerBinding = texD && samplerD ? nativeBindingHull.second
+ : (samplerD ? nativeBindingHull.first : -1);
+ if (nativeBindingHull.first >= 0 && texD)
+ res[RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
+ if (samplerBinding >= 0)
+ res[RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
+ const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
+ : (samplerD ? nativeBindingDomain.first : -1);
+ if (nativeBindingDomain.first >= 0 && texD)
+ res[RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
+ if (samplerBinding >= 0)
+ res[RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
+ const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
+ : (samplerD ? nativeBindingGeom.first : -1);
+ if (nativeBindingGeom.first >= 0 && texD)
+ res[RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
+ if (samplerBinding >= 0)
+ res[RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
+ }
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
- : (samplerD ? nativeBindingVert.first : -1);
+ : (samplerD ? nativeBindingFrag.first : -1);
if (nativeBindingFrag.first >= 0 && texD)
res[RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
if (samplerBinding >= 0)
@@ -2223,7 +2285,7 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int samplerBinding = texD && samplerD ? nativeBindingComp.second
- : (samplerD ? nativeBindingVert.first : -1);
+ : (samplerD ? nativeBindingComp.first : -1);
if (nativeBindingComp.first >= 0 && texD)
res[RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
if (samplerBinding >= 0)
@@ -2295,63 +2357,21 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
});
}
- for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) {
- srbD->vsubufs.feed(buf.breg, buf.buffer);
- srbD->vsubuforigbindings.feed(buf.breg, UINT(buf.binding));
- srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants);
- srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants);
- }
- srbD->vsubufsPresent = srbD->vsubufs.finish();
- srbD->vsubuforigbindings.finish();
- srbD->vsubufoffsets.finish();
- srbD->vsubufsizes.finish();
-
- for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) {
- srbD->fsubufs.feed(buf.breg, buf.buffer);
- srbD->fsubuforigbindings.feed(buf.breg, UINT(buf.binding));
- srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants);
- srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants);
- }
- srbD->fsubufsPresent = srbD->fsubufs.finish();
- srbD->fsubuforigbindings.finish();
- srbD->fsubufoffsets.finish();
- srbD->fsubufsizes.finish();
-
- for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) {
- srbD->csubufs.feed(buf.breg, buf.buffer);
- srbD->csubuforigbindings.feed(buf.breg, UINT(buf.binding));
- srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants);
- srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants);
- }
- srbD->csubufsPresent = srbD->csubufs.finish();
- srbD->csubuforigbindings.finish();
- srbD->csubufoffsets.finish();
- srbD->csubufsizes.finish();
-
- for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures))
- srbD->vsshaderresources.feed(t.treg, t.srv);
- for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers))
- srbD->vssamplers.feed(s.sreg, s.sampler);
- srbD->vssamplersPresent = srbD->vssamplers.finish();
- srbD->vsshaderresources.finish();
-
- for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures))
- srbD->fsshaderresources.feed(t.treg, t.srv);
- for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers))
- srbD->fssamplers.feed(s.sreg, s.sampler);
- srbD->fssamplersPresent = srbD->fssamplers.finish();
- srbD->fsshaderresources.finish();
-
- for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures))
- srbD->csshaderresources.feed(t.treg, t.srv);
- for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers))
- srbD->cssamplers.feed(s.sreg, s.sampler);
- srbD->cssamplersPresent = srbD->cssamplers.finish();
- srbD->csshaderresources.finish();
-
- for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
- srbD->csUAVs.feed(u.ureg, u.uav);
- srbD->csUAVsPresent = srbD->csUAVs.finish();
+ res[RBM_VERTEX].buildBufferBatches(srbD->vsUniformBufferBatches);
+ res[RBM_HULL].buildBufferBatches(srbD->hsUniformBufferBatches);
+ res[RBM_DOMAIN].buildBufferBatches(srbD->dsUniformBufferBatches);
+ res[RBM_GEOMETRY].buildBufferBatches(srbD->gsUniformBufferBatches);
+ res[RBM_FRAGMENT].buildBufferBatches(srbD->fsUniformBufferBatches);
+ res[RBM_COMPUTE].buildBufferBatches(srbD->csUniformBufferBatches);
+
+ res[RBM_VERTEX].buildSamplerBatches(srbD->vsSamplerBatches);
+ res[RBM_HULL].buildSamplerBatches(srbD->hsSamplerBatches);
+ res[RBM_DOMAIN].buildSamplerBatches(srbD->dsSamplerBatches);
+ res[RBM_GEOMETRY].buildSamplerBatches(srbD->gsSamplerBatches);
+ res[RBM_FRAGMENT].buildSamplerBatches(srbD->fsSamplerBatches);
+ res[RBM_COMPUTE].buildSamplerBatches(srbD->csSamplerBatches);
+
+ res[RBM_COMPUTE].buildUavBatches(srbD->csUavBatches);
}
void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
@@ -2373,8 +2393,8 @@ void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
static void applyDynamicOffsets(UINT *offsets,
int batchIndex,
- QRhiBatchedBindings<UINT> *originalBindings,
- QRhiBatchedBindings<UINT> *staticOffsets,
+ const QRhiBatchedBindings<UINT> *originalBindings,
+ const QRhiBatchedBindings<UINT> *staticOffsets,
const uint *dynOfsPairs, int dynOfsPairCount)
{
const int count = staticOffsets->batches[batchIndex].resources.count();
@@ -2405,162 +2425,92 @@ static inline uint clampedResourceCount(uint startSlot, int countSlots, uint max
return countSlots;
}
+#define SETUBUFBATCH(stagePrefixL, stagePrefixU) \
+ if (srbD->stagePrefixL##UniformBufferBatches.present) { \
+ const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(srbD->stagePrefixL##UniformBufferBatches); \
+ for (int i = 0, ie = batches.ubufs.batches.count(); i != ie; ++i) { \
+ const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding, \
+ batches.ubufs.batches[i].resources.count(), \
+ D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, \
+ #stagePrefixU " cbuf"); \
+ if (count) { \
+ if (!dynOfsPairCount) { \
+ context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding, \
+ count, \
+ batches.ubufs.batches[i].resources.constData(), \
+ batches.ubufoffsets.batches[i].resources.constData(), \
+ batches.ubufsizes.batches[i].resources.constData()); \
+ } else { \
+ applyDynamicOffsets(offsets, i, \
+ &batches.ubuforigbindings, &batches.ubufoffsets, \
+ dynOfsPairs, dynOfsPairCount); \
+ context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding, \
+ count, \
+ batches.ubufs.batches[i].resources.constData(), \
+ offsets, \
+ batches.ubufsizes.batches[i].resources.constData()); \
+ } \
+ } \
+ } \
+ }
+
+#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU) \
+ if (srbD->stagePrefixL##SamplerBatches.present) { \
+ for (const auto &batch : srbD->stagePrefixL##SamplerBatches.samplers.batches) { \
+ const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(), \
+ D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler"); \
+ if (count) \
+ context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData()); \
+ } \
+ for (const auto &batch : srbD->stagePrefixL##SamplerBatches.shaderresources.batches) { \
+ const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(), \
+ D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV"); \
+ if (count) { \
+ context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData()); \
+ contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding, \
+ int(batch.startBinding + count) - 1); \
+ } \
+ } \
+ }
+
+#define SETUAVBATCH(stagePrefixL, stagePrefixU) \
+ if (srbD->stagePrefixL##UavBatches.present) { \
+ for (const auto &batch : srbD->stagePrefixL##UavBatches.uavs.batches) { \
+ const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(), \
+ D3D11_1_UAV_SLOT_COUNT, #stagePrefixU " UAV"); \
+ if (count) { \
+ context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding, \
+ count, \
+ batch.resources.constData(), \
+ nullptr); \
+ contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding, \
+ int(batch.startBinding + count) - 1); \
+ } \
+ } \
+ }
+
void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange)
{
UINT offsets[QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT];
- if (srbD->vsubufsPresent) {
- for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) {
- const uint count = clampedResourceCount(srbD->vsubufs.batches[i].startBinding,
- srbD->vsubufs.batches[i].resources.count(),
- D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
- "VS cbuf");
- if (count) {
- if (!dynOfsPairCount) {
- context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
- count,
- srbD->vsubufs.batches[i].resources.constData(),
- srbD->vsubufoffsets.batches[i].resources.constData(),
- srbD->vsubufsizes.batches[i].resources.constData());
- } else {
- applyDynamicOffsets(offsets, i, &srbD->vsubuforigbindings, &srbD->vsubufoffsets,
- dynOfsPairs, dynOfsPairCount);
- context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
- count,
- srbD->vsubufs.batches[i].resources.constData(),
- offsets,
- srbD->vsubufsizes.batches[i].resources.constData());
- }
- }
- }
- }
-
- if (srbD->fsubufsPresent) {
- for (int i = 0, ie = srbD->fsubufs.batches.count(); i != ie; ++i) {
- const uint count = clampedResourceCount(srbD->fsubufs.batches[i].startBinding,
- srbD->fsubufs.batches[i].resources.count(),
- D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
- "PS cbuf");
- if (count) {
- if (!dynOfsPairCount) {
- context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
- count,
- srbD->fsubufs.batches[i].resources.constData(),
- srbD->fsubufoffsets.batches[i].resources.constData(),
- srbD->fsubufsizes.batches[i].resources.constData());
- } else {
- applyDynamicOffsets(offsets, i, &srbD->fsubuforigbindings, &srbD->fsubufoffsets,
- dynOfsPairs, dynOfsPairCount);
- context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
- count,
- srbD->fsubufs.batches[i].resources.constData(),
- offsets,
- srbD->fsubufsizes.batches[i].resources.constData());
- }
- }
- }
- }
-
- if (srbD->csubufsPresent) {
- for (int i = 0, ie = srbD->csubufs.batches.count(); i != ie; ++i) {
- const uint count = clampedResourceCount(srbD->csubufs.batches[i].startBinding,
- srbD->csubufs.batches[i].resources.count(),
- D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
- "CS cbuf");
- if (count) {
- if (!dynOfsPairCount) {
- context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
- count,
- srbD->csubufs.batches[i].resources.constData(),
- srbD->csubufoffsets.batches[i].resources.constData(),
- srbD->csubufsizes.batches[i].resources.constData());
- } else {
- applyDynamicOffsets(offsets, i, &srbD->csubuforigbindings, &srbD->csubufoffsets,
- dynOfsPairs, dynOfsPairCount);
- context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
- count,
- srbD->csubufs.batches[i].resources.constData(),
- offsets,
- srbD->csubufsizes.batches[i].resources.constData());
- }
- }
- }
- }
+ SETUBUFBATCH(vs, VS)
+ SETUBUFBATCH(hs, HS)
+ SETUBUFBATCH(ds, DS)
+ SETUBUFBATCH(gs, GS)
+ SETUBUFBATCH(fs, PS)
+ SETUBUFBATCH(cs, CS)
if (!offsetOnlyChange) {
- if (srbD->vssamplersPresent) {
- for (const auto &batch : srbD->vssamplers.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "VS sampler");
- if (count)
- context->VSSetSamplers(batch.startBinding, count, batch.resources.constData());
- }
-
- for (const auto &batch : srbD->vsshaderresources.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "VS SRV");
- if (count) {
- context->VSSetShaderResources(batch.startBinding, count, batch.resources.constData());
- contextState.vsHighestActiveSrvBinding = qMax(contextState.vsHighestActiveSrvBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
-
- if (srbD->fssamplersPresent) {
- for (const auto &batch : srbD->fssamplers.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "PS sampler");
- if (count)
- context->PSSetSamplers(batch.startBinding, count, batch.resources.constData());
- }
-
- for (const auto &batch : srbD->fsshaderresources.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "PS SRV");
- if (count) {
- context->PSSetShaderResources(batch.startBinding, count, batch.resources.constData());
- contextState.fsHighestActiveSrvBinding = qMax(contextState.fsHighestActiveSrvBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
+ SETSAMPLERBATCH(vs, VS)
+ SETSAMPLERBATCH(hs, HS)
+ SETSAMPLERBATCH(ds, DS)
+ SETSAMPLERBATCH(gs, GS)
+ SETSAMPLERBATCH(fs, PS)
+ SETSAMPLERBATCH(cs, CS)
- if (srbD->cssamplersPresent) {
- for (const auto &batch : srbD->cssamplers.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "CS sampler");
- if (count)
- context->CSSetSamplers(batch.startBinding, count, batch.resources.constData());
- }
-
- for (const auto &batch : srbD->csshaderresources.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "CS SRV");
- if (count) {
- context->CSSetShaderResources(batch.startBinding, count, batch.resources.constData());
- contextState.csHighestActiveSrvBinding = qMax(contextState.csHighestActiveSrvBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
-
- if (srbD->csUAVsPresent) {
- for (const auto &batch : srbD->csUAVs.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_1_UAV_SLOT_COUNT, "CS UAV");
- if (count) {
- context->CSSetUnorderedAccessViews(batch.startBinding,
- count,
- batch.resources.constData(),
- nullptr);
- contextState.csHighestActiveUavBinding = qMax(contextState.csHighestActiveUavBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
+ SETUAVBATCH(cs, CS)
}
}
@@ -2589,6 +2539,9 @@ void QRhiD3D11::resetShaderResources()
}
int nullsrvCount = qMax(contextState.vsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding);
+ nullsrvCount = qMax(nullsrvCount, contextState.hsHighestActiveSrvBinding);
+ nullsrvCount = qMax(nullsrvCount, contextState.dsHighestActiveSrvBinding);
+ nullsrvCount = qMax(nullsrvCount, contextState.gsHighestActiveSrvBinding);
nullsrvCount = qMax(nullsrvCount, contextState.csHighestActiveSrvBinding);
nullsrvCount += 1;
if (nullsrvCount > 0) {
@@ -2600,6 +2553,18 @@ void QRhiD3D11::resetShaderResources()
context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.vsHighestActiveSrvBinding = -1;
}
+ if (contextState.hsHighestActiveSrvBinding >= 0) {
+ context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
+ contextState.hsHighestActiveSrvBinding = -1;
+ }
+ if (contextState.dsHighestActiveSrvBinding >= 0) {
+ context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
+ contextState.dsHighestActiveSrvBinding = -1;
+ }
+ if (contextState.gsHighestActiveSrvBinding >= 0) {
+ context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
+ contextState.gsHighestActiveSrvBinding = -1;
+ }
if (contextState.fsHighestActiveSrvBinding >= 0) {
context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.fsHighestActiveSrvBinding = -1;
@@ -2621,10 +2586,27 @@ void QRhiD3D11::resetShaderResources()
}
}
+#define SETSHADER(StageL, StageU) \
+ if (psD->StageL.shader) { \
+ context->StageU##SetShader(psD->StageL.shader, nullptr, 0); \
+ currentShaderMask |= StageU##MaskBit; \
+ } else if (currentShaderMask & StageU##MaskBit) { \
+ context->StageU##SetShader(nullptr, nullptr, 0); \
+ currentShaderMask &= ~StageU##MaskBit; \
+ }
+
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
{
quint32 stencilRef = 0;
float blendConstants[] = { 1, 1, 1, 1 };
+ enum ActiveShaderMask {
+ VSMaskBit = 0x01,
+ HSMaskBit = 0x02,
+ DSMaskBit = 0x04,
+ GSMaskBit = 0x08,
+ PSMaskBit = 0x10
+ };
+ int currentShaderMask = 0xFF;
if (timestampSwapChain) {
const int currentFrameSlot = timestampSwapChain->currentFrameSlot;
@@ -2713,8 +2695,11 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
- context->VSSetShader(psD->vs.shader, nullptr, 0);
- context->PSSetShader(psD->fs.shader, nullptr, 0);
+ SETSHADER(vs, VS)
+ SETSHADER(hs, HS)
+ SETSHADER(ds, DS)
+ SETSHADER(gs, GS)
+ SETSHADER(fs, PS)
context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout); // may be null, that's ok
context->OMSetDepthStencilState(psD->dsState, stencilRef);
@@ -3853,6 +3838,16 @@ QD3D11GraphicsPipeline::~QD3D11GraphicsPipeline()
destroy();
}
+template<typename T>
+inline void releasePipelineShader(T &s)
+{
+ if (s.shader) {
+ s.shader->Release();
+ s.shader = nullptr;
+ }
+ s.nativeResourceBindingMap.clear();
+}
+
void QD3D11GraphicsPipeline::destroy()
{
if (!dsState)
@@ -3876,17 +3871,11 @@ void QD3D11GraphicsPipeline::destroy()
rastState = nullptr;
}
- if (vs.shader) {
- vs.shader->Release();
- vs.shader = nullptr;
- }
- vs.nativeResourceBindingMap.clear();
-
- if (fs.shader) {
- fs.shader->Release();
- fs.shader = nullptr;
- }
- fs.nativeResourceBindingMap.clear();
+ releasePipelineShader(vs);
+ releasePipelineShader(hs);
+ releasePipelineShader(ds);
+ releasePipelineShader(gs);
+ releasePipelineShader(fs);
QRHI_RES_RHI(QRhiD3D11);
if (rhiD)
@@ -4010,7 +3999,7 @@ static inline DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format
}
}
-static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t)
+static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
{
switch (t) {
case QRhiGraphicsPipeline::Triangles:
@@ -4023,6 +4012,9 @@ static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topol
return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
case QRhiGraphicsPipeline::Points:
return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+ case QRhiGraphicsPipeline::Patches:
+ Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
+ return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
default:
Q_UNREACHABLE();
return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
@@ -4307,6 +4299,21 @@ bool QD3D11GraphicsPipeline::create()
vsByteCode = cacheIt->bytecode;
vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
+ case QRhiShaderStage::TessellationControl:
+ hs.shader = static_cast<ID3D11HullShader *>(cacheIt->s);
+ hs.shader->AddRef();
+ hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ break;
+ case QRhiShaderStage::TessellationEvaluation:
+ ds.shader = static_cast<ID3D11DomainShader *>(cacheIt->s);
+ ds.shader->AddRef();
+ ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ break;
+ case QRhiShaderStage::Geometry:
+ gs.shader = static_cast<ID3D11GeometryShader *>(cacheIt->s);
+ gs.shader->AddRef();
+ gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ break;
case QRhiShaderStage::Fragment:
fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
fs.shader->AddRef();
@@ -4346,6 +4353,36 @@ bool QD3D11GraphicsPipeline::create()
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
vs.shader->AddRef();
break;
+ case QRhiShaderStage::TessellationControl:
+ hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &hs.shader);
+ if (FAILED(hr)) {
+ qWarning("Failed to create hull shader: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
+ hs.shader->AddRef();
+ break;
+ case QRhiShaderStage::TessellationEvaluation:
+ hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &ds.shader);
+ if (FAILED(hr)) {
+ qWarning("Failed to create domain shader: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
+ ds.shader->AddRef();
+ break;
+ case QRhiShaderStage::Geometry:
+ hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &gs.shader);
+ if (FAILED(hr)) {
+ qWarning("Failed to create geometry shader: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+ gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
+ gs.shader->AddRef();
+ break;
case QRhiShaderStage::Fragment:
hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader);
if (FAILED(hr)) {
@@ -4362,7 +4399,7 @@ bool QD3D11GraphicsPipeline::create()
}
}
- d3dTopology = toD3DTopology(m_topology);
+ d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
if (!vsByteCode.isEmpty()) {
QByteArrayList matrixSliceSemantics;
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 50ea3fbbfe..96c7818ee9 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -221,39 +221,66 @@ struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
};
QVarLengthArray<BoundResourceData, 8> boundResourceData;
- bool vsubufsPresent = false;
- bool fsubufsPresent = false;
- bool csubufsPresent = false;
- bool vssamplersPresent = false;
- bool fssamplersPresent = false;
- bool cssamplersPresent = false;
- bool csUAVsPresent = false;
-
- QRhiBatchedBindings<ID3D11Buffer *> vsubufs;
- QRhiBatchedBindings<UINT> vsubuforigbindings;
- QRhiBatchedBindings<UINT> vsubufoffsets;
- QRhiBatchedBindings<UINT> vsubufsizes;
-
- QRhiBatchedBindings<ID3D11Buffer *> fsubufs;
- QRhiBatchedBindings<UINT> fsubuforigbindings;
- QRhiBatchedBindings<UINT> fsubufoffsets;
- QRhiBatchedBindings<UINT> fsubufsizes;
+ struct StageUniformBufferBatches {
+ bool present = false;
+ QRhiBatchedBindings<ID3D11Buffer *> ubufs;
+ QRhiBatchedBindings<UINT> ubuforigbindings;
+ QRhiBatchedBindings<UINT> ubufoffsets;
+ QRhiBatchedBindings<UINT> ubufsizes;
+ void finish() {
+ present = ubufs.finish();
+ ubuforigbindings.finish();
+ ubufoffsets.finish();
+ ubufsizes.finish();
+ }
+ void clear() {
+ ubufs.clear();
+ ubuforigbindings.clear();
+ ubufoffsets.clear();
+ ubufsizes.clear();
+ }
+ };
- QRhiBatchedBindings<ID3D11Buffer *> csubufs;
- QRhiBatchedBindings<UINT> csubuforigbindings;
- QRhiBatchedBindings<UINT> csubufoffsets;
- QRhiBatchedBindings<UINT> csubufsizes;
+ struct StageSamplerBatches {
+ bool present = false;
+ QRhiBatchedBindings<ID3D11SamplerState *> samplers;
+ QRhiBatchedBindings<ID3D11ShaderResourceView *> shaderresources;
+ void finish() {
+ present = samplers.finish();
+ shaderresources.finish();
+ }
+ void clear() {
+ samplers.clear();
+ shaderresources.clear();
+ }
+ };
- QRhiBatchedBindings<ID3D11SamplerState *> vssamplers;
- QRhiBatchedBindings<ID3D11ShaderResourceView *> vsshaderresources;
+ struct StageUavBatches {
+ bool present = false;
+ QRhiBatchedBindings<ID3D11UnorderedAccessView *> uavs;
+ void finish() {
+ present = uavs.finish();
+ }
+ void clear() {
+ uavs.clear();
+ }
+ };
- QRhiBatchedBindings<ID3D11SamplerState *> fssamplers;
- QRhiBatchedBindings<ID3D11ShaderResourceView *> fsshaderresources;
+ StageUniformBufferBatches vsUniformBufferBatches;
+ StageUniformBufferBatches hsUniformBufferBatches;
+ StageUniformBufferBatches dsUniformBufferBatches;
+ StageUniformBufferBatches gsUniformBufferBatches;
+ StageUniformBufferBatches fsUniformBufferBatches;
+ StageUniformBufferBatches csUniformBufferBatches;
- QRhiBatchedBindings<ID3D11SamplerState *> cssamplers;
- QRhiBatchedBindings<ID3D11ShaderResourceView *> csshaderresources;
+ StageSamplerBatches vsSamplerBatches;
+ StageSamplerBatches hsSamplerBatches;
+ StageSamplerBatches dsSamplerBatches;
+ StageSamplerBatches gsSamplerBatches;
+ StageSamplerBatches fsSamplerBatches;
+ StageSamplerBatches csSamplerBatches;
- QRhiBatchedBindings<ID3D11UnorderedAccessView *> csUAVs;
+ StageUavBatches csUavBatches;
friend class QRhiD3D11;
};
@@ -274,6 +301,18 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} vs;
struct {
+ ID3D11HullShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } hs;
+ struct {
+ ID3D11DomainShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } ds;
+ struct {
+ ID3D11GeometryShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } gs;
+ struct {
ID3D11PixelShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} fs;
@@ -707,6 +746,9 @@ public:
int vsHighestActiveVertexBufferBinding = -1;
bool vsHasIndexBufferBound = false;
int vsHighestActiveSrvBinding = -1;
+ int hsHighestActiveSrvBinding = -1;
+ int dsHighestActiveSrvBinding = -1;
+ int gsHighestActiveSrvBinding = -1;
int fsHighestActiveSrvBinding = -1;
int csHighestActiveSrvBinding = -1;
int csHighestActiveUavBinding = -1;