!F (Profiling) (DEV-7171) Added support for PIX profiler on Windows.
[CRYENGINE.git] / Code / CryEngine / RenderDll / XRenderD3D9 / DeviceManager / D3D12 / DeviceCommandListCommon_D3D12.cpp
blob0db7db8777c8496ff448ab5530dc22cf4415ee71
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
2 #include "StdAfx.h"
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
9 # define USE_PIX
10 # endif
11 # include <WinPixEventRuntime/pix3.h>
12 #endif
14 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
15 bool CDeviceTimestampGroup::s_reservedGroups[MAX_FRAMES_IN_FLIGHT] = { false, false, false, false };
17 CDeviceTimestampGroup::CDeviceTimestampGroup()
18 : m_numTimestamps(0)
19 , m_groupIndex(0xFFFFFFFF)
20 , m_fence(0)
21 , m_frequency(0)
22 , m_measurable(false)
23 , m_measured(false)
25 m_timeValues.fill(0);
28 CDeviceTimestampGroup::~CDeviceTimestampGroup()
30 s_reservedGroups[m_groupIndex] = false;
33 void CDeviceTimestampGroup::Init()
35 GetDeviceObjectFactory().CreateFence(m_fence);
36 m_numTimestamps = 0;
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;
44 m_groupIndex = i;
45 break;
49 assert(m_groupIndex < 0xFFFFFFFF);
52 void CDeviceTimestampGroup::BeginMeasurement()
54 m_numTimestamps = 0;
55 m_frequency = 0;
56 m_measurable = false;
57 m_measured = false;
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();
69 m_measurable = true;
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)
85 ++m_numTimestamps;
88 return timestampIndex;
91 bool CDeviceTimestampGroup::ResolveTimestamps()
93 if (!m_measurable)
94 return false;
95 if (m_measured || m_numTimestamps == 0)
96 return true;
98 auto* pDX12Device = GetDeviceObjectFactory().GetDX12Device();
99 auto* pDX12Scheduler = GetDeviceObjectFactory().GetDX12Scheduler();
101 if (pDX12Scheduler->TestForFence(m_fence) != S_OK)
102 return false;
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);
115 #endif
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);
123 #endif
126 void CDeviceCommandListImpl::EndProfilerEvent(const char* label)
128 #if defined(ENABLE_FRAME_PROFILER_LABELS)
129 PIXEndEvent(GetDX12CommandList()->GetD3D12CommandList());
130 m_profilerEventStack.pop_back();
131 #endif
134 void CDeviceCommandListImpl::ClearStateImpl(bool bOutputMergerOnly) const
138 void CDeviceCommandListImpl::CeaseCommandListEvent(int nPoolId)
140 if (nPoolId != CMDQUEUE_GRAPHICS)
141 return;
143 #if defined(USE_CRY_ASSERT) || defined(ENABLE_FRAME_PROFILER_LABELS)
144 auto* pCommandList = GetScheduler()->GetCommandList(nPoolId);
145 #endif
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());
155 #endif
157 reinterpret_cast<CDeviceCommandList*>(this)->Reset();
160 void CDeviceCommandListImpl::ResumeCommandListEvent(int nPoolId)
162 if (nPoolId != CMDQUEUE_GRAPHICS)
163 return;
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);
174 #endif
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 =
207 bCompute
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)
422 return;
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);
445 numBarriers += 1;
450 if (numBarriers > 0)
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();
472 pDSV = &View;
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);
486 pRTV[i] = &View;
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);
519 #endif
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()]);
551 #endif
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()]);
576 #endif
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);
581 #else
582 pCommandListDX12->BindAndSetIndexBufferView(pBuffer->GetDX12View(), (DXGI_FORMAT)indexStream->nStride, UINT(offset));
583 #endif
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()]);
601 #endif
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()]);
622 #endif
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()]);
640 #endif
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()]);
669 #endif
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()]);
695 #endif
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()]);
894 #endif
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()]);
910 #endif
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()]);
926 #endif
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()]);
948 #endif
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()]);
968 #endif
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);
1107 else
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)
1161 assert(0);
1164 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture* pSrc, void* pDst, const SResourceMemoryAlignment& memoryLayout)
1166 assert(0);
1169 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceBuffer* pSrc, void* pDst, const SResourceMemoryMapping& region)
1171 assert(0);
1174 void CDeviceCopyCommandInterfaceImpl::CopyImpl(CDeviceTexture* pSrc, void* pDst, const SResourceMemoryMapping& region)
1176 assert(0);