Skip to content

Commit c7493c1

Browse files
Fixed issue with setting scissor rects in D3D12 backend
1 parent 3f757fc commit c7493c1

File tree

2 files changed

+92
-66
lines changed

2 files changed

+92
-66
lines changed

Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class DeviceContextD3D12Impl : public DeviceContextBase<IDeviceContextD3D12>
117117
void TransitionD3D12VertexBuffers(class GraphicsContext &GraphCtx);
118118
void CommitRenderTargets();
119119
void CommitViewports();
120-
void CommitScissorRects();
120+
void CommitScissorRects(class GraphicsContext &GraphCtx, bool ScissorEnable);
121121
void Flush(bool RequestNewCmdCtx);
122122

123123
friend class SwapChainD3D12Impl;

Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp

+91-65
Original file line numberDiff line numberDiff line change
@@ -89,31 +89,6 @@ namespace Diligent
8989

9090
IMPLEMENT_QUERY_INTERFACE( DeviceContextD3D12Impl, IID_DeviceContextD3D12, TDeviceContextBase )
9191

92-
const LONG MaxD3D12TexDim = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
93-
const Uint32 MaxD3D12ScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
94-
static const RECT MaxD3D12TexSizeRects[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] =
95-
{
96-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
97-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
98-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
99-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
100-
101-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
102-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
103-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
104-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
105-
106-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
107-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
108-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
109-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
110-
111-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
112-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
113-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim},
114-
{0,0, MaxD3D12TexDim,MaxD3D12TexDim}
115-
};
116-
11792
void DeviceContextD3D12Impl::SetPipelineState(IPipelineState *pPipelineState)
11893
{
11994
// Never flush deferred context!
@@ -122,18 +97,36 @@ namespace Diligent
12297
Flush(true);
12398
}
12499

125-
// If no pipeline state is bound, we are working with the fresh command
126-
// list. We have to commit the states set in the context that are not
127-
// committed by the draw command (render targets, viewports, scissor rects, etc.)
128-
bool CommitStates = !m_pPipelineState;
100+
auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pPipelineState);
101+
const auto &PSODesc = pPipelineStateD3D12->GetDesc();
102+
103+
bool CommitStates = false;
104+
bool CommitScissor = false;
105+
if(!m_pPipelineState)
106+
{
107+
// If no pipeline state is bound, we are working with the fresh command
108+
// list. We have to commit the states set in the context that are not
109+
// committed by the draw command (render targets, viewports, scissor rects, etc.)
110+
CommitStates = true;
111+
}
112+
else
113+
{
114+
const auto& OldPSODesc = m_pPipelineState->GetDesc();
115+
// Commit all graphics states when switching from compute pipeline
116+
// This is necessary because if the command list had been flushed
117+
// and the first PSO set on the command list was a compute pipeline,
118+
// the states would otherwise never be committed (since m_pPipelineState != nullptr)
119+
CommitStates = OldPSODesc.IsComputePipeline;
120+
// We also need to update scissor rect if ScissorEnable state has changed
121+
CommitScissor = OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable != PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable;
122+
}
129123

130124
TDeviceContextBase::SetPipelineState( pPipelineState );
131-
auto *pPipelineStateD3D12 = ValidatedCast<PipelineStateD3D12Impl>(pPipelineState);
132125

133126
auto *pCmdCtx = RequestCmdContext();
134-
const auto &Desc = pPipelineStateD3D12->GetDesc();
127+
135128
auto *pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState();
136-
if (Desc.IsComputePipeline)
129+
if (PSODesc.IsComputePipeline)
137130
{
138131
pCmdCtx->AsComputeContext().SetPipelineState(pd3d12PSO);
139132
}
@@ -142,33 +135,18 @@ namespace Diligent
142135
auto &GraphicsCtx = pCmdCtx->AsGraphicsContext();
143136
GraphicsCtx.SetPipelineState(pd3d12PSO);
144137

145-
if (CommitStates)
138+
if(CommitStates)
146139
{
147-
if (Desc.GraphicsPipeline.RasterizerDesc.ScissorEnable)
148-
{
149-
// Commit currently set scissor rectangles
150-
D3D12_RECT d3d12ScissorRects[MaxD3D12ScissorRects]; // Do not waste time initializing array with zeroes
151-
for( Uint32 sr = 0; sr < m_NumScissorRects; ++sr )
152-
{
153-
d3d12ScissorRects[sr].left = m_ScissorRects[sr].left;
154-
d3d12ScissorRects[sr].top = m_ScissorRects[sr].top;
155-
d3d12ScissorRects[sr].right = m_ScissorRects[sr].right;
156-
d3d12ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
157-
}
158-
GraphicsCtx.SetScissorRects(m_NumScissorRects, d3d12ScissorRects);
159-
}
160-
else
161-
{
162-
// Disable scissor rectangles
163-
static_assert(_countof(MaxD3D12TexSizeRects) == MaxD3D12ScissorRects, "Unexpected array size");
164-
GraphicsCtx.SetScissorRects(MaxD3D12ScissorRects, MaxD3D12TexSizeRects);
165-
}
166-
167140
GraphicsCtx.SetStencilRef(m_StencilRef);
168141
GraphicsCtx.SetBlendFactor(m_BlendFactors);
169142
CommitRenderTargets();
170143
CommitViewports();
171144
}
145+
146+
if(CommitStates || CommitScissor)
147+
{
148+
CommitScissorRects(GraphicsCtx, PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable);
149+
}
172150
}
173151
m_pCommittedResourceCache = nullptr;
174152
}
@@ -516,7 +494,7 @@ namespace Diligent
516494
}
517495
}
518496

