1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "DeviceResourceSet_D3D12.h"
4 #include "DeviceCommandListCommon_D3D12.h"
5 #include "DevicePSO_D3D12.h"
7 #if CRY_PLATFORM_WINDOWS
8 # ifdef ENABLE_PROFILING_CODE
11 # include <WinPixEventRuntime/pix3.h>
14 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
15 bool CDeviceTimestampGroup::s_reservedGroups
[MAX_FRAMES_IN_FLIGHT
] = { false, false, false, false };
17 CDeviceTimestampGroup::CDeviceTimestampGroup()
19 , m_groupIndex(0xFFFFFFFF)
28 CDeviceTimestampGroup::~CDeviceTimestampGroup()
30 s_reservedGroups
[m_groupIndex
] = false;
33 void CDeviceTimestampGroup::Init()
35 GetDeviceObjectFactory().CreateFence(m_fence
);
38 m_groupIndex
= 0xFFFFFFFF;
39 for (uint32 i
= 0; i
< CRY_ARRAY_COUNT(s_reservedGroups
); i
++)
41 if (s_reservedGroups
[i
] == false)
43 s_reservedGroups
[i
] = true;
49 assert(m_groupIndex
< 0xFFFFFFFF);
52 void CDeviceTimestampGroup::BeginMeasurement()
60 void CDeviceTimestampGroup::EndMeasurement()
62 auto* pDX12Device
= GetDeviceObjectFactory().GetDX12Device();
63 auto* pDX12Scheduler
= GetDeviceObjectFactory().GetDX12Scheduler();
64 auto* pDX12CmdList
= GetDeviceObjectFactory().GetCoreCommandList().GetDX12CommandList();
66 pDX12Device
->IssueTimestampResolve(pDX12CmdList
, m_groupIndex
* kMaxTimestamps
, m_numTimestamps
);
67 m_fence
= (DeviceFenceHandle
)pDX12Scheduler
->InsertFence();
72 uint32
CDeviceTimestampGroup::IssueTimestamp(CDeviceCommandList
* pCommandList
)
74 // Passing a nullptr means we want to use the current core command-list
75 auto* pDX12Device
= GetDeviceObjectFactory().GetDX12Device();
76 auto* pDX12CmdList
= (pCommandList
? *pCommandList
: GetDeviceObjectFactory().GetCoreCommandList()).GetDX12CommandList();
78 assert(m_numTimestamps
< kMaxTimestamps
);
80 const uint32 timestampIndex
= m_groupIndex
* kMaxTimestamps
+ m_numTimestamps
;
81 pDX12Device
->InsertTimestamp(pDX12CmdList
, timestampIndex
);
83 if((m_numTimestamps
+ 1) < kMaxTimestamps
)
88 return timestampIndex
;
91 bool CDeviceTimestampGroup::ResolveTimestamps()
95 if (m_measured
|| m_numTimestamps
== 0)
98 auto* pDX12Device
= GetDeviceObjectFactory().GetDX12Device();
99 auto* pDX12Scheduler
= GetDeviceObjectFactory().GetDX12Scheduler();
101 if (pDX12Scheduler
->TestForFence(m_fence
) != S_OK
)
104 m_frequency
= pDX12Device
->GetTimestampFrequency();
105 pDX12Device
->QueryTimestamps(m_groupIndex
* kMaxTimestamps
, m_numTimestamps
, &m_timeValues
[0]);
107 return m_measured
= true;
110 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111 void CDeviceCommandListImpl::SetProfilerMarker(const char* label
)
113 #if defined(ENABLE_FRAME_PROFILER_LABELS)
114 PIXSetMarker(GetDX12CommandList()->GetD3D12CommandList(), 0, label
);
118 void CDeviceCommandListImpl::BeginProfilerEvent(const char* label
)
120 #if defined(ENABLE_FRAME_PROFILER_LABELS)
121 m_profilerEventStack
.push_back(label
);
122 PIXBeginEvent(GetDX12CommandList()->GetD3D12CommandList(), 0, label
);
126 void CDeviceCommandListImpl::EndProfilerEvent(const char* label
)
128 #if defined(ENABLE_FRAME_PROFILER_LABELS)
129 PIXEndEvent(GetDX12CommandList()->GetD3D12CommandList());
130 m_profilerEventStack
.pop_back();
134 void CDeviceCommandListImpl::ClearStateImpl(bool bOutputMergerOnly
) const
138 void CDeviceCommandListImpl::CeaseCommandListEvent(int nPoolId
)
140 if (nPoolId
!= CMDQUEUE_GRAPHICS
)
143 #if defined(USE_CRY_ASSERT) || defined(ENABLE_FRAME_PROFILER_LABELS)
144 auto* pCommandList
= GetScheduler()->GetCommandList(nPoolId
);
147 CRY_ASSERT(m_sharedState
.pCommandList
== pCommandList
|| m_sharedState
.pCommandList
== nullptr);
148 m_sharedState
.pCommandList
= nullptr;
150 #if defined(ENABLE_FRAME_PROFILER_LABELS)
151 for (size_t num
= m_profilerEventStack
.size(), i
= 0; i
< num
; ++i
)
153 PIXEndEvent(pCommandList
->GetD3D12CommandList());
157 reinterpret_cast<CDeviceCommandList
*>(this)->Reset();
160 void CDeviceCommandListImpl::ResumeCommandListEvent(int nPoolId
)
162 if (nPoolId
!= CMDQUEUE_GRAPHICS
)
165 auto* pCommandList
= GetScheduler()->GetCommandList(nPoolId
);
166 CRY_ASSERT(m_sharedState
.pCommandList
== nullptr);
167 m_sharedState
.pCommandList
= pCommandList
;
169 #if defined(ENABLE_FRAME_PROFILER_LABELS)
170 for (auto pEventLabel
: m_profilerEventStack
)
172 PIXBeginEvent(pCommandList
->GetD3D12CommandList(), 0, pEventLabel
);
177 void CDeviceCommandListImpl::ResetImpl()
179 m_graphicsState
.custom
.primitiveTopology
= D3D_PRIMITIVE_TOPOLOGY_UNDEFINED
;
182 void CDeviceCommandListImpl::LockToThreadImpl()
184 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
186 pCommandListDX12
->Begin();
187 pCommandListDX12
->SetResourceAndSamplerStateHeaps();
190 void CDeviceCommandListImpl::CloseImpl()
192 FUNCTION_PROFILER_RENDERER();
193 GetDX12CommandList()->End();
196 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
197 void CDeviceGraphicsCommandInterfaceImpl::PrepareUAVsForUseImpl(uint32 viewCount
, CDeviceBuffer
** pViews
, bool bCompute
) const
199 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
201 for (int v
= 0; v
< viewCount
; ++v
)
203 // TODO: ResourceViewHandles[]
204 const NCryDX12::CView
& View
= GET_DX12_UNORDERED_VIEW(pViews
[v
], EDefaultResourceViews::UnorderedAccess
)->GetDX12View();
205 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
206 const D3D12_RESOURCE_STATES desiredState
=
208 ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS
209 : D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
;
211 if (Resource
.InitHasBeenDeferred())
213 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
216 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
218 pCommandListDX12
->PrepareResourceUAVUsage(Resource
, View
, desiredState
);
222 void CDeviceGraphicsCommandInterfaceImpl::PrepareRenderPassForUseImpl(CDeviceRenderPass
& renderPass
) const
224 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
226 if (renderPass
.m_pDepthStencilView
)
228 const NCryDX12::CView
& View
= renderPass
.m_pDepthStencilView
->GetDX12View();
229 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
231 D3D11_DEPTH_STENCIL_VIEW_DESC Desc
; renderPass
.m_pDepthStencilView
->GetDesc(&Desc
);
232 const D3D12_RESOURCE_STATES desiredState
= Desc
.Flags
& D3D11_DSV_READ_ONLY_DEPTH
? D3D12_RESOURCE_STATE_DEPTH_READ
: D3D12_RESOURCE_STATE_DEPTH_WRITE
;
234 pCommandListDX12
->PrepareResourceDSVUsage(Resource
, View
, desiredState
);
237 // Get current render target views
238 for (int i
= 0; i
< renderPass
.m_RenderTargetCount
; ++i
)
240 const NCryDX12::CView
& View
= renderPass
.m_RenderTargetViews
[i
]->GetDX12View();
241 NCryDX12::CResource
& Resource
= View
.GetDX12Resource(); Resource
.VerifyBackBuffer(true);
243 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_RENDER_TARGET
;
245 pCommandListDX12
->PrepareResourceRTVUsage(Resource
, View
, desiredState
);
249 void CDeviceGraphicsCommandInterfaceImpl::PrepareResourceForUseImpl(uint32 bindSlot
, CTexture
* pTexture
, const ResourceViewHandle TextureView
, ::EShaderStage srvUsage
) const
251 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
253 CCryDX12ShaderResourceView
* it
= GET_DX12_SHADER_VIEW(pTexture
->GetDevTexture(), TextureView
);
255 const NCryDX12::CView
& View
= it
->GetDX12View();
256 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
257 const D3D12_RESOURCE_STATES desiredState
=
258 (srvUsage
& EShaderStage_Pixel
? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
: D3D12_RESOURCE_STATE_COMMON
) |
259 (srvUsage
& ~EShaderStage_Pixel
? D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
: D3D12_RESOURCE_STATE_COMMON
);
261 if (Resource
.InitHasBeenDeferred())
263 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
266 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && !(Resource
.GetTargetState() & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
268 pCommandListDX12
->PrepareResourceSRVUsage(Resource
, View
, desiredState
);
272 void CDeviceGraphicsCommandInterfaceImpl::PrepareResourcesForUseImpl(uint32 bindSlot
, CDeviceResourceSet
* pResources
) const
274 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
275 CDeviceResourceSet_DX12
* pResourcesDX12
= reinterpret_cast<CDeviceResourceSet_DX12
*>(pResources
);
277 for (auto& it
: pResourcesDX12
->m_ConstantBuffersInUse
)
279 NCryDX12::CResource
& Resource
= it
.second
->GetDX12Resource();
280 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
;
282 if (Resource
.InitHasBeenDeferred())
284 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
);
287 pCommandListDX12
->PrepareResourceCBVUsage(Resource
, desiredState
);
290 for (auto& it
: pResourcesDX12
->m_ShaderResourceViewsInUse
)
292 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
293 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
295 const D3D12_RESOURCE_STATES desiredState
=
296 (it
.first
.stages
& EShaderStage_Pixel
? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
: D3D12_RESOURCE_STATE_COMMON
) |
297 (it
.first
.stages
& ~EShaderStage_Pixel
? D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
: D3D12_RESOURCE_STATE_COMMON
);
299 if (Resource
.InitHasBeenDeferred())
301 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
304 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && !(Resource
.GetTargetState() & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
306 pCommandListDX12
->PrepareResourceSRVUsage(Resource
, View
, desiredState
);
309 for (auto& it
: pResourcesDX12
->m_UnorderedAccessViewsInUse
)
311 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
312 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
313 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_UNORDERED_ACCESS
;
315 if (Resource
.InitHasBeenDeferred())
317 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
320 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
322 pCommandListDX12
->PrepareResourceUAVUsage(Resource
, View
, desiredState
);
326 void CDeviceGraphicsCommandInterfaceImpl::PrepareInlineConstantBufferForUseImpl(uint32 bindSlot
, CConstantBuffer
* pBuffer
, EConstantBufferShaderSlot shaderSlot
, EHWShaderClass shaderClass
) const
328 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
330 NCryDX12::CResource
& Resource
= GET_DX12_CONSTANTBUFFER_RESOURCE(pBuffer
)->GetDX12Resource();
331 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
;
333 if (Resource
.InitHasBeenDeferred())
335 Resource
.InitDeferred(pCommandListDX12
, desiredState
);
338 pCommandListDX12
->PrepareResourceCBVUsage(Resource
, desiredState
);
341 void CDeviceGraphicsCommandInterfaceImpl::PrepareInlineConstantBufferForUseImpl(uint32 bindSlot
, CConstantBuffer
* pBuffer
, EConstantBufferShaderSlot shaderSlot
, ::EShaderStage shaderStages
) const
343 PrepareInlineConstantBufferForUseImpl(bindSlot
, pBuffer
, shaderSlot
, eHWSC_NumGfx
);
346 void CDeviceGraphicsCommandInterfaceImpl::PrepareInlineShaderResourceForUseImpl(uint32 bindSlot
, CDeviceBuffer
* pBuffer
, EShaderResourceShaderSlot shaderSlot
, EHWShaderClass shaderClass
) const
348 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
350 NCryDX12::CResource
& Resource
= GET_DX12_RAWBUFFER_RESOURCE(pBuffer
)->GetDX12Resource();
351 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
;
353 if (Resource
.InitHasBeenDeferred())
355 Resource
.InitDeferred(pCommandListDX12
, desiredState
);
358 pCommandListDX12
->PrepareResourceSRVUsage(Resource
, desiredState
);
361 void CDeviceGraphicsCommandInterfaceImpl::PrepareInlineShaderResourceForUseImpl(uint32 bindSlot
, CDeviceBuffer
* pBuffer
, EShaderResourceShaderSlot shaderSlot
, ::EShaderStage shaderStages
) const
363 PrepareInlineShaderResourceForUseImpl(bindSlot
, pBuffer
, shaderSlot
, eHWSC_NumGfx
);
366 void CDeviceGraphicsCommandInterfaceImpl::PrepareVertexBuffersForUseImpl(uint32 numStreams
, uint32 lastStreamSlot
, const CDeviceInputStream
* vertexStreams
) const
368 if (m_graphicsState
.vertexStreams
!= vertexStreams
)
370 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
372 for (uint32 s
= 0; s
< numStreams
; ++s
)
374 const CDeviceInputStream
& vertexStream
= vertexStreams
[s
];
376 CRY_ASSERT(vertexStream
.hStream
!= ~0u);
378 // TODO: try not to call GetD3D() here, overhead: 1 call (and no inlinening) + 1 look-up + 2 accesses + branch
379 buffer_size_t offset
;
380 auto pBuffer
= reinterpret_cast<CCryDX12Buffer
*>(gcpRendD3D
.m_DevBufMan
.GetD3D(vertexStream
.hStream
, &offset
));
381 NCryDX12::CResource
& Resource
= pBuffer
->GetDX12Resource();
382 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
;
384 if (Resource
.InitHasBeenDeferred())
386 Resource
.InitDeferred(pCommandListDX12
, desiredState
);
389 pCommandListDX12
->PrepareResourceVBVUsage(Resource
, desiredState
);
395 void CDeviceGraphicsCommandInterfaceImpl::PrepareIndexBufferForUseImpl(const CDeviceInputStream
* indexStream
) const
397 if (m_graphicsState
.indexStream
!= indexStream
)
399 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
401 CRY_ASSERT(indexStream
->hStream
!= ~0u);
403 // TODO: try not to call GetD3D() here, overhead: 1 call (and no inlinening) + 1 look-up + 2 accesses + branch
404 buffer_size_t offset
;
405 auto pBuffer
= reinterpret_cast<CCryDX12Buffer
*>(gcpRendD3D
.m_DevBufMan
.GetD3D(indexStream
->hStream
, &offset
));
406 NCryDX12::CResource
& Resource
= pBuffer
->GetDX12Resource();
407 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_INDEX_BUFFER
;
409 if (Resource
.InitHasBeenDeferred())
411 Resource
.InitDeferred(pCommandListDX12
, desiredState
);
414 pCommandListDX12
->PrepareResourceIBVUsage(Resource
, desiredState
);
419 void CDeviceGraphicsCommandInterfaceImpl::BeginResourceTransitionsImpl(uint32 numTextures
, CTexture
** pTextures
, EResourceTransitionType type
)
421 if (!CRenderer::CV_r_D3D12EarlyResourceBarriers
)
424 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
426 uint32 numBarriers
= 0;
427 for (uint32 i
= 0; i
< numTextures
; i
++)
429 CCryDX12Resource
<ID3D11ResourceToImplement
>* pResource
= nullptr;
430 if (pTextures
[i
] && pTextures
[i
]->GetDevTexture())
432 pResource
= DX12_EXTRACT_RESOURCE(pTextures
[i
]->GetDevTexture()->GetBaseTexture());
435 if (pResource
!= nullptr)
437 NCryDX12::CResource
& resource
= pResource
->GetDX12Resource();
438 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
;
440 if (resource
.NeedsTransitionBarrier(pCommandListDX12
, desiredState
))
442 pCommandListDX12
->MaxResourceFenceValue(resource
, CMDTYPE_WRITE
);
443 pCommandListDX12
->BeginResourceStateTransition(resource
, desiredState
);
444 pCommandListDX12
->SetResourceFenceValue(resource
, CMDTYPE_READ
);
452 pCommandListDX12
->PendingResourceBarriers();
454 if (CRenderer::CV_r_D3D12EarlyResourceBarriers
> 1)
455 gcpRendD3D
->GetDeviceContext_Unsynchronized().Flush();
459 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
460 void CDeviceGraphicsCommandInterfaceImpl::BeginRenderPassImpl(const CDeviceRenderPass
& renderPass
, const D3DRectangle
& renderArea
)
462 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
464 const NCryDX12::CView
* pDSV
= nullptr;
465 const NCryDX12::CView
* pRTV
[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT
] = { nullptr };
467 // Get current depth stencil views
468 if (renderPass
.m_pDepthStencilView
)
470 const NCryDX12::CView
& View
= renderPass
.m_pDepthStencilView
->GetDX12View();
474 D3D11_DEPTH_STENCIL_VIEW_DESC Desc
; renderPass
.m_pDepthStencilView
->GetDesc(&Desc
);
475 const D3D12_RESOURCE_STATES desiredState
= Desc
.Flags
& D3D11_DSV_READ_ONLY_DEPTH
? D3D12_RESOURCE_STATE_DEPTH_READ
: D3D12_RESOURCE_STATE_DEPTH_WRITE
;
477 assert(!View
.GetDX12Resource().NeedsTransitionBarrier(pCommandListDX12
, View
, desiredState
));
480 // Get current render target views
481 for (int i
= 0; i
< renderPass
.m_RenderTargetCount
; ++i
)
483 const NCryDX12::CView
& View
= renderPass
.m_RenderTargetViews
[i
]->GetDX12View();
484 NCryDX12::CResource
& Resource
= View
.GetDX12Resource(); Resource
.VerifyBackBuffer(true);
488 assert(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, *pRTV
[i
], D3D12_RESOURCE_STATE_RENDER_TARGET
));
491 pCommandListDX12
->BindAndSetOutputViews(renderPass
.m_RenderTargetCount
, pRTV
, pDSV
);
494 void CDeviceGraphicsCommandInterfaceImpl::SetViewportsImpl(uint32 vpCount
, const D3DViewPort
* pViewports
)
496 // D3D11_VIEWPORT := D3D12_VIEWPORT
497 GetDX12CommandList()->SetViewports(vpCount
, (D3D12_VIEWPORT
*)pViewports
);
500 void CDeviceGraphicsCommandInterfaceImpl::SetScissorRectsImpl(uint32 rcCount
, const D3DRectangle
* pRects
)
502 // D3D11_RECT := D3D12_RECT
503 GetDX12CommandList()->SetScissorRects(rcCount
, (D3D12_RECT
*)pRects
);
506 void CDeviceGraphicsCommandInterfaceImpl::SetPipelineStateImpl(const CDeviceGraphicsPSO
* devicePSO
)
508 auto pCommandListDX12
= GetDX12CommandList();
509 const CDeviceGraphicsPSO_DX12
* pDevicePSO
= reinterpret_cast<const CDeviceGraphicsPSO_DX12
*>(devicePSO
);
511 pCommandListDX12
->SetPSO(pDevicePSO
->GetGraphicsPSO());
512 m_computeState
.pPipelineState
= nullptr; // on dx12 pipeline state is shared between graphics and compute
514 D3D12_PRIMITIVE_TOPOLOGY psoPrimitiveTopology
= pDevicePSO
->GetPrimitiveTopology();
515 if (m_graphicsState
.custom
.primitiveTopology
.Set(psoPrimitiveTopology
))
517 #if defined(ENABLE_PROFILING_CODE)
518 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumTopologySets
);
521 pCommandListDX12
->SetPrimitiveTopology(psoPrimitiveTopology
);
525 void CDeviceGraphicsCommandInterfaceImpl::SetResourceLayoutImpl(const CDeviceResourceLayout
* resourceLayout
)
527 const CDeviceResourceLayout_DX12
* pResourceLayoutDX12
= reinterpret_cast<const CDeviceResourceLayout_DX12
*>(resourceLayout
);
528 GetDX12CommandList()->SetGraphicsRootSignature(pResourceLayoutDX12
->GetRootSignature());
531 void CDeviceGraphicsCommandInterfaceImpl::SetVertexBuffersImpl(uint32 numStreams
, uint32 lastStreamSlot
, const CDeviceInputStream
* vertexStreams
)
533 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
534 pCommandListDX12
->ClearVertexBufferHeap(lastStreamSlot
+ 1);
536 for (uint32 s
= 0; s
< numStreams
; ++s
)
538 const CDeviceInputStream
& vertexStream
= vertexStreams
[s
];
540 CRY_ASSERT(vertexStream
.hStream
!= ~0u);
542 // TODO: try not to call GetD3D() here, overhead: 1 call (and no inlinening) + 1 look-up + 2 accesses + branch
543 buffer_size_t offset
;
544 auto* pBuffer
= reinterpret_cast<CCryDX12Buffer
*>(gcpRendD3D
.m_DevBufMan
.GetD3D(vertexStream
.hStream
, &offset
));
546 DX12_ASSERT(!pBuffer
->GetDX12Resource().InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", pBuffer
->GetDX12Resource().GetName());
547 DX12_ASSERT(!pBuffer
->GetDX12Resource().NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
));
549 #if defined(ENABLE_PROFILING_CODE)
550 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundVertexBuffers
[pBuffer
->GetDX12Resource().IsOffCard()]);
553 pCommandListDX12
->BindVertexBufferView(pBuffer
->GetDX12View(), vertexStream
.nSlot
, TRange
<uint32
>(offset
, offset
), vertexStream
.nStride
);
557 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
558 pCommandListDX12
->SetVertexBufferHeap(lastStreamSlot
+ 1);
561 void CDeviceGraphicsCommandInterfaceImpl::SetIndexBufferImpl(const CDeviceInputStream
* indexStream
)
563 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
565 CRY_ASSERT(indexStream
->hStream
!= ~0u);
567 // TODO: try not to call GetD3D() here, overhead: 1 call (and no inlinening) + 1 look-up + 2 accesses + branch
568 buffer_size_t offset
;
569 auto* pBuffer
= reinterpret_cast<CCryDX12Buffer
*>(gcpRendD3D
.m_DevBufMan
.GetD3D(indexStream
->hStream
, &offset
));
571 DX12_ASSERT(!pBuffer
->GetDX12Resource().InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", pBuffer
->GetDX12Resource().GetName());
572 DX12_ASSERT(!pBuffer
->GetDX12Resource().NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_INDEX_BUFFER
));
574 #if defined(ENABLE_PROFILING_CODE)
575 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundIndexBuffers
[pBuffer
->GetDX12Resource().IsOffCard()]);
578 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
579 #if !defined(SUPPORT_FLEXIBLE_INDEXBUFFER)
580 pCommandListDX12
->BindAndSetIndexBufferView(pBuffer
->GetDX12View(), DXGI_FORMAT_R16_UINT
, offset
);
582 pCommandListDX12
->BindAndSetIndexBufferView(pBuffer
->GetDX12View(), (DXGI_FORMAT
)indexStream
->nStride
, UINT(offset
));
587 void CDeviceGraphicsCommandInterfaceImpl::SetResourcesImpl(uint32 bindSlot
, const CDeviceResourceSet
* pResources
)
589 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
590 const CDeviceResourceSet_DX12
* pResourcesDX12
= reinterpret_cast<const CDeviceResourceSet_DX12
*>(pResources
);
592 for (auto& it
: pResourcesDX12
->m_ConstantBuffersInUse
)
594 NCryDX12::CResource
& Resource
= it
.second
->GetDX12Resource();
596 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
597 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
));
599 #if defined(ENABLE_PROFILING_CODE)
600 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundConstBuffers
[Resource
.IsOffCard()]);
603 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
604 pCommandListDX12
->TrackResourceCBVUsage(Resource
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
);
607 for (auto& it
: pResourcesDX12
->m_ShaderResourceViewsInUse
)
609 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
610 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
611 const D3D12_RESOURCE_STATES desiredState
=
612 (it
.first
.stages
& EShaderStage_Pixel
? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
: D3D12_RESOURCE_STATE_COMMON
) |
613 (it
.first
.stages
& ~EShaderStage_Pixel
? D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
: D3D12_RESOURCE_STATE_COMMON
);
615 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
616 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, View
, desiredState
));
618 #if defined(ENABLE_PROFILING_CODE)
619 const bool bIsBuffer
= Resource
.GetDesc().Dimension
== D3D12_RESOURCE_DIMENSION_BUFFER
;
620 if (bIsBuffer
) CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundUniformBuffers
[Resource
.IsOffCard()]);
621 else CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundUniformTextures
[Resource
.IsOffCard()]);
624 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
625 pCommandListDX12
->TrackResourcePRVUsage(Resource
, View
, desiredState
);
628 for (auto& it
: pResourcesDX12
->m_UnorderedAccessViewsInUse
)
630 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
631 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
633 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
634 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
));
636 #if defined(ENABLE_PROFILING_CODE)
637 const bool bIsBuffer
= Resource
.GetDesc().Dimension
== D3D12_RESOURCE_DIMENSION_BUFFER
;
638 if (bIsBuffer
) CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundUniformBuffers
[Resource
.IsOffCard()]);
639 else CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundUniformTextures
[Resource
.IsOffCard()]);
642 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
643 pCommandListDX12
->TrackResourceUAVUsage(Resource
, View
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
646 const CDescriptorBlock
& descriptorBlock
= pResourcesDX12
->GetDescriptorBlock();
647 pCommandListDX12
->SetGraphicsDescriptorTable(bindSlot
, descriptorBlock
.GetHandleOffsetGPU(0));
652 void CDeviceGraphicsCommandInterfaceImpl::SetInlineConstantBufferImpl(uint32 bindSlot
, const CConstantBuffer
* pBuffer
, EConstantBufferShaderSlot shaderSlot
, ::EShaderStage shaderStages
)
654 SetInlineConstantBufferImpl(bindSlot
, pBuffer
, shaderSlot
, eHWSC_Num
);
657 void CDeviceGraphicsCommandInterfaceImpl::SetInlineConstantBufferImpl(uint32 bindSlot
, const CConstantBuffer
* pBuffer
, EConstantBufferShaderSlot shaderSlot
, EHWShaderClass shaderClass
)
659 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
661 const NCryDX12::CView
& View
= GET_DX12_CONSTANTBUFFER_RESOURCE(pBuffer
)->GetDX12View();
662 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
664 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
665 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
));
667 #if defined(ENABLE_PROFILING_CODE)
668 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundInlineBuffers
[Resource
.IsOffCard()]);
671 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
672 pCommandListDX12
->TrackResourceCBVUsage(Resource
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
);
674 D3D12_GPU_VIRTUAL_ADDRESS gpuAddress
= View
.GetCBVDesc().BufferLocation
+ pBuffer
->m_offset
;
675 pCommandListDX12
->SetGraphicsConstantBufferView(bindSlot
, gpuAddress
);
678 void CDeviceGraphicsCommandInterfaceImpl::SetInlineShaderResourceImpl(uint32 bindSlot
, const CDeviceBuffer
* pBuffer
, EShaderResourceShaderSlot shaderSlot
, ::EShaderStage shaderStages
, ResourceViewHandle resourceViewID
)
680 SetInlineShaderResourceImpl(bindSlot
, pBuffer
, shaderSlot
, eHWSC_Num
, resourceViewID
);
683 void CDeviceGraphicsCommandInterfaceImpl::SetInlineShaderResourceImpl(uint32 bindSlot
, const CDeviceBuffer
* pBuffer
, EShaderResourceShaderSlot shaderSlot
, EHWShaderClass shaderClass
, ResourceViewHandle resourceViewID
)
685 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
687 const NCryDX12::CView
& View
= GET_DX12_SHADER_VIEW(pBuffer
, resourceViewID
)->GetDX12View();
688 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
690 assert(!Resource
.InitHasBeenDeferred());
691 assert(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
));
693 #if defined(ENABLE_PROFILING_CODE)
694 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundInlineBuffers
[Resource
.IsOffCard()]);
697 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
698 pCommandListDX12
->TrackResourceSRVUsage(Resource
, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
700 D3D12_GPU_VIRTUAL_ADDRESS gpuAddress
= Resource
.GetGPUVirtualAddress();
701 pCommandListDX12
->SetGraphicsShaderResourceView(bindSlot
, gpuAddress
);
704 void CDeviceGraphicsCommandInterfaceImpl::SetInlineConstantsImpl(uint32 bindSlot
, uint32 constantCount
, float* pConstants
)
706 GetDX12CommandList()->SetGraphics32BitConstants(bindSlot
, constantCount
, pConstants
, 0);
709 void CDeviceGraphicsCommandInterfaceImpl::SetStencilRefImpl(uint8 stencilRefValue
)
711 GetDX12CommandList()->SetStencilRef(stencilRefValue
);
714 void CDeviceGraphicsCommandInterfaceImpl::SetDepthBiasImpl(float constBias
, float slopeBias
, float biasClamp
)
716 CRY_ASSERT_MESSAGE(false, "Depth bias can only be set via PSO on DirectX 12");
719 void CDeviceGraphicsCommandInterfaceImpl::SetDepthBoundsImpl(float fMin
, float fMax
)
721 GetDX12CommandList()->SetDepthBounds(fMin
, fMax
);
724 void CDeviceGraphicsCommandInterfaceImpl::DrawImpl(uint32 VertexCountPerInstance
, uint32 InstanceCount
, uint32 StartVertexLocation
, uint32 StartInstanceLocation
)
726 GetDX12CommandList()->DrawInstanced(VertexCountPerInstance
, InstanceCount
, StartVertexLocation
, StartInstanceLocation
);
729 void CDeviceGraphicsCommandInterfaceImpl::DrawIndexedImpl(uint32 IndexCountPerInstance
, uint32 InstanceCount
, uint32 StartIndexLocation
, int BaseVertexLocation
, uint32 StartInstanceLocation
)
731 GetDX12CommandList()->DrawIndexedInstanced(IndexCountPerInstance
, InstanceCount
, StartIndexLocation
, BaseVertexLocation
, StartInstanceLocation
);
734 void CDeviceGraphicsCommandInterfaceImpl::ClearSurfaceImpl(D3DSurface
* pView
, const FLOAT Color
[4], UINT NumRects
, const D3D11_RECT
* pRects
)
736 const NCryDX12::CView
& View
= reinterpret_cast<CCryDX12RenderTargetView
*>(pView
)->GetDX12View();
737 GetDX12CommandList()->ClearRenderTargetView(View
, Color
, NumRects
, pRects
);
740 void CDeviceGraphicsCommandInterfaceImpl::ClearSurfaceImpl(D3DDepthSurface
* pView
, int clearFlags
, float depth
, uint8 stencil
, uint32 numRects
, const D3D11_RECT
* pRects
)
742 const NCryDX12::CView
& View
= reinterpret_cast<CCryDX12DepthStencilView
*>(pView
)->GetDX12View();
743 GetDX12CommandList()->ClearDepthStencilView(View
, D3D12_CLEAR_FLAGS(clearFlags
), depth
, stencil
, numRects
, pRects
);
746 void CDeviceGraphicsCommandInterfaceImpl::DiscardContentsImpl(D3DResource
* pResource
, uint32 numRects
, const D3D11_RECT
* pRects
)
748 NCryDX12::CResource
& Resource
= reinterpret_cast<CCryDX12Resource
<IEmptyResource
>*>(pResource
)->GetDX12Resource();
749 D3D12_DISCARD_REGION rRegion
= { numRects
, pRects
, 0, Resource
.GetDesc().MipLevels
* Resource
.GetDesc().DepthOrArraySize
};
750 GetDX12CommandList()->DiscardResource(Resource
, &rRegion
);
753 void CDeviceGraphicsCommandInterfaceImpl::DiscardContentsImpl(D3DBaseView
* pView
, uint32 numRects
, const D3D11_RECT
* pRects
)
755 const NCryDX12::CView
& View
= reinterpret_cast<CCryDX12RenderTargetView
*>(pView
)->GetDX12View();
756 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
757 D3D12_DISCARD_REGION rRegion
= { numRects
, pRects
, 0, 0x7FFFFFFF }; // TODO: calculate sub-resources and loop according to the given view
758 GetDX12CommandList()->DiscardResource(Resource
, &rRegion
);
761 void CDeviceGraphicsCommandInterfaceImpl::BeginOcclusionQueryImpl(D3DOcclusionQuery
* pQuery
)
763 CRY_ASSERT(GetDX12CommandList() == GetDeviceObjectFactory().GetCoreCommandList().GetDX12CommandList());
764 gcpRendD3D
->GetDeviceContext().GetRealDeviceContext()->Begin(pQuery
);
767 void CDeviceGraphicsCommandInterfaceImpl::EndOcclusionQueryImpl(D3DOcclusionQuery
* pQuery
)
769 CRY_ASSERT(GetDX12CommandList() == GetDeviceObjectFactory().GetCoreCommandList().GetDX12CommandList());
770 gcpRendD3D
->GetDeviceContext().GetRealDeviceContext()->End(pQuery
);
773 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
774 void CDeviceComputeCommandInterfaceImpl::PrepareUAVsForUseImpl(uint32 viewCount
, CDeviceBuffer
** pViews
) const
776 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
778 for (int v
= 0; v
< viewCount
; ++v
)
780 // TODO: ResourceViewHandles[]
781 const NCryDX12::CView
& View
= GET_DX12_UNORDERED_VIEW(pViews
[v
], EDefaultResourceViews::UnorderedAccess
)->GetDX12View();
782 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
783 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_UNORDERED_ACCESS
;
785 if (Resource
.InitHasBeenDeferred())
787 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
790 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
792 pCommandListDX12
->PrepareResourceUAVUsage(Resource
, View
, desiredState
);
796 void CDeviceComputeCommandInterfaceImpl::PrepareResourcesForUseImpl(uint32 bindSlot
, CDeviceResourceSet
* pResources
) const
798 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
799 CDeviceResourceSet_DX12
* pResourcesDX12
= reinterpret_cast<CDeviceResourceSet_DX12
*>(pResources
);
801 for (auto& it
: pResourcesDX12
->m_ConstantBuffersInUse
)
803 NCryDX12::CResource
& Resource
= it
.second
->GetDX12Resource();
804 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
;
806 if (Resource
.InitHasBeenDeferred())
808 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
);
811 pCommandListDX12
->PrepareResourceCBVUsage(Resource
, desiredState
);
814 for (auto& it
: pResourcesDX12
->m_ShaderResourceViewsInUse
)
816 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
817 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
818 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
;
820 if (Resource
.InitHasBeenDeferred())
822 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
825 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
827 pCommandListDX12
->PrepareResourceCRVUsage(Resource
, View
, desiredState
);
830 for (auto& it
: pResourcesDX12
->m_UnorderedAccessViewsInUse
)
832 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
833 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
834 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_UNORDERED_ACCESS
;
836 if (Resource
.InitHasBeenDeferred())
838 Resource
.InitDeferred(pCommandListDX12
, desiredState
| D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
841 DX12_ASSERT(!((pCommandListDX12
->GetD3D12ListType() != D3D12_COMMAND_LIST_TYPE_DIRECT
) && (Resource
.GetTargetState() & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
) && (!Resource
.IsOffCard())));
843 pCommandListDX12
->PrepareResourceUAVUsage(Resource
, View
, desiredState
);
847 void CDeviceComputeCommandInterfaceImpl::PrepareInlineConstantBufferForUseImpl(uint32 bindSlot
, CConstantBuffer
* pBuffer
, EConstantBufferShaderSlot shaderSlot
) const
849 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
851 NCryDX12::CResource
& Resource
= GET_DX12_CONSTANTBUFFER_RESOURCE(pBuffer
)->GetDX12Resource();
852 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
;
854 pCommandListDX12
->PrepareResourceCBVUsage(Resource
, desiredState
);
857 void CDeviceComputeCommandInterfaceImpl::PrepareInlineShaderResourceForUseImpl(uint32 bindSlot
, CDeviceBuffer
* pBuffer
, EShaderResourceShaderSlot shaderSlot
) const
859 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
861 NCryDX12::CResource
& Resource
= GET_DX12_RAWBUFFER_RESOURCE(pBuffer
)->GetDX12Resource();
862 const D3D12_RESOURCE_STATES desiredState
= D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
;
864 pCommandListDX12
->PrepareResourceSRVUsage(Resource
, desiredState
);
867 void CDeviceComputeCommandInterfaceImpl::SetPipelineStateImpl(const CDeviceComputePSO
* pDevicePSO
)
869 const CDeviceComputePSO_DX12
* pDevicePsoDX12
= reinterpret_cast<const CDeviceComputePSO_DX12
*>(pDevicePSO
);
870 GetDX12CommandList()->SetPSO(pDevicePsoDX12
->GetComputePSO());
871 m_graphicsState
.pPipelineState
= nullptr; // on dx12 pipeline state is shared between graphics and compute
874 void CDeviceComputeCommandInterfaceImpl::SetResourceLayoutImpl(const CDeviceResourceLayout
* pResourceLayout
)
876 const CDeviceResourceLayout_DX12
* pResourceLayoutDX12
= reinterpret_cast<const CDeviceResourceLayout_DX12
*>(pResourceLayout
);
877 GetDX12CommandList()->SetComputeRootSignature(pResourceLayoutDX12
->GetRootSignature());
880 void CDeviceComputeCommandInterfaceImpl::SetResourcesImpl(uint32 bindSlot
, const CDeviceResourceSet
* pResources
)
882 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
883 const CDeviceResourceSet_DX12
* pResourcesDX12
= reinterpret_cast<const CDeviceResourceSet_DX12
*>(pResources
);
885 for (auto& it
: pResourcesDX12
->m_ConstantBuffersInUse
)
887 NCryDX12::CResource
& Resource
= it
.second
->GetDX12Resource();
889 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
890 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
));
892 #if defined(ENABLE_PROFILING_CODE)
893 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundConstBuffers
[Resource
.IsOffCard()]);
896 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
897 pCommandListDX12
->TrackResourceCBVUsage(Resource
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
);
900 for (auto& it
: pResourcesDX12
->m_ShaderResourceViewsInUse
)
902 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
903 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
905 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
906 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, View
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
));
908 #if defined(ENABLE_PROFILING_CODE)
909 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundUniformTextures
[Resource
.IsOffCard()]);
912 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
913 pCommandListDX12
->TrackResourceCRVUsage(Resource
, View
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
916 for (auto& it
: pResourcesDX12
->m_UnorderedAccessViewsInUse
)
918 const NCryDX12::CView
& View
= it
.second
->GetDX12View();
919 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
921 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
922 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
));
924 #if defined(ENABLE_PROFILING_CODE)
925 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundUniformBuffers
[Resource
.IsOffCard()]);
928 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
929 pCommandListDX12
->TrackResourceUAVUsage(Resource
, View
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
932 const CDescriptorBlock
& descriptorBlock
= pResourcesDX12
->GetDescriptorBlock();
933 pCommandListDX12
->SetComputeDescriptorTable(bindSlot
, descriptorBlock
.GetHandleOffsetGPU(0));
936 void CDeviceComputeCommandInterfaceImpl::SetInlineConstantBufferImpl(uint32 bindSlot
, const CConstantBuffer
* pBuffer
, EConstantBufferShaderSlot shaderSlot
)
938 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
940 const NCryDX12::CView
& View
= GET_DX12_CONSTANTBUFFER_RESOURCE(pBuffer
)->GetDX12View();
941 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
943 DX12_ASSERT(!Resource
.InitHasBeenDeferred(), "Resource %s hasn't been uploaded prior to use!", Resource
.GetName());
944 DX12_ASSERT(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
));
946 #if defined(ENABLE_PROFILING_CODE)
947 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundInlineBuffers
[Resource
.IsOffCard()]);
950 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
951 pCommandListDX12
->TrackResourceCBVUsage(Resource
, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
);
953 D3D12_GPU_VIRTUAL_ADDRESS gpuAddress
= View
.GetCBVDesc().BufferLocation
+ pBuffer
->m_offset
;
954 pCommandListDX12
->SetComputeConstantBufferView(bindSlot
, gpuAddress
);
957 void CDeviceComputeCommandInterfaceImpl::SetInlineShaderResourceImpl(uint32 bindSlot
, const CDeviceBuffer
* pBuffer
, EShaderResourceShaderSlot shaderSlot
, ResourceViewHandle resourceViewID
)
959 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
961 const NCryDX12::CView
& View
= GET_DX12_SHADER_VIEW(pBuffer
, resourceViewID
)->GetDX12View();
962 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
964 assert(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
));
966 #if defined(ENABLE_PROFILING_CODE)
967 CryInterlockedIncrement(&SRenderStatistics::Write().m_nNumBoundInlineBuffers
[Resource
.IsOffCard()]);
970 // TODO: if we know early that the resource(s) will be GENERIC_READ we can begin the barrier early and end it here
971 pCommandListDX12
->TrackResourceSRVUsage(Resource
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
973 D3D12_GPU_VIRTUAL_ADDRESS gpuAddress
= Resource
.GetGPUVirtualAddress();
974 pCommandListDX12
->SetComputeShaderResourceView(bindSlot
, gpuAddress
);
977 void CDeviceComputeCommandInterfaceImpl::SetInlineConstantsImpl(uint32 bindSlot
, uint32 constantCount
, float* pConstants
)
979 GetDX12CommandList()->SetCompute32BitConstants(bindSlot
, constantCount
, pConstants
, 0);
982 void CDeviceComputeCommandInterfaceImpl::DispatchImpl(uint32 X
, uint32 Y
, uint32 Z
)
984 GetDX12CommandList()->Dispatch(X
, Y
, Z
);
987 void CDeviceComputeCommandInterfaceImpl::ClearUAVImpl(D3DUAV
* pView
, const FLOAT Values
[4], UINT NumRects
, const D3D11_RECT
* pRects
)
989 const NCryDX12::CView
& View
= reinterpret_cast<CCryDX12UnorderedAccessView
*>(pView
)->GetDX12View();
990 GetDX12CommandList()->ClearUnorderedAccessView(View
, Values
, NumRects
, pRects
);
993 void CDeviceComputeCommandInterfaceImpl::ClearUAVImpl(D3DUAV
* pView
, const UINT Values
[4], UINT NumRects
, const D3D11_RECT
* pRects
)
995 const NCryDX12::CView
& View
= reinterpret_cast<CCryDX12UnorderedAccessView
*>(pView
)->GetDX12View();
996 GetDX12CommandList()->ClearUnorderedAccessView(View
, Values
, NumRects
, pRects
);
999 void CDeviceComputeCommandInterfaceImpl::DiscardUAVContentsImpl(D3DResource
* pResource
, uint32 numRects
, const D3D11_RECT
* pRects
)
1001 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
1002 NCryDX12::CResource
& Resource
= reinterpret_cast<CCryDX12Resource
<IEmptyResource
>*>(pResource
)->GetDX12Resource();
1003 D3D12_DISCARD_REGION rRegion
= { numRects
, pRects
, 0, 1 }; // NOTE: UAV-arrays are technically possible but not supported here
1004 assert(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
));
1005 pCommandListDX12
->DiscardResource(Resource
, &rRegion
);
1008 void CDeviceComputeCommandInterfaceImpl::DiscardUAVContentsImpl(D3DBaseView
* pView
, uint32 numRects
, const D3D11_RECT
* pRects
)
1010 NCryDX12::CCommandList
* pCommandListDX12
= GetDX12CommandList();
1011 const NCryDX12::CView
& View
= reinterpret_cast<CCryDX12RenderTargetView
*>(pView
)->GetDX12View();
1012 NCryDX12::CResource
& Resource
= View
.GetDX12Resource();
1013 D3D12_DISCARD_REGION rRegion
= { numRects
, pRects
, 0, 0x7FFFFFFF }; // TODO: calculate sub-resources and loop according to the given view
1014 assert(!Resource
.NeedsTransitionBarrier(pCommandListDX12
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
));
1015 pCommandListDX12
->DiscardResource(Resource
, &rRegion
);
1018 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1019 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceBuffer
* pSrc
, CDeviceBuffer
* pDst
)
1021 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1022 rd
->GetDeviceContext().CopyResource(pDst
->GetBaseBuffer(), pSrc
->GetBaseBuffer());
1025 void CDeviceCopyCommandInterfaceImpl::CopyImpl(D3DBuffer
* pSrc
, D3DBuffer
* pDst
)
1027 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1028 rd
->GetDeviceContext().CopyResource(pDst
, pSrc
);
1031 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture
* pSrc
, CDeviceTexture
* pDst
)
1033 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1034 rd
->GetDeviceContext().CopyResource(pDst
->GetBaseTexture(), pSrc
->GetBaseTexture());
1037 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture
* pSrc
, D3DTexture
* pDst
)
1039 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1040 rd
->GetDeviceContext().CopyResource(pDst
, pSrc
->GetBaseTexture());
1043 void CDeviceCopyCommandInterfaceImpl::CopyImpl(D3DTexture
* pSrc
, D3DTexture
* pDst
)
1045 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1046 rd
->GetDeviceContext().CopyResource(pDst
, pSrc
);
1049 void CDeviceCopyCommandInterfaceImpl::CopyImpl(D3DTexture
* pSrc
, CDeviceTexture
* pDst
)
1051 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1052 rd
->GetDeviceContext().CopyResource(pDst
->GetBaseTexture(), pSrc
);
1055 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceBuffer
* pSrc
, CDeviceBuffer
* pDst
, const SResourceRegionMapping
& region
)
1057 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1058 D3D11_BOX box
= { region
.SourceOffset
.Left
, region
.SourceOffset
.Top
, region
.SourceOffset
.Front
, region
.SourceOffset
.Left
+ region
.Extent
.Width
, region
.SourceOffset
.Top
+ region
.Extent
.Height
, region
.SourceOffset
.Front
+ region
.Extent
.Depth
};
1059 rd
->GetDeviceContext().CopySubresourcesRegion1(pDst
->GetBaseBuffer(), region
.DestinationOffset
.Subresource
, region
.DestinationOffset
.Left
, region
.DestinationOffset
.Top
, region
.DestinationOffset
.Front
, pSrc
->GetBaseBuffer(), region
.SourceOffset
.Subresource
, &box
, region
.Flags
, region
.Extent
.Subresources
);
1062 void CDeviceCopyCommandInterfaceImpl::CopyImpl(D3DBuffer
* pSrc
, D3DBuffer
* pDst
, const SResourceRegionMapping
& region
)
1064 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1065 D3D11_BOX box
= { region
.SourceOffset
.Left
, region
.SourceOffset
.Top
, region
.SourceOffset
.Front
, region
.SourceOffset
.Left
+ region
.Extent
.Width
, region
.SourceOffset
.Top
+ region
.Extent
.Height
, region
.SourceOffset
.Front
+ region
.Extent
.Depth
};
1066 rd
->GetDeviceContext().CopySubresourcesRegion1(pDst
, region
.DestinationOffset
.Subresource
, region
.DestinationOffset
.Left
, region
.DestinationOffset
.Top
, region
.DestinationOffset
.Front
, pSrc
, region
.SourceOffset
.Subresource
, &box
, region
.Flags
, region
.Extent
.Subresources
);
1069 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture
* pSrc
, CDeviceTexture
* pDst
, const SResourceRegionMapping
& region
)
1071 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1072 D3D11_BOX box
= { region
.SourceOffset
.Left
, region
.SourceOffset
.Top
, region
.SourceOffset
.Front
, region
.SourceOffset
.Left
+ region
.Extent
.Width
, region
.SourceOffset
.Top
+ region
.Extent
.Height
, region
.SourceOffset
.Front
+ region
.Extent
.Depth
};
1074 if (region
.Flags
& DX12_COPY_CONCURRENT_MARKER
)
1076 ICryDX12Resource
* dstDX12Resource
= DX12_EXTRACT_ICRYDX12RESOURCE(pDst
->GetBaseTexture());
1077 ICryDX12Resource
* srcDX12Resource
= DX12_EXTRACT_ICRYDX12RESOURCE(pSrc
->GetBaseTexture());
1078 NCryDX12::CResource
& rDstResource
= dstDX12Resource
->GetDX12Resource(); rDstResource
.VerifyBackBuffer(true);
1079 NCryDX12::CResource
& rSrcResource
= srcDX12Resource
->GetDX12Resource(); rSrcResource
.VerifyBackBuffer(false);
1082 D3D12_RESOURCE_STATES prevDstState
= rDstResource
.GetState(), dstState
= prevDstState
;
1083 D3D12_RESOURCE_STATES prevSrcState
= rSrcResource
.GetState(), srcState
= prevSrcState
;
1085 GetDX12CommandList()->MaxResourceFenceValue(rDstResource
, CMDTYPE_ANY
);
1086 GetDX12CommandList()->MaxResourceFenceValue(rSrcResource
, CMDTYPE_WRITE
);
1088 rDstResource
.TransitionBarrierStatic(GetDX12CommandList(), D3D12_RESOURCE_STATE_COPY_DEST
, dstState
);
1089 rSrcResource
.TransitionBarrierStatic(GetDX12CommandList(), D3D12_RESOURCE_STATE_COPY_SOURCE
, srcState
);
1091 GetDX12CommandList()->PendingResourceBarriers();
1093 CD3DX12_TEXTURE_COPY_LOCATION
src(rSrcResource
.GetD3D12Resource(), region
.SourceOffset
.Subresource
);
1094 CD3DX12_TEXTURE_COPY_LOCATION
dst(rDstResource
.GetD3D12Resource(), region
.DestinationOffset
.Subresource
);
1096 GetDX12CommandList()->CopyTextureRegion(
1097 &dst
, region
.DestinationOffset
.Left
, region
.DestinationOffset
.Top
, region
.DestinationOffset
.Front
,
1098 &src
, reinterpret_cast<const D3D12_BOX
*>(&box
));
1099 GetDX12CommandList()->m_nCommands
+= CLCOUNT_COPY
;
1101 GetDX12CommandList()->SetResourceFenceValue(rDstResource
, CMDTYPE_WRITE
);
1102 GetDX12CommandList()->SetResourceFenceValue(rSrcResource
, CMDTYPE_READ
);
1104 rDstResource
.TransitionBarrierStatic(GetDX12CommandList(), prevDstState
, dstState
);
1105 rSrcResource
.TransitionBarrierStatic(GetDX12CommandList(), prevSrcState
, srcState
);
1109 rd
->GetDeviceContext().CopySubresourcesRegion1(pDst
->GetBaseTexture(), region
.DestinationOffset
.Subresource
, region
.DestinationOffset
.Left
, region
.DestinationOffset
.Top
, region
.DestinationOffset
.Front
, pSrc
->GetBaseTexture(), region
.SourceOffset
.Subresource
, &box
, region
.Flags
, region
.Extent
.Subresources
);
1113 void CDeviceCopyCommandInterfaceImpl::CopyImpl(D3DTexture
* pSrc
, CDeviceTexture
* pDst
, const SResourceRegionMapping
& region
)
1115 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1116 D3D11_BOX box
= { region
.SourceOffset
.Left
, region
.SourceOffset
.Top
, region
.SourceOffset
.Front
, region
.SourceOffset
.Left
+ region
.Extent
.Width
, region
.SourceOffset
.Top
+ region
.Extent
.Height
, region
.SourceOffset
.Front
+ region
.Extent
.Depth
};
1117 rd
->GetDeviceContext().CopySubresourcesRegion1(pDst
->GetBaseTexture(), region
.DestinationOffset
.Subresource
, region
.DestinationOffset
.Left
, region
.DestinationOffset
.Top
, region
.DestinationOffset
.Front
, pSrc
, region
.SourceOffset
.Subresource
, &box
, region
.Flags
, region
.Extent
.Subresources
);
1120 void CDeviceCopyCommandInterfaceImpl::CopyImpl(const void* pSrc
, CConstantBuffer
* pDst
, const SResourceMemoryAlignment
& memoryLayout
)
1122 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1123 rd
->GetDeviceContext().UpdateSubresource(pDst
->GetD3D(), 0, nullptr, pSrc
, 0, 0);
1126 void CDeviceCopyCommandInterfaceImpl::CopyImpl(const void* pSrc
, CDeviceBuffer
* pDst
, const SResourceMemoryAlignment
& memoryLayout
)
1128 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1129 rd
->GetDeviceContext().UpdateSubresource(pDst
->GetBaseBuffer(), 0, nullptr, pSrc
, memoryLayout
.rowStride
, memoryLayout
.planeStride
);
1132 void CDeviceCopyCommandInterfaceImpl::CopyImpl(const void* pSrc
, CDeviceTexture
* pDst
, const SResourceMemoryAlignment
& memoryLayout
)
1134 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1135 rd
->GetDeviceContext().UpdateSubresource(pDst
->GetBaseTexture(), 0, nullptr, pSrc
, memoryLayout
.rowStride
, memoryLayout
.planeStride
);
1138 void CDeviceCopyCommandInterfaceImpl::CopyImpl(const void* pSrc
, CConstantBuffer
* pDst
, const SResourceMemoryMapping
& region
)
1140 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1141 D3D11_BOX box
= { region
.ResourceOffset
.Left
, region
.ResourceOffset
.Top
, region
.ResourceOffset
.Front
, region
.ResourceOffset
.Left
+ region
.Extent
.Width
, region
.ResourceOffset
.Top
+ region
.Extent
.Height
, region
.ResourceOffset
.Front
+ region
.Extent
.Depth
};
1142 rd
->GetDeviceContext().UpdateSubresource1(pDst
->GetD3D(), region
.ResourceOffset
.Subresource
, &box
, pSrc
, region
.MemoryLayout
.rowStride
, region
.MemoryLayout
.planeStride
, region
.Flags
);
1145 void CDeviceCopyCommandInterfaceImpl::CopyImpl(const void* pSrc
, CDeviceBuffer
* pDst
, const SResourceMemoryMapping
& region
)
1147 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1148 D3D11_BOX box
= { region
.ResourceOffset
.Left
, region
.ResourceOffset
.Top
, region
.ResourceOffset
.Front
, region
.ResourceOffset
.Left
+ region
.Extent
.Width
, region
.ResourceOffset
.Top
+ region
.Extent
.Height
, region
.ResourceOffset
.Front
+ region
.Extent
.Depth
};
1149 rd
->GetDeviceContext().UpdateSubresource1(pDst
->GetBaseBuffer(), region
.ResourceOffset
.Subresource
, &box
, pSrc
, region
.MemoryLayout
.rowStride
, region
.MemoryLayout
.planeStride
, region
.Flags
);
1152 void CDeviceCopyCommandInterfaceImpl::CopyImpl(const void* pSrc
, CDeviceTexture
* pDst
, const SResourceMemoryMapping
& region
)
1154 CD3D9Renderer
* const __restrict rd
= gcpRendD3D
;
1155 D3D11_BOX box
= { region
.ResourceOffset
.Left
, region
.ResourceOffset
.Top
, region
.ResourceOffset
.Front
, region
.ResourceOffset
.Left
+ region
.Extent
.Width
, region
.ResourceOffset
.Top
+ region
.Extent
.Height
, region
.ResourceOffset
.Front
+ region
.Extent
.Depth
};
1156 rd
->GetDeviceContext().UpdateSubresource1(pDst
->GetBaseTexture(), region
.ResourceOffset
.Subresource
, &box
, pSrc
, region
.MemoryLayout
.rowStride
, region
.MemoryLayout
.planeStride
, region
.Flags
);
1159 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceBuffer
* pSrc
, void* pDst
, const SResourceMemoryAlignment
& memoryLayout
)
1164 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture
* pSrc
, void* pDst
, const SResourceMemoryAlignment
& memoryLayout
)
1169 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceBuffer
* pSrc
, void* pDst
, const SResourceMemoryMapping
& region
)
1174 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture
* pSrc
, void* pDst
, const SResourceMemoryMapping
& region
)