Improve D3D11 predication handling, and track other asyncs independently

* Instead of replaying predication, we now always skip it during replay,
  so all objects will render. This is much more consistent and
  understandable behaviour instead of things mysteriously disappearing
  with no obvious reason why.
* We track the predication that would have happened and replay Begin/End
  pairs so that we can know if the predication *would* have failed.
* This is displayed in the UI (currently in the raster state, for lack
  of a better location) with the pass/fail that would have happened.
* This information can feed into other places for analysis like the
  pixel history.
This commit is contained in:
baldurk
2017-12-20 23:41:08 +00:00
parent 649e82b8ed
commit b070a371e2
15 changed files with 393 additions and 56 deletions
@@ -77,7 +77,7 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
const QIcon &action = Icons::action();
const QIcon &action_hover = Icons::action_hover();
RDLabel *shaderLabels[] = {
RDLabel *objectLabels[] = {
ui->vsShader, ui->hsShader, ui->dsShader, ui->gsShader,
ui->psShader, ui->csShader, ui->iaBytecode,
};
@@ -137,7 +137,7 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
for(QToolButton *b : viewButtons)
QObject::connect(b, &QToolButton::clicked, this, &D3D11PipelineStateViewer::shaderView_clicked);
for(RDLabel *b : shaderLabels)
for(RDLabel *b : objectLabels)
{
b->setAutoFillBackground(true);
b->setBackgroundRole(QPalette::ToolTipBase);
@@ -173,7 +173,7 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
addGridLines(ui->blendStateGridLayout, palette().color(QPalette::WindowText));
addGridLines(ui->depthStateGridLayout, palette().color(QPalette::WindowText));
for(RDLabel *st : {ui->depthState, ui->blendState, ui->rastState})
for(RDLabel *st : {ui->depthState, ui->blendState, ui->rastState, ui->predicate})
{
st->setAutoFillBackground(true);
st->setBackgroundRole(QPalette::ToolTipBase);
@@ -847,6 +847,8 @@ void D3D11PipelineStateViewer::clearState()
ui->stencilRef->setText(lit("FF"));
ui->stencils->clear();
ui->predicateGroup->setVisible(false);
}
void D3D11PipelineStateViewer::setShaderState(const D3D11Pipe::Shader &stage, RDLabel *shader,
@@ -1539,6 +1541,21 @@ void D3D11PipelineStateViewer::setState()
ui->forcedSampleCount->setText(QString::number(state.m_RS.m_State.ForcedSampleCount));
ui->conservativeRaster->setPixmap(state.m_RS.m_State.ConservativeRasterization ? tick : cross);
////////////////////////////////////////////////
// Predication
if(state.m_Predicate.Obj == ResourceId())
{
ui->predicateGroup->setVisible(false);
}
else
{
ui->predicateGroup->setVisible(true);
ui->predicate->setText(ToQStr(state.m_Predicate.Obj));
ui->predicateValue->setText(state.m_Predicate.Value ? lit("TRUE") : lit("FALSE"));
ui->predicatePassing->setPixmap(state.m_Predicate.Passing ? tick : cross);
}
////////////////////////////////////////////////
// Output Merger
@@ -76,7 +76,7 @@
<string>Show Disabled Items</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_delete.png</normaloff>:/page_white_delete.png</iconset>
</property>
<property name="checkable">
@@ -99,7 +99,7 @@
<string>Show Empty Items</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_database.png</normaloff>:/page_white_database.png</iconset>
</property>
<property name="checkable">
@@ -122,7 +122,7 @@
<string>Export</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="checkable">
@@ -313,7 +313,7 @@
<string>View the mesh input data</string>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/wireframe_mesh.png</pixmap>
<pixmap>:/wireframe_mesh.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
@@ -368,7 +368,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/topologies/topo_trilist.svg</pixmap>
<pixmap>:/topologies/topo_trilist.svg</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -418,7 +418,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -484,6 +484,12 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
@@ -616,7 +622,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -636,7 +642,7 @@
<string>Edit</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -656,7 +662,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -987,7 +993,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1007,7 +1013,7 @@
<string>Edit</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1027,7 +1033,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1355,7 +1361,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1375,7 +1381,7 @@
<string>Edit</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1395,7 +1401,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1723,7 +1729,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1743,7 +1749,7 @@
<string>Edit</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -1763,7 +1769,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -2273,7 +2279,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -2289,7 +2295,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -2305,7 +2311,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -2339,7 +2345,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -2456,7 +2462,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -2485,7 +2491,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -2536,7 +2542,7 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QGroupBox" name="viewportsGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -2591,7 +2597,7 @@
</layout>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QGroupBox" name="scissorGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -2646,6 +2652,67 @@
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="predicateGroup">
<property name="title">
<string>Predication</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_41">
<item>
<widget class="RDLabel" name="predicate">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="margin">
<number>4</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Value:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="predicateValue">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>FALSE</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Passing:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="predicatePassing"/>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="PS">
@@ -2705,7 +2772,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -2725,7 +2792,7 @@
<string>Edit</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -2745,7 +2812,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -3239,7 +3306,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -3330,7 +3397,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -3411,7 +3478,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -3437,7 +3504,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -3618,7 +3685,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../Resources/resources.qrc">:/cross.png</pixmap>
<pixmap>:/cross.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -3853,7 +3920,7 @@
<string>View</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/action.png</normaloff>:/action.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -3873,7 +3940,7 @@
<string>Edit</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -3893,7 +3960,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -3969,7 +4036,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../Resources/resources.qrc">
<iconset>
<normaloff>:/wrench.png</normaloff>:/wrench.png</iconset>
</property>
<property name="autoRaise">
@@ -4314,8 +4381,6 @@
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../Resources/resources.qrc"/>
</resources>
<resources/>
<connections/>
</ui>
+2
View File
@@ -547,6 +547,8 @@ private:
s += tr("\nDepth test failed");
if(mod.stencilTestFailed)
s += tr("\nStencil test failed");
if(mod.predicationSkipped)
s += tr("\nPredicated rendering skipped");
return s;
}
+18 -1
View File
@@ -704,10 +704,23 @@ struct OM
View DepthTarget;
DOCUMENT("``True`` if depth access to the depth-stencil target is read-only.");
bool DepthReadOnly = false;
DOCUMENT("``True`` if stenncil access to the depth-stencil target is read-only.");
DOCUMENT("``True`` if stencil access to the depth-stencil target is read-only.");
bool StencilReadOnly = false;
};
DOCUMENT("Describes the current state of predicated rendering.");
struct Predication
{
DOCUMENT("The :class:`ResourceId` of the active predicate.");
ResourceId Obj;
DOCUMENT("The value to go along with the predicate.");
bool Value = false;
DOCUMENT("``True`` if the current predicate would render.");
bool Passing = false;
};
DOCUMENT("The full current D3D11 pipeline state.");
struct State
{
@@ -735,6 +748,9 @@ struct State
DOCUMENT("A :class:`D3D11_OM` describing the output merger pipeline stage.");
OM m_OM;
DOCUMENT("A :class:`Predication` describing the predicated rendering state.");
Predication m_Predicate;
};
}; // namespace D3D11Pipe
@@ -759,4 +775,5 @@ DECLARE_REFLECTION_STRUCT(D3D11Pipe::Blend);
DECLARE_REFLECTION_STRUCT(D3D11Pipe::BlendEquation);
DECLARE_REFLECTION_STRUCT(D3D11Pipe::BlendState);
DECLARE_REFLECTION_STRUCT(D3D11Pipe::OM);
DECLARE_REFLECTION_STRUCT(D3D11Pipe::Predication);
DECLARE_REFLECTION_STRUCT(D3D11Pipe::State);
+3 -1
View File
@@ -1362,6 +1362,8 @@ pixel.
bool depthTestFailed;
DOCUMENT("``True`` if stencil testing eliminated this fragment.");
bool stencilTestFailed;
DOCUMENT("``True`` if predicated rendering skipped this call.");
bool predicationSkipped;
DOCUMENT(R"(Determine if this fragment passed all tests and wrote to the texture.
@@ -1371,7 +1373,7 @@ pixel.
bool passed() const
{
return !sampleMasked && !backfaceCulled && !depthClipped && !viewClipped && !scissorClipped &&
!shaderDiscarded && !depthTestFailed && !stencilTestFailed;
!shaderDiscarded && !depthTestFailed && !stencilTestFailed && !predicationSkipped;
}
};
+8
View File
@@ -5167,6 +5167,9 @@ vector<PixelModification> D3D11DebugManager::PixelHistory(vector<EventUsage> eve
// if the sample mask set at this event doesn't have the right bit set
TestMustFail_SampleMask = 1 << 10,
// if predication was failing at this event
Predication_Failed = 1 << 11,
};
#if 1
@@ -5487,6 +5490,9 @@ vector<PixelModification> D3D11DebugManager::PixelHistory(vector<EventUsage> eve
flags[ev] |= TestMustFail_SampleMask;
}
if(!m_WrappedContext->GetCurrentPipelineState()->PredicationWouldPass())
flags[ev] |= Predication_Failed;
m_pDevice->CreateRasterizerState(&rd, &newRS);
m_pImmediateContext->RSSetState(newRS);
SAFE_RELEASE(newRS);
@@ -5916,6 +5922,8 @@ vector<PixelModification> D3D11DebugManager::PixelHistory(vector<EventUsage> eve
mod.scissorClipped = true;
if(flags[i] & TestMustFail_SampleMask)
mod.sampleMasked = true;
if(flags[i] & Predication_Failed)
mod.predicationSkipped = true;
m_WrappedDevice->ReplayLog(0, events[i].eventID, eReplay_WithoutDraw);
+83 -1
View File
@@ -6400,21 +6400,49 @@ bool WrappedID3D11DeviceContext::Serialise_Begin(SerialiserType &ser, ID3D11Asyn
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading() && pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
// only replay predicates which can affect rendering, don't re-submit queries or counters (that
// might even interfere with queries we want to run)
if(WrappedID3D11Predicate::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
// if you change this to replay other types, check with Serialise_CreateCounter which creates
// dummy queries to ensure it always succeeds.
if(unwrapped)
m_pRealContext->Begin(unwrapped);
}
return true;
}
void WrappedID3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
ResourceId id;
if(WrappedID3D11Query1::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Query1, pAsync);
id = ((WrappedID3D11Query1 *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Predicate::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
id = ((WrappedID3D11Predicate *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Counter::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Counter, pAsync);
id = ((WrappedID3D11Counter *)pAsync)->GetResourceID();
}
else
{
RDCERR("Unexpected ID3D11Asynchronous");
}
SERIALISE_TIME_CALL(m_pRealContext->Begin(unwrapped));
@@ -6426,6 +6454,8 @@ void WrappedID3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync)
Serialise_Begin(GET_SERIALISER, pAsync);
m_ContextRecord->AddChunk(scope.Get());
MarkResourceReferenced(id, eFrameRef_Read);
}
}
@@ -6436,21 +6466,49 @@ bool WrappedID3D11DeviceContext::Serialise_End(SerialiserType &ser, ID3D11Asynch
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading() && pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
// only replay predicates which can affect rendering, don't re-submit queries or counters (that
// might even interfere with queries we want to run)
if(WrappedID3D11Predicate::IsAlloc(pAsync))
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
// if you change this to replay other types, check with Serialise_CreateCounter which creates
// dummy queries to ensure it always succeeds.
if(unwrapped)
m_pRealContext->End(unwrapped);
}
return true;
}
void WrappedID3D11DeviceContext::End(ID3D11Asynchronous *pAsync)
{
ID3D11Asynchronous *unwrapped = NULL;
ResourceId id;
if(WrappedID3D11Query1::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Query1, pAsync);
id = ((WrappedID3D11Query1 *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Predicate::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Predicate, pAsync);
id = ((WrappedID3D11Predicate *)pAsync)->GetResourceID();
}
else if(WrappedID3D11Counter::IsAlloc(pAsync))
{
unwrapped = UNWRAP(WrappedID3D11Counter, pAsync);
id = ((WrappedID3D11Counter *)pAsync)->GetResourceID();
}
else
{
RDCERR("Unexpected ID3D11Asynchronous");
}
SERIALISE_TIME_CALL(m_pRealContext->End(unwrapped));
@@ -6462,6 +6520,8 @@ void WrappedID3D11DeviceContext::End(ID3D11Asynchronous *pAsync)
Serialise_End(GET_SERIALISER, pAsync);
m_ContextRecord->AddChunk(scope.Get());
MarkResourceReferenced(id, eFrameRef_Read);
}
}
@@ -6494,7 +6554,16 @@ bool WrappedID3D11DeviceContext::Serialise_SetPredication(SerialiserType &ser,
if(IsReplayingAndReading())
{
m_pRealContext->SetPredication(pPredicate, PredicateValue ? TRUE : FALSE);
// we don't replay predication as it can be confusing and inconsistent. We just store the state
// so that we can manually check whether it *would* have passed or failed.
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->Predicate, pPredicate);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PredicateValue,
PredicateValue ? TRUE : FALSE);
/*
m_pRealContext->SetPredication(UNWRAP(WrappedID3D11Predicate, pPredicate),
PredicateValue ? TRUE : FALSE);
*/
}
return true;
@@ -6504,6 +6573,13 @@ void WrappedID3D11DeviceContext::SetPredication(ID3D11Predicate *pPredicate, BOO
{
m_EmptyCommandList = false;
m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->Predicate, pPredicate);
m_CurrentPipelineState->Change(m_CurrentPipelineState->PredicateValue, PredicateValue);
// on replay don't actually apply any predication. Just update the state and bail
if(IsReplayMode(m_State))
return;
SERIALISE_TIME_CALL(
m_pRealContext->SetPredication(UNWRAP(WrappedID3D11Predicate, pPredicate), PredicateValue));
@@ -6515,6 +6591,12 @@ void WrappedID3D11DeviceContext::SetPredication(ID3D11Predicate *pPredicate, BOO
Serialise_SetPredication(GET_SERIALISER, pPredicate, PredicateValue);
m_ContextRecord->AddChunk(scope.Get());
if(pPredicate)
{
ResourceId id = ((WrappedID3D11Predicate *)pPredicate)->GetResourceID();
MarkResourceReferenced(id, eFrameRef_Read);
}
}
}
+12
View File
@@ -3819,6 +3819,18 @@ void D3D11DebugManager::ClearPostVSCache()
m_PostVSData.clear();
}
void D3D11DebugManager::RenderForPredicate()
{
// just somehow draw a quad that renders some pixels to fill the predicate with TRUE
m_WrappedContext->ClearState();
D3D11_VIEWPORT viewport = {0, 0, 1, 1, 0.0f, 1.0f};
m_WrappedContext->RSSetViewports(1, &viewport);
m_WrappedContext->VSSetShader(m_DebugRender.FullscreenVS, NULL, 0);
m_WrappedContext->PSSetShader(m_DebugRender.WireframePS, NULL, 0);
m_WrappedContext->OMSetRenderTargets(1, &m_DebugRender.PickPixelRT, NULL);
m_WrappedContext->Draw(3, 0);
}
MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage)
{
D3D11PostVSData postvs;
+2
View File
@@ -130,6 +130,8 @@ public:
MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage);
void ClearPostVSCache();
void RenderForPredicate();
uint32_t GetStructCount(ID3D11UnorderedAccessView *uav);
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, bytebuf &retData);
void GetBufferData(ID3D11Buffer *buff, uint64_t offset, uint64_t length, bytebuf &retData);
+1 -1
View File
@@ -62,7 +62,7 @@ struct D3D11InitParams
D3D_FEATURE_LEVEL FeatureLevels[16];
// check if a frame capture section version is supported
static const uint64_t CurrentVersion = 0xD;
static const uint64_t CurrentVersion = 0xE;
static bool IsSupportedVersion(uint64_t ver);
};
+46 -6
View File
@@ -2615,7 +2615,15 @@ HRESULT WrappedID3D11Device::CreateQuery(const D3D11_QUERY_DESC *pQueryDesc, ID3
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateQuery);
Serialise_CreateQuery(GET_SERIALISER, pQueryDesc, &wrapped);
m_DeviceRecord->AddChunk(scope.Get());
WrappedID3D11Query1 *q = (WrappedID3D11Query1 *)wrapped;
ResourceId id = q->GetResourceID();
RDCASSERT(GetResourceManager()->GetResourceRecord(id) == NULL);
D3D11ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
record->Length = 0;
record->AddChunk(scope.Get());
}
*ppQuery = wrapped;
@@ -2636,6 +2644,10 @@ bool WrappedID3D11Device::Serialise_CreatePredicate(SerialiserType &ser,
if(IsReplayingAndReading())
{
// We don't use predicates directly, so removing this flag doesn't make any direct difference.
// It means we can query the result via GetData which we can't if the flag is set.
Descriptor.MiscFlags &= ~D3D11_QUERY_MISC_PREDICATEHINT;
ID3D11Predicate *ret;
HRESULT hr = m_pDevice->CreatePredicate(&Descriptor, &ret);
@@ -2652,6 +2664,12 @@ bool WrappedID3D11Device::Serialise_CreatePredicate(SerialiserType &ser,
}
AddResource(pPredicate, ResourceType::Query, "Predicate");
// prime the predicate with a true result, so that if we end up referencing a predicate that was
// filled in a previous frame that we don't have the data for, we default to passing.
m_pImmediateContext->Begin(ret);
GetDebugManager()->RenderForPredicate();
m_pImmediateContext->End(ret);
}
return true;
@@ -2681,7 +2699,15 @@ HRESULT WrappedID3D11Device::CreatePredicate(const D3D11_QUERY_DESC *pPredicateD
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreatePredicate);
Serialise_CreatePredicate(GET_SERIALISER, pPredicateDesc, &wrapped);
m_DeviceRecord->AddChunk(scope.Get());
WrappedID3D11Predicate *p = (WrappedID3D11Predicate *)wrapped;
ResourceId id = p->GetResourceID();
RDCASSERT(GetResourceManager()->GetResourceRecord(id) == NULL);
D3D11ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
record->Length = 0;
record->AddChunk(scope.Get());
}
*ppPredicate = wrapped;
@@ -2702,8 +2728,14 @@ bool WrappedID3D11Device::Serialise_CreateCounter(SerialiserType &ser,
if(IsReplayingAndReading())
{
ID3D11Counter *ret;
HRESULT hr = m_pDevice->CreateCounter(&Descriptor, &ret);
// counters may not always be available on the replay, so instead we create a timestamp query as
// a dummy. We never replay any counter fetch since it doesn't affect rendering, so the
// difference doesn't matter.
D3D11_QUERY_DESC dummyQueryDesc;
dummyQueryDesc.Query = D3D11_QUERY_TIMESTAMP;
dummyQueryDesc.MiscFlags = 0;
ID3D11Query *ret;
HRESULT hr = m_pDevice->CreateQuery(&dummyQueryDesc, &ret);
if(FAILED(hr))
{
@@ -2712,7 +2744,7 @@ bool WrappedID3D11Device::Serialise_CreateCounter(SerialiserType &ser,
}
else
{
ret = new WrappedID3D11Counter(ret, this);
ret = new WrappedID3D11Query1(ret, this);
GetResourceManager()->AddLiveResource(pCounter, ret);
}
@@ -2747,7 +2779,15 @@ HRESULT WrappedID3D11Device::CreateCounter(const D3D11_COUNTER_DESC *pCounterDes
SCOPED_SERIALISE_CHUNK(D3D11Chunk::CreateCounter);
Serialise_CreateCounter(GET_SERIALISER, pCounterDesc, &wrapped);
m_DeviceRecord->AddChunk(scope.Get());
WrappedID3D11Counter *c = (WrappedID3D11Counter *)wrapped;
ResourceId id = c->GetResourceID();
RDCASSERT(GetResourceManager()->GetResourceRecord(id) == NULL);
D3D11ResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
record->Length = 0;
record->AddChunk(scope.Get());
}
*ppCounter = wrapped;
@@ -41,6 +41,8 @@ D3D11RenderState::D3D11RenderState(D3D11RenderState::EmptyInit)
RDCEraseEl(OM);
RDCEraseEl(CS);
RDCEraseEl(CSUAVs);
Predicate = NULL;
PredicateValue = FALSE;
Clear();
m_ImmediatePipeline = false;
@@ -61,6 +63,8 @@ D3D11RenderState::D3D11RenderState(const D3D11RenderState &other)
RDCEraseEl(OM);
RDCEraseEl(CS);
RDCEraseEl(CSUAVs);
Predicate = NULL;
PredicateValue = FALSE;
m_ImmediatePipeline = false;
m_pDevice = NULL;
@@ -84,6 +88,9 @@ void D3D11RenderState::CopyState(const D3D11RenderState &other)
memcpy(&CS, &other.CS, sizeof(CS));
memcpy(&CSUAVs, &other.CSUAVs, sizeof(CSUAVs));
Predicate = other.Predicate;
PredicateValue = other.PredicateValue;
m_ViewportScissorPartial = other.m_ViewportScissorPartial;
AddRefs();
@@ -143,6 +150,8 @@ void D3D11RenderState::ReleaseRefs()
ReleaseRef(OM.DepthView);
ReleaseRef(Predicate);
RDCEraseEl(IA);
RDCEraseEl(VS);
RDCEraseEl(HS);
@@ -154,6 +163,7 @@ void D3D11RenderState::ReleaseRefs()
RDCEraseEl(OM);
RDCEraseEl(CS);
RDCEraseEl(CSUAVs);
Predicate = NULL;
}
void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool initial) const
@@ -254,6 +264,12 @@ void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool init
ctx->MarkResourceReferenced(GetViewResourceResID(OM.DepthView),
initial ? eFrameRef_Unknown : eFrameRef_Write);
}
if(Predicate)
{
ctx->MarkResourceReferenced(GetIDForResource(Predicate),
initial ? eFrameRef_Unknown : eFrameRef_Read);
}
}
void D3D11RenderState::CacheViewportPartial()
@@ -394,6 +410,8 @@ void D3D11RenderState::AddRefs()
TakeRef(OM.UAVs[i]);
TakeRef(OM.DepthView);
TakeRef(Predicate);
}
D3D11RenderState::D3D11RenderState(WrappedID3D11DeviceContext *context)
@@ -490,6 +508,8 @@ D3D11RenderState::D3D11RenderState(WrappedID3D11DeviceContext *context)
context->OMGetRenderTargetsAndUnorderedAccessViews(
OM.UAVStartSlot, OM.RenderTargets, &OM.DepthView, OM.UAVStartSlot,
D3D11_PS_CS_UAV_REGISTER_COUNT - OM.UAVStartSlot, OM.UAVs);
context->GetPredication(&Predicate, &PredicateValue);
}
void D3D11RenderState::Clear()
@@ -498,11 +518,42 @@ void D3D11RenderState::Clear()
OM.BlendFactor[0] = OM.BlendFactor[1] = OM.BlendFactor[2] = OM.BlendFactor[3] = 1.0f;
OM.SampleMask = 0xffffffff;
Predicate = NULL;
PredicateValue = FALSE;
for(size_t i = 0; i < ARRAY_COUNT(VS.CBCounts); i++)
VS.CBCounts[i] = HS.CBCounts[i] = DS.CBCounts[i] = GS.CBCounts[i] = PS.CBCounts[i] =
CS.CBCounts[i] = 4096;
}
bool D3D11RenderState::PredicationWouldPass()
{
if(Predicate == NULL)
return true;
BOOL data = TRUE;
HRESULT hr = S_FALSE;
do
{
hr = m_pDevice->GetImmediateContext()->GetData(Predicate, &data, sizeof(BOOL), 0);
} while(hr == S_FALSE);
RDCASSERTEQUAL(hr, S_OK);
// From SetPredication for PredicateValue:
//
// "If TRUE, rendering will be affected by when the predicate's conditions are met. If FALSE,
// rendering will be affected when the conditions are not met."
//
// Which is really confusingly worded. 'rendering will be affected' means 'no rendering will
// happen', and 'conditions are met' for e.g. an occlusion query means that it passed.
// Thus a passing occlusion query has value TRUE and is 'condition is met', so for a typical "skip
// when occlusion query fails" the value will be FALSE.
return PredicateValue != data;
}
void D3D11RenderState::ApplyState(WrappedID3D11DeviceContext *context)
{
context->ClearState();
@@ -583,6 +634,8 @@ void D3D11RenderState::ApplyState(WrappedID3D11DeviceContext *context)
context->OMSetRenderTargetsAndUnorderedAccessViews(
OM.UAVStartSlot, OM.RenderTargets, OM.DepthView, OM.UAVStartSlot,
D3D11_PS_CS_UAV_REGISTER_COUNT - OM.UAVStartSlot, OM.UAVs, UAV_keepcounts);
context->SetPredication(Predicate, PredicateValue);
}
void D3D11RenderState::TakeRef(ID3D11DeviceChild *p)
@@ -1268,6 +1321,12 @@ bool D3D11RenderState::IsBoundForWrite(ID3D11InputLayout *resource)
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11Predicate *resource)
{
return false;
}
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11ClassInstance *resource)
{
@@ -1472,6 +1531,8 @@ void DoSerialise(SerialiserType &ser, D3D11RenderState &el)
SERIALISE_MEMBER(SO);
SERIALISE_MEMBER(RS);
SERIALISE_MEMBER(OM);
SERIALISE_MEMBER(Predicate);
SERIALISE_MEMBER(PredicateValue);
if(ser.IsReading())
el.AddRefs();
@@ -268,6 +268,11 @@ struct D3D11RenderState
ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT];
} OM;
ID3D11Predicate *Predicate;
BOOL PredicateValue;
bool PredicationWouldPass();
void SetImmediatePipeline(WrappedID3D11Device *device)
{
m_ImmediatePipeline = true;
@@ -311,6 +316,9 @@ private:
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11InputLayout *resource);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11Predicate *resource);
template <>
bool D3D11RenderState::IsBoundForWrite(ID3D11ClassInstance *resource);
+8
View File
@@ -1216,6 +1216,14 @@ void D3D11Replay::SavePipelineState()
ret.m_OM.m_State.m_BackFace.FailOp = StencilOp::Keep;
}
}
/////////////////////////////////////////////////
// Predication
/////////////////////////////////////////////////
ret.m_Predicate.Obj = rm->GetOriginalID(GetIDForResource(rs->Predicate));
ret.m_Predicate.Value = rs->PredicateValue == TRUE ? true : false;
ret.m_Predicate.Passing = rs->PredicationWouldPass();
}
ReplayStatus D3D11Replay::ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers)
+15 -2
View File
@@ -768,8 +768,9 @@ void DoSerialise(SerialiserType &ser, PixelModification &el)
SERIALISE_MEMBER(shaderDiscarded);
SERIALISE_MEMBER(depthTestFailed);
SERIALISE_MEMBER(stencilTestFailed);
SERIALISE_MEMBER(predicationSkipped);
SIZE_CHECK(96);
SIZE_CHECK(100);
}
template <typename SerialiserType>
@@ -1072,6 +1073,16 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::OM &el)
SIZE_CHECK(224);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D11Pipe::Predication &el)
{
SERIALISE_MEMBER(Obj);
SERIALISE_MEMBER(Value);
SERIALISE_MEMBER(Passing);
SIZE_CHECK(16);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el)
{
@@ -1089,7 +1100,9 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el)
SERIALISE_MEMBER(m_RS);
SERIALISE_MEMBER(m_OM);
SIZE_CHECK(1488);
SERIALISE_MEMBER(m_Predicate);
SIZE_CHECK(1504);
}
#pragma endregion D3D11 pipeline state