@@ -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