diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp
index 9b9741473..a0f7e52e3 100644
--- a/qrenderdoc/Code/QRDUtils.cpp
+++ b/qrenderdoc/Code/QRDUtils.cpp
@@ -1273,6 +1273,21 @@ QString ToQStr(const AddressMode addr, const GraphicsAPI apitype)
return lit("Unknown");
}
+QString ToQStr(const ShadingRateCombiner addr, const GraphicsAPI apitype)
+{
+ if(IsD3D(apitype))
+ {
+ switch(addr)
+ {
+ case ShadingRateCombiner::Keep: return lit("Passthrough");
+ case ShadingRateCombiner::Replace: return lit("Override");
+ default: break;
+ }
+ }
+
+ return ToQStr(addr);
+}
+
QString TypeString(const SigParameter &sig)
{
QString ret = ToQStr(sig.varType);
diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h
index 0f1010cca..1e5453a94 100644
--- a/qrenderdoc/Code/QRDUtils.h
+++ b/qrenderdoc/Code/QRDUtils.h
@@ -58,14 +58,11 @@ inline QString ToQStr(const T &el)
return QString(ToStr(el));
}
-// overload for a couple of things that need to know the pipeline type when converting
+// overloads for a couple of things that need to know the pipeline type when converting
QString ToQStr(const ResourceUsage usage, const GraphicsAPI apitype);
-
-// overload for a couple of things that need to know the pipeline type when converting
QString ToQStr(const ShaderStage stage, const GraphicsAPI apitype);
-
-// overload for a couple of things that need to know the pipeline type when converting
QString ToQStr(const AddressMode addr, const GraphicsAPI apitype);
+QString ToQStr(const ShadingRateCombiner addr, const GraphicsAPI apitype);
inline QMetaType::Type GetVariantMetatype(const QVariant &v)
{
diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp
index 2db20e5a7..c42dc1550 100644
--- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp
+++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp
@@ -915,6 +915,10 @@ void D3D12PipelineStateViewer::clearState()
ui->frontCCW->setPixmap(tick);
ui->conservativeRaster->setPixmap(cross);
+ ui->baseShadingRate->setText(lit("1x1"));
+ ui->shadingRateCombiners->setText(lit("Passthrough, Passthrough"));
+ ui->shadingRateImage->setText(ToQStr(ResourceId()));
+
ui->depthBias->setText(lit("0.0"));
ui->depthBiasClamp->setText(lit("0.0"));
ui->slopeScaledBias->setText(lit("0.0"));
@@ -1790,6 +1794,15 @@ void D3D12PipelineStateViewer::setState()
state.rasterizer.state.conservativeRasterization != ConservativeRaster::Disabled ? tick
: cross);
+ ui->baseShadingRate->setText(QFormatStr("%1x%2")
+ .arg(state.rasterizer.state.baseShadingRate.first)
+ .arg(state.rasterizer.state.baseShadingRate.second));
+ ui->shadingRateCombiners->setText(
+ QFormatStr("%1, %2")
+ .arg(ToQStr(state.rasterizer.state.shadingRateCombiners.first, GraphicsAPI::D3D12))
+ .arg(ToQStr(state.rasterizer.state.shadingRateCombiners.second, GraphicsAPI::D3D12)));
+ ui->shadingRateImage->setText(ToQStr(state.rasterizer.state.shadingRateImage));
+
////////////////////////////////////////////////
// Output Merger
diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui
index c056a4a90..998ddf22d 100644
--- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui
+++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.ui
@@ -2201,19 +2201,6 @@
0
- -
-
-
- Fill Mode:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
-
@@ -2232,28 +2219,15 @@
- -
-
-
- Cull Mode:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
- -
-
+
-
+
12
- None
+ 0.00
Qt::AlignCenter
@@ -2263,10 +2237,26 @@
- -
-
+
-
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Preferred
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
- Front CCW:
+ Fill Mode:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -2276,19 +2266,29 @@
- -
-
+
-
+
-
-
-
- :/cross.png
+ Depth Bias:
- Qt::AlignCenter
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- 4
+
+ true
+
+
+
+ -
+
+
+ Line AA:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
@@ -2305,6 +2305,19 @@
+ -
+
+
+ Forced Sample Count:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
-
@@ -2321,28 +2334,13 @@
- -
-
+
-
+
- Depth Bias:
+
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
- -
-
-
-
- 12
-
-
-
- 0.00
+
+ :/cross.png
Qt::AlignCenter
@@ -2352,28 +2350,13 @@
- -
-
+
-
+
- Depth Bias Clamp:
+
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
- -
-
-
-
- 12
-
-
-
- 0.00
+
+ :/cross.png
Qt::AlignCenter
@@ -2383,16 +2366,19 @@
- -
-
+
-
+
- Slope-Scaled Bias:
+
+
+
+ :/cross.png
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+ Qt::AlignCenter
-
- true
+
+ 4
@@ -2414,66 +2400,6 @@
- -
-
-
- Forced Sample Count:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
- -
-
-
-
- 12
-
-
-
- 0
-
-
- Qt::AlignCenter
-
-
- 4
-
-
-
- -
-
-
- Depth Clip:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- true
-
-
-
- -
-
-
-
-
-
- :/cross.png
-
-
- Qt::AlignCenter
-
-
- 4
-
-
-
-
@@ -2487,26 +2413,26 @@
- -
-
-
-
+
-
+
+
+ Qt::Horizontal
-
- :/cross.png
+
+ QSizePolicy::MinimumExpanding
-
- Qt::AlignCenter
+
+
+ 0
+ 0
+
-
- 4
-
-
+
- -
-
+
-
+
- Line AA:
+ Depth Clip:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -2516,26 +2442,23 @@
- -
-
+
-
+
-
-
-
- :/cross.png
+ Front CCW:
- Qt::AlignCenter
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- 4
+
+ true
- -
-
+
-
+
- Sample Mask:
+ Slope-Scaled Bias:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -2563,37 +2486,162 @@
- -
-
-
- Qt::Vertical
+
-
+
+
+
+ 12
+
-
- QSizePolicy::Preferred
+
+ None
-
-
- 0
- 0
-
+
+ Qt::AlignCenter
-
+
+ 4
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 0.00
+
+
+ Qt::AlignCenter
+
+
+ 4
+
+
+
+ -
+
+
+ Cull Mode:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+ -
+
+
+ Depth Bias Clamp:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+ -
+
+
+ Sample Mask:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
-
-
-
- Qt::Horizontal
+
+
+ Base Shading Rate:
-
- QSizePolicy::MinimumExpanding
+
+
+ -
+
+
+
-
-
- 0
- 0
-
+
+ :/cross.png
-
+
+ Qt::AlignCenter
+
+
+ 4
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 0
+
+
+ Qt::AlignCenter
+
+
+ 4
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 1x1
+
+
+
+ -
+
+
+ Shading Rate Image:
+
+
+
+ -
+
+
+ -
+
+
+ Shading Rate Combiners:
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ Keep, Keep
+
+
diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h
index 722e9f647..7754b49f5 100644
--- a/renderdoc/api/replay/d3d12_pipestate.h
+++ b/renderdoc/api/replay/d3d12_pipestate.h
@@ -626,6 +626,34 @@ not force any sample count.
uint32_t forcedSampleCount = 0;
DOCUMENT("The current :class:`ConservativeRaster` mode.");
ConservativeRaster conservativeRasterization = ConservativeRaster::Disabled;
+ DOCUMENT(R"(The current base variable shading rate. This will always be 1x1 when variable shading
+is disabled.
+
+:type: Tuple[int,int]
+)");
+ rdcpair baseShadingRate = {1, 1};
+ DOCUMENT(R"(The shading rate combiners.
+
+The combiners are applied as follows, according to the D3D spec:
+
+ ``intermediateRate = combiner[0] ( baseShadingRate, shaderExportedShadingRate )``
+ ``finalRate = combiner[1] ( intermediateRate, imageBasedShadingRate )``
+
+Where the first input is from :data:`baseShadingRate` and the second is the exported shading rate
+from a vertex or geometry shader, which defaults to 1x1 if not exported.
+
+The intermediate result is then used as the first input to the second combiner, together with the
+shading rate sampled from the shading rate image.
+
+:type: Tuple[ShadingRateCombiner,ShadingRateCombiner]
+)");
+ rdcpair shadingRateCombiners = {
+ ShadingRateCombiner::Passthrough, ShadingRateCombiner::Passthrough};
+ DOCUMENT(R"(The image bound as a shading rate image.
+
+:type: ResourceId
+)");
+ ResourceId shadingRateImage;
};
DOCUMENT("Describes the rasterization state of the D3D12 pipeline.");
diff --git a/renderdoc/api/replay/renderdoc_tostr.inl b/renderdoc/api/replay/renderdoc_tostr.inl
index 5631b67b8..19d524f34 100644
--- a/renderdoc/api/replay/renderdoc_tostr.inl
+++ b/renderdoc/api/replay/renderdoc_tostr.inl
@@ -323,6 +323,20 @@ rdcstr DoStringise(const ConservativeRaster &el)
END_ENUM_STRINGISE();
}
+template <>
+rdcstr DoStringise(const ShadingRateCombiner &el)
+{
+ BEGIN_ENUM_STRINGISE(ShadingRateCombiner)
+ {
+ STRINGISE_ENUM_CLASS(Keep);
+ STRINGISE_ENUM_CLASS(Replace);
+ STRINGISE_ENUM_CLASS(Min);
+ STRINGISE_ENUM_CLASS(Max);
+ STRINGISE_ENUM_CLASS(Multiply);
+ }
+ END_ENUM_STRINGISE();
+}
+
template <>
rdcstr DoStringise(const LineRaster &el)
{
diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h
index dde557b12..c71508423 100644
--- a/renderdoc/api/replay/replay_enums.h
+++ b/renderdoc/api/replay/replay_enums.h
@@ -2709,6 +2709,50 @@ enum class ConservativeRaster : uint32_t
DECLARE_REFLECTION_ENUM(ConservativeRaster);
+DOCUMENT(R"(A combiner to apply when determining a pixel shading rate.
+
+.. data:: Keep
+
+ Keep the first input to the combiner.
+
+.. data:: Passthrough
+
+ Keep the first input to the combiner. Alias for :data:`Keep`, for D3D terminology.
+
+.. data:: Replace
+
+ Replace with the second input to the combiner.
+
+.. data:: Override
+
+ Replace with the second input to the combiner. Alias for :data:`Replace`, for D3D terminology.
+
+.. data:: Min
+
+ Use the minimum (finest rate) of the two inputs.
+
+.. data:: Max
+
+ Use the maximum (coarsest rate) of the two inputs.
+
+.. data:: Multiply
+
+ Multiply the two rates together (e.g. 1x1 and 1x2 = 1x2, 2x2 and 2x2 = 4x4). Note that D3D names
+ this 'sum' misleadingly.
+)");
+enum class ShadingRateCombiner : uint32_t
+{
+ Keep,
+ Passthrough = Keep,
+ Replace,
+ Override = Replace,
+ Min,
+ Max,
+ Multiply,
+};
+
+DECLARE_REFLECTION_ENUM(ShadingRateCombiner);
+
DOCUMENT(R"(The line rasterization mode.
.. data:: Default
diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp
index 66624aaff..ba04fd7df 100644
--- a/renderdoc/driver/d3d12/d3d12_replay.cpp
+++ b/renderdoc/driver/d3d12/d3d12_replay.cpp
@@ -1515,6 +1515,41 @@ void D3D12Replay::SavePipelineState(uint32_t eventId)
src.ConservativeRaster == D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON
? ConservativeRaster::Overestimate
: ConservativeRaster::Disabled;
+
+ switch(rs.shadingRate)
+ {
+ default:
+ case D3D12_SHADING_RATE_1X1: dst.baseShadingRate = {1, 1}; break;
+ case D3D12_SHADING_RATE_1X2: dst.baseShadingRate = {1, 2}; break;
+ case D3D12_SHADING_RATE_2X1: dst.baseShadingRate = {2, 1}; break;
+ case D3D12_SHADING_RATE_2X2: dst.baseShadingRate = {2, 2}; break;
+ case D3D12_SHADING_RATE_2X4: dst.baseShadingRate = {2, 4}; break;
+ case D3D12_SHADING_RATE_4X2: dst.baseShadingRate = {4, 2}; break;
+ case D3D12_SHADING_RATE_4X4: dst.baseShadingRate = {4, 4}; break;
+ }
+
+ ShadingRateCombiner combiners[2];
+
+ for(int i = 0; i < 2; i++)
+ {
+ switch(rs.shadingRateCombiners[i])
+ {
+ default:
+ case D3D12_SHADING_RATE_COMBINER_PASSTHROUGH:
+ combiners[i] = ShadingRateCombiner::Passthrough;
+ break;
+ case D3D12_SHADING_RATE_COMBINER_OVERRIDE:
+ combiners[i] = ShadingRateCombiner::Override;
+ break;
+ case D3D12_SHADING_RATE_COMBINER_MIN: combiners[i] = ShadingRateCombiner::Min; break;
+ case D3D12_SHADING_RATE_COMBINER_MAX: combiners[i] = ShadingRateCombiner::Max; break;
+ case D3D12_SHADING_RATE_COMBINER_SUM: combiners[i] = ShadingRateCombiner::Multiply; break;
+ }
+ }
+
+ dst.shadingRateCombiners = {combiners[0], combiners[1]};
+
+ dst.shadingRateImage = rm->GetOriginalID(rs.shadingRateImage);
}
state.rasterizer.scissors.resize(rs.scissors.size());
diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl
index 52780c3a0..5573af6f4 100644
--- a/renderdoc/replay/renderdoc_serialise.inl
+++ b/renderdoc/replay/renderdoc_serialise.inl
@@ -1439,8 +1439,11 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::RasterizerState &el)
SERIALISE_MEMBER(antialiasedLines);
SERIALISE_MEMBER(forcedSampleCount);
SERIALISE_MEMBER(conservativeRasterization);
+ SERIALISE_MEMBER(baseShadingRate);
+ SERIALISE_MEMBER(shadingRateCombiners);
+ SERIALISE_MEMBER(shadingRateImage);
- SIZE_CHECK(36);
+ SIZE_CHECK(64);
}
template
@@ -1451,7 +1454,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::Rasterizer &el)
SERIALISE_MEMBER(scissors);
SERIALISE_MEMBER(state);
- SIZE_CHECK(96);
+ SIZE_CHECK(120);
}
template
@@ -1539,7 +1542,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::State &el)
SERIALISE_MEMBER(resourceStates);
- SIZE_CHECK(1408);
+ SIZE_CHECK(1432);
}
#pragma endregion D3D12 pipeline state