519-
static const float Zero[4] = { 0.f, 0.f, 0.f, 0.f };
497+
static constexpr float Zero[4] = { 0.f, 0.f, 0.f, 0.f };
520498
if( RGBA == nullptr )
521499
RGBA = Zero;
522500

@@ -586,7 +564,7 @@ namespace Diligent
586564

587565
void DeviceContextD3D12Impl::CommitViewports()
588566
{
589-
const Uint32 MaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
567+
constexpr Uint32 MaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
590568
D3D12_VIEWPORT d3d12Viewports[MaxViewports]; // Do not waste time initializing array to zero
591569

592570
for( Uint32 vp = 0; vp < m_NumViewports; ++vp )
@@ -605,7 +583,7 @@ namespace Diligent
605583

606584
void DeviceContextD3D12Impl::SetViewports( Uint32 NumViewports, const Viewport *pViewports, Uint32 RTWidth, Uint32 RTHeight )
607585
{
608-
const Uint32 MaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
586+
constexpr Uint32 MaxViewports = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
609587
VERIFY( NumViewports < MaxViewports, "Too many viewports are being set" );
610588
NumViewports = std::min( NumViewports, MaxViewports );
611589

@@ -615,6 +593,55 @@ namespace Diligent
615593
CommitViewports();
616594
}
617595

596+
597+
constexpr LONG MaxD3D12TexDim = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
598+
constexpr Uint32 MaxD3D12ScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
599+
static constexpr RECT MaxD3D12TexSizeRects[D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] =
600+
{
601+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
602+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
603+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
604+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
605+
606+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
607+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
608+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
609+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
610+
611+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
612+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
613+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
614+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
615+
616+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
617+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
618+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim },
619+
{ 0,0, MaxD3D12TexDim,MaxD3D12TexDim }
620+
};
621+
622+
void DeviceContextD3D12Impl::CommitScissorRects(GraphicsContext &GraphCtx, bool ScissorEnable)
623+
{
624+
if (ScissorEnable)
625+
{
626+
// Commit currently set scissor rectangles
627+
D3D12_RECT d3d12ScissorRects[MaxD3D12ScissorRects]; // Do not waste time initializing array with zeroes
628+
for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr)
629+
{
630+
d3d12ScissorRects[sr].left = m_ScissorRects[sr].left;
631+
d3d12ScissorRects[sr].top = m_ScissorRects[sr].top;
632+
d3d12ScissorRects[sr].right = m_ScissorRects[sr].right;
633+
d3d12ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
634+
}
635+
GraphCtx.SetScissorRects(m_NumScissorRects, d3d12ScissorRects);
636+
}
637+
else
638+
{
639+
// Disable scissor rectangles
640+
static_assert(_countof(MaxD3D12TexSizeRects) == MaxD3D12ScissorRects, "Unexpected array size");
641+
GraphCtx.SetScissorRects(MaxD3D12ScissorRects, MaxD3D12TexSizeRects);
642+
}
643+
}
644+
618645
void DeviceContextD3D12Impl::SetScissorRects( Uint32 NumRects, const Rect *pRects, Uint32 RTWidth, Uint32 RTHeight )
619646
{
620647
const Uint32 MaxScissorRects = D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
@@ -624,18 +651,17 @@ namespace Diligent
624651
TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
625652

626653
// Only commit scissor rects if scissor test is enabled in the rasterizer state.
627-
if( !m_pPipelineState || m_pPipelineState->GetDesc().GraphicsPipeline.RasterizerDesc.ScissorEnable )
654+
// If scissor is currently disabled, or no PSO is bound, scissor rects will be committed by
655+
// the SetPipelineState() when a PSO with enabled scissor test is set.
656+
if( m_pPipelineState )
628657
{
629-
D3D12_RECT d3d12ScissorRects[MaxScissorRects];
630-
VERIFY( NumRects == m_NumScissorRects, "Unexpected number of scissor rects" );
631-
for( Uint32 sr = 0; sr < NumRects; ++sr )
658+
const auto &PSODesc = m_pPipelineState->GetDesc();
659+
if(!PSODesc.IsComputePipeline && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable)
632660
{
633-
d3d12ScissorRects[sr].left = m_ScissorRects[sr].left;
634-
d3d12ScissorRects[sr].top = m_ScissorRects[sr].top;
635-
d3d12ScissorRects[sr].right = m_ScissorRects[sr].right;
636-
d3d12ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
661+
VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
662+
auto &Ctx = RequestCmdContext()->AsGraphicsContext();
663+
CommitScissorRects(Ctx, true);
637664
}
638-
RequestCmdContext()->AsGraphicsContext().SetScissorRects(NumRects, d3d12ScissorRects);
639665
}
640666
}
641667

0 commit comments

Comments
 (0)