Diligent Engine API Reference
CommandContext.h
1 /* Copyright 2015-2018 Egor Yusov
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12  *
13  * In no event and under no legal theory, whether in tort (including negligence),
14  * contract, or otherwise, unless required by applicable law (such as deliberate
15  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16  * liable for any damages, including any direct, indirect, special, incidental,
17  * or consequential damages of any character arising as a result of this License or
18  * out of the use or inability to use the software (including but not limited to damages
19  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20  * all other commercial damages or losses), even if such Contributor has been advised
21  * of the possibility of such damages.
22  */
23 
24 
25 #pragma once
26 
27 #include <vector>
28 
29 #include "D3D12ResourceBase.h"
30 #include "TextureViewD3D12.h"
31 #include "TextureD3D12.h"
32 #include "BufferD3D12.h"
33 #include "DescriptorHeap.h"
34 
35 namespace Diligent
36 {
37 
38 
39 struct DWParam
40 {
41  DWParam( FLOAT f ) : Float(f) {}
42  DWParam( UINT u ) : Uint(u) {}
43  DWParam( INT i ) : Int(i) {}
44 
45  void operator= ( FLOAT f ) { Float = f; }
46  void operator= ( UINT u ) { Uint = u; }
47  void operator= ( INT i ) { Int = i; }
48 
49  union
50  {
51  FLOAT Float;
52  UINT Uint;
53  INT Int;
54  };
55 };
56 
57 
58 class CommandContext
59 {
60 public:
61 
62  CommandContext( IMemoryAllocator &MemAllocator,
63  class CommandListManager& CmdListManager,
64  GPUDescriptorHeap GPUDescriptorHeaps[],
65  const Uint32 DynamicDescriptorAllocationChunkSize[]);
66 
67  ~CommandContext(void);
68 
69  // Submit the command buffer and reset it. This is encouraged to keep the GPU busy and reduce latency.
70  // Taking too long to build command lists and submit them can idle the GPU.
71  ID3D12GraphicsCommandList* Close(ID3D12CommandAllocator **ppAllocator);
72  void Reset( CommandListManager& CmdListManager );
73 
74  class GraphicsContext& AsGraphicsContext();
75  class ComputeContext& AsComputeContext();
76 
77  void ClearUAVFloat( ITextureViewD3D12 *pTexView, const float* Color );
78  void ClearUAVUint( ITextureViewD3D12 *pTexView, const UINT *Color );
79 
80  void CopyResource(ID3D12Resource *pDstRes, ID3D12Resource *pSrcRes)
81  {
82  m_pCommandList->CopyResource(pDstRes, pSrcRes);
83  }
84 
85  void TransitionResource(ITextureD3D12 *pTexture, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
86  void TransitionResource(IBufferD3D12 *pBuffer, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
87  //void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false);
88  void FlushResourceBarriers();
89 
90  struct ShaderDescriptorHeaps
91  {
92  ID3D12DescriptorHeap* pSrvCbvUavHeap;
93  ID3D12DescriptorHeap* pSamplerHeap;
94  ShaderDescriptorHeaps(ID3D12DescriptorHeap* _pSrvCbvUavHeap = nullptr, ID3D12DescriptorHeap* _pSamplerHeap = nullptr) :
95  pSrvCbvUavHeap(_pSrvCbvUavHeap),
96  pSamplerHeap(_pSamplerHeap)
97  {}
98  bool operator == (const ShaderDescriptorHeaps& rhs)const
99  {
100  return pSrvCbvUavHeap == rhs.pSrvCbvUavHeap && pSamplerHeap == rhs.pSamplerHeap;
101  }
102  operator bool()const
103  {
104  return pSrvCbvUavHeap != nullptr || pSamplerHeap != nullptr;
105  }
106  };
107  void SetDescriptorHeaps( ShaderDescriptorHeaps& Heaps );
108 
109  void ExecuteIndirect(ID3D12CommandSignature *pCmdSignature, ID3D12Resource *pBuff, Uint64 ArgsOffset)
110  {
111  FlushResourceBarriers();
112  m_pCommandList->ExecuteIndirect(pCmdSignature, 1, pBuff, ArgsOffset, nullptr, 0);
113  }
114 
115  void SetID(const Char* ID) { m_ID = ID; }
116  ID3D12GraphicsCommandList *GetCommandList(){return m_pCommandList;}
117 
118  void DiscardDynamicDescriptors(Uint64 FenceValue);
119  DescriptorHeapAllocation AllocateDynamicGPUVisibleDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
120 
121  void InsertUAVBarrier(D3D12ResourceBase& Resource, IDeviceObject &Object, bool FlushImmediate = false);
122 
123  void SetPipelineState( ID3D12PipelineState* pPSO )
124  {
125  if (pPSO != m_pCurPipelineState)
126  {
127  m_pCommandList->SetPipelineState(m_pCurPipelineState = pPSO);
128  }
129  }
130 
131 protected:
132  void TransitionResource(D3D12ResourceBase& Resource, IDeviceObject &Object, D3D12_RESOURCE_STATES NewState, bool FlushImmediate);
133  void InsertAliasBarrier(D3D12ResourceBase& Before, D3D12ResourceBase& After, IDeviceObject &BeforeObj, IDeviceObject &AfterObj, bool FlushImmediate = false);
134 
135  CComPtr<ID3D12GraphicsCommandList> m_pCommandList;
136  CComPtr<ID3D12CommandAllocator> m_pCurrentAllocator;
137 
138  ID3D12PipelineState* m_pCurPipelineState = nullptr;
139  ID3D12RootSignature* m_pCurGraphicsRootSignature = nullptr;
140  ID3D12RootSignature* m_pCurComputeRootSignature = nullptr;
141 
142  static constexpr int MaxPendingBarriers = 16;
143  std::vector<D3D12_RESOURCE_BARRIER, STDAllocatorRawMem<D3D12_RESOURCE_BARRIER> > m_PendingResourceBarriers;
144  // We must make sure that all referenced objects are alive until barriers are executed
145  // Keeping reference to ID3D12Resource is not sufficient!
146  // TextureD3D12Impl::~TextureD3D12Impl() and BufferD3D12Impl::~BufferD3D12Impl()
147  // are responsible for putting the D3D12 resource in the release queue
148  std::vector< RefCntAutoPtr<IDeviceObject>, STDAllocatorRawMem<RefCntAutoPtr<IDeviceObject>> > m_PendingBarrierObjects;
149 
150  ShaderDescriptorHeaps m_BoundDescriptorHeaps;
151 
152  // Every context must use its own allocator that maintains individual list of retired descriptor heaps to
153  // avoid interference with other command contexts
154  // The heaps can only be discarded after the command list is submitted for execution
155  DynamicSuballocationsManager m_DynamicGPUDescriptorAllocator[2];
156 
157  String m_ID;
158 
159  D3D12_PRIMITIVE_TOPOLOGY m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
160 };
161 
162 
163 class GraphicsContext : public CommandContext
164 {
165 public:
166  void ClearRenderTarget( ITextureViewD3D12 *pRTV, const float *Color );
167  void ClearDepthStencil( ITextureViewD3D12 *pDSV, D3D12_CLEAR_FLAGS ClearFlags, float Depth, UINT8 Stencil );
168 
169  void SetRootSignature( ID3D12RootSignature *pRootSig )
170  {
171  if (pRootSig != m_pCurGraphicsRootSignature)
172  {
173  m_pCommandList->SetGraphicsRootSignature(m_pCurGraphicsRootSignature = pRootSig);
174  }
175  }
176 
177  void SetRenderTargets( UINT NumRTVs, ITextureViewD3D12** ppRTVs, ITextureViewD3D12* pDSV );
178 
179  void SetViewports( UINT NumVPs, const D3D12_VIEWPORT* pVPs )
180  {
181  m_pCommandList->RSSetViewports(NumVPs, pVPs);
182  }
183 
184  void SetScissorRects( UINT NumRects, const D3D12_RECT* pRects )
185  {
186  m_pCommandList->RSSetScissorRects(NumRects, pRects);
187  }
188 
189  void SetStencilRef( UINT StencilRef )
190  {
191  m_pCommandList->OMSetStencilRef( StencilRef );
192  }
193 
194  void SetBlendFactor( const float* BlendFactor )
195  {
196  m_pCommandList->OMSetBlendFactor( BlendFactor );
197  }
198 
199  void SetPrimitiveTopology( D3D12_PRIMITIVE_TOPOLOGY Topology )
200  {
201  if(m_PrimitiveTopology != Topology)
202  {
203  m_PrimitiveTopology = Topology;
204  m_pCommandList->IASetPrimitiveTopology(Topology);
205  }
206  }
207 
208  void SetConstants( UINT RootIndex, UINT NumConstants, const void* pConstants )
209  {
210  m_pCommandList->SetGraphicsRoot32BitConstants( RootIndex, NumConstants, pConstants, 0 );
211  }
212 
213  void SetConstants( UINT RootIndex, DWParam X )
214  {
215  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
216  }
217 
218  void SetConstants( UINT RootIndex, DWParam X, DWParam Y )
219  {
220  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
221  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );
222  }
223 
224  void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z )
225  {
226  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
227  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );
228  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Z.Uint, 2 );
229  }
230 
231  void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W )
232  {
233  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, X.Uint, 0 );
234  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Y.Uint, 1 );
235  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, Z.Uint, 2 );
236  m_pCommandList->SetGraphicsRoot32BitConstant( RootIndex, W.Uint, 3 );
237  }
238 
239  void SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV )
240  {
241  m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV);
242  }
243 
244  void SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle )
245  {
246  m_pCommandList->SetGraphicsRootDescriptorTable( RootIndex, FirstHandle );
247  }
248 
249  void SetIndexBuffer( const D3D12_INDEX_BUFFER_VIEW& IBView )
250  {
251  m_pCommandList->IASetIndexBuffer(&IBView);
252  }
253 
254  void SetVertexBuffers( UINT StartSlot, UINT Count, const D3D12_VERTEX_BUFFER_VIEW VBViews[] )
255  {
256  m_pCommandList->IASetVertexBuffers(StartSlot, Count, VBViews);
257  }
258 
259  void Draw(UINT VertexCountPerInstance, UINT InstanceCount,
260  UINT StartVertexLocation, UINT StartInstanceLocation)
261  {
262  FlushResourceBarriers();
263  m_pCommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);
264  }
265 
266  void DrawIndexed(UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation,
267  INT BaseVertexLocation, UINT StartInstanceLocation)
268  {
269  FlushResourceBarriers();
270  m_pCommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);
271  }
272 };
273 
274 class ComputeContext : public CommandContext
275 {
276 public:
277 
278  void SetRootSignature( ID3D12RootSignature *pRootSig )
279  {
280  if (pRootSig != m_pCurComputeRootSignature)
281  {
282  m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig);
283  }
284  }
285 
286  void SetConstants( UINT RootIndex, UINT NumConstants, const void* pConstants )
287  {
288  m_pCommandList->SetComputeRoot32BitConstants( RootIndex, NumConstants, pConstants, 0 );
289  }
290 
291  void SetConstants( UINT RootIndex, DWParam X )
292  {
293  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
294  }
295 
296  void SetConstants( UINT RootIndex, DWParam X, DWParam Y )
297  {
298  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
299  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Y.Uint, 1 );
300  }
301 
302  void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z )
303  {
304  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
305  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Y.Uint, 1 );
306  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Z.Uint, 2 );
307  }
308 
309  void SetConstants( UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W )
310  {
311  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, X.Uint, 0 );
312  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Y.Uint, 1 );
313  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, Z.Uint, 2 );
314  m_pCommandList->SetComputeRoot32BitConstant( RootIndex, W.Uint, 3 );
315  }
316 
317 
318  void SetConstantBuffer( UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV )
319  {
320  m_pCommandList->SetComputeRootConstantBufferView(RootIndex, CBV);
321  }
322 
323  void SetDescriptorTable( UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle )
324  {
325  m_pCommandList->SetComputeRootDescriptorTable( RootIndex, FirstHandle );
326  }
327 
328  void Dispatch( size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1 )
329  {
330  FlushResourceBarriers();
331  m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ);
332  }
333 };
334 
335 inline GraphicsContext& CommandContext::AsGraphicsContext()
336 {
337  return static_cast<GraphicsContext&>(*this);
338 }
339 
340 inline ComputeContext& CommandContext::AsComputeContext()
341 {
342  return static_cast<ComputeContext&>(*this);
343 }
344 
345 inline void CommandContext::SetDescriptorHeaps( ShaderDescriptorHeaps& Heaps )
346 {
347 #ifdef _DEBUG
348  VERIFY(Heaps.pSrvCbvUavHeap != nullptr || Heaps.pSamplerHeap != nullptr, "At least one heap is expected to be set");
349  VERIFY(Heaps.pSrvCbvUavHeap == nullptr || Heaps.pSrvCbvUavHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, "Invalid heap type provided in pSrvCbvUavHeap");
350  VERIFY(Heaps.pSamplerHeap == nullptr || Heaps.pSamplerHeap->GetDesc().Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type provided in pSamplerHeap");
351 #endif
352 
353  if (!(Heaps == m_BoundDescriptorHeaps))
354  {
355  m_BoundDescriptorHeaps = Heaps;
356 
357  ID3D12DescriptorHeap **ppHeaps = reinterpret_cast<ID3D12DescriptorHeap**>(&Heaps);
358  UINT NumHeaps = (ppHeaps[0] != nullptr ? 1 : 0) + (ppHeaps[1] != nullptr ? 1 : 0);
359  if(ppHeaps[0] == nullptr)
360  ++ppHeaps;
361 
362  m_pCommandList->SetDescriptorHeaps(NumHeaps, ppHeaps);
363  }
364 }
365 
366 }
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34