D3DGrManager.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Gr/D3D/D3DGrManager.h>
  6. #include <AnKi/Gr/D3D/D3DDescriptor.h>
  7. #include <AnKi/Gr/D3D/D3DAccelerationStructure.h>
  8. #include <AnKi/Gr/D3D/D3DTexture.h>
  9. #include <AnKi/Gr/D3D/D3DCommandBuffer.h>
  10. #include <AnKi/Gr/D3D/D3DShader.h>
  11. #include <AnKi/Gr/D3D/D3DShaderProgram.h>
  12. #include <AnKi/Gr/D3D/D3DTexture.h>
  13. #include <AnKi/Gr/D3D/D3DPipelineQuery.h>
  14. #include <AnKi/Gr/D3D/D3DSampler.h>
  15. #include <AnKi/Gr/RenderGraph.h>
  16. #include <AnKi/Gr/D3D/D3DGrUpscaler.h>
  17. #include <AnKi/Gr/D3D/D3DTimestampQuery.h>
  18. #include <AnKi/ShaderCompiler/Common.h>
  19. #include <AnKi/Util/Tracer.h>
  20. #if ANKI_WINDOWING_SYSTEM_SDL
  21. # include <AnKi/Window/NativeWindowSdl.h>
  22. #endif
  23. // Use the Agility SDK
  24. extern "C" {
  25. __declspec(dllexport) extern const UINT D3D12SDKVersion = 616; // Number taken from the download page
  26. __declspec(dllexport) extern const char* D3D12SDKPath = ".\\"; // The D3D12Core.dll should be in the same dir as the .exe
  27. }
  28. namespace anki {
  29. static void NTAPI d3dDebugMessageCallback([[maybe_unused]] D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
  30. [[maybe_unused]] D3D12_MESSAGE_ID id, LPCSTR pDescription, [[maybe_unused]] void* pContext)
  31. {
  32. if(id == D3D12_MESSAGE_ID_INVALID_BARRIER_ACCESS)
  33. {
  34. // Skip these for now
  35. return;
  36. }
  37. if(!Logger::isAllocated())
  38. {
  39. printf("d3dDebugMessageCallback : %s", pDescription);
  40. return;
  41. }
  42. else
  43. {
  44. switch(severity)
  45. {
  46. case D3D12_MESSAGE_SEVERITY_CORRUPTION:
  47. case D3D12_MESSAGE_SEVERITY_ERROR:
  48. ANKI_D3D_LOGE("%s", pDescription);
  49. break;
  50. case D3D12_MESSAGE_SEVERITY_WARNING:
  51. ANKI_D3D_LOGW("%s", pDescription);
  52. break;
  53. case D3D12_MESSAGE_SEVERITY_INFO:
  54. case D3D12_MESSAGE_SEVERITY_MESSAGE:
  55. ANKI_D3D_LOGI("%s", pDescription);
  56. break;
  57. }
  58. }
  59. }
  60. template<>
  61. template<>
  62. GrManager& MakeSingletonPtr<GrManager>::allocateSingleton<>()
  63. {
  64. ANKI_ASSERT(m_global == nullptr);
  65. m_global = new GrManagerImpl;
  66. #if ANKI_ASSERTIONS_ENABLED
  67. ++g_singletonsAllocated;
  68. #endif
  69. return *m_global;
  70. }
  71. template<>
  72. void MakeSingletonPtr<GrManager>::freeSingleton()
  73. {
  74. if(m_global)
  75. {
  76. delete static_cast<GrManagerImpl*>(m_global);
  77. m_global = nullptr;
  78. #if ANKI_ASSERTIONS_ENABLED
  79. --g_singletonsAllocated;
  80. #endif
  81. }
  82. }
  83. GrManager::GrManager()
  84. {
  85. }
  86. GrManager::~GrManager()
  87. {
  88. }
  89. PtrSize GrManager::getAccelerationStructureMemoryRequirement(const AccelerationStructureInitInfo& init) const
  90. {
  91. PtrSize asSize, unused;
  92. AccelerationStructureImpl::getMemoryRequirement(init, asSize, unused);
  93. return asSize;
  94. }
  95. Error GrManager::init(GrManagerInitInfo& inf)
  96. {
  97. ANKI_D3D_SELF(GrManagerImpl);
  98. return self.initInternal(inf);
  99. }
  100. void GrManager::beginFrame()
  101. {
  102. ANKI_D3D_SELF(GrManagerImpl);
  103. self.beginFrameInternal();
  104. }
  105. TexturePtr GrManager::acquireNextPresentableTexture()
  106. {
  107. ANKI_D3D_SELF(GrManagerImpl);
  108. return self.acquireNextPresentableTextureInternal();
  109. }
  110. void GrManager::endFrame()
  111. {
  112. ANKI_D3D_SELF(GrManagerImpl);
  113. self.endFrameInternal();
  114. }
  115. void GrManager::finish()
  116. {
  117. ANKI_D3D_SELF(GrManagerImpl);
  118. self.finishInternal();
  119. }
  120. void GrManager::submit(WeakArray<CommandBuffer*> cmdbs, WeakArray<Fence*> waitFences, FencePtr* signalFence)
  121. {
  122. ANKI_D3D_SELF(GrManagerImpl);
  123. self.submitInternal(cmdbs, waitFences, signalFence);
  124. }
  125. #define ANKI_NEW_GR_OBJECT(type) \
  126. type##Ptr GrManager::new##type(const type##InitInfo& init) \
  127. { \
  128. type##Ptr ptr(type::newInstance(init)); \
  129. if(!ptr.isCreated()) [[unlikely]] \
  130. { \
  131. ANKI_D3D_LOGF("Failed to create a " ANKI_STRINGIZE(type) " object"); \
  132. } \
  133. return ptr; \
  134. }
  135. #define ANKI_NEW_GR_OBJECT_NO_INIT_INFO(type) \
  136. type##Ptr GrManager::new##type() \
  137. { \
  138. type##Ptr ptr(type::newInstance()); \
  139. if(!ptr.isCreated()) [[unlikely]] \
  140. { \
  141. ANKI_D3D_LOGF("Failed to create a " ANKI_STRINGIZE(type) " object"); \
  142. } \
  143. return ptr; \
  144. }
  145. ANKI_NEW_GR_OBJECT(Buffer)
  146. ANKI_NEW_GR_OBJECT(Texture)
  147. ANKI_NEW_GR_OBJECT(Sampler)
  148. ANKI_NEW_GR_OBJECT(Shader)
  149. ANKI_NEW_GR_OBJECT(ShaderProgram)
  150. ANKI_NEW_GR_OBJECT(CommandBuffer)
  151. ANKI_NEW_GR_OBJECT_NO_INIT_INFO(TimestampQuery)
  152. ANKI_NEW_GR_OBJECT(PipelineQuery)
  153. ANKI_NEW_GR_OBJECT_NO_INIT_INFO(RenderGraph)
  154. ANKI_NEW_GR_OBJECT(AccelerationStructure)
  155. ANKI_NEW_GR_OBJECT(GrUpscaler)
  156. #undef ANKI_NEW_GR_OBJECT
  157. #undef ANKI_NEW_GR_OBJECT_NO_INIT_INFO
  158. GrManagerImpl::~GrManagerImpl()
  159. {
  160. destroy();
  161. }
  162. void GrManagerImpl::beginFrameInternal()
  163. {
  164. ANKI_TRACE_FUNCTION();
  165. LockGuard<Mutex> lock(m_globalMtx);
  166. // Do that at begin frame, ALWAYS
  167. m_crntFrame = (m_crntFrame + 1) % m_frames.getSize();
  168. PerFrame& frame = m_frames[m_crntFrame];
  169. // Wait for the oldest frame because we don't want to start the new one too early
  170. {
  171. ANKI_TRACE_SCOPED_EVENT(WaitFences);
  172. for(MicroFencePtr& fence : frame.m_fences)
  173. {
  174. if(fence)
  175. {
  176. const Bool signaled = fence->clientWait(kMaxSecond);
  177. if(!signaled)
  178. {
  179. ANKI_D3D_LOGF("Timeout detected");
  180. }
  181. }
  182. }
  183. }
  184. frame.m_fences.destroy();
  185. frame.m_queueWroteToSwapchainImage = GpuQueueType::kCount;
  186. // Clear garbage
  187. deleteObjectsMarkedForDeletion();
  188. }
  189. TexturePtr GrManagerImpl::acquireNextPresentableTextureInternal()
  190. {
  191. ANKI_TRACE_FUNCTION();
  192. m_crntSwapchain->m_backbufferIdx = m_crntSwapchain->m_swapchain->GetCurrentBackBufferIndex();
  193. Texture* tex = m_crntSwapchain->m_textures[m_crntSwapchain->m_backbufferIdx].get();
  194. return TexturePtr(tex);
  195. }
  196. void GrManagerImpl::endFrameInternal()
  197. {
  198. ANKI_TRACE_FUNCTION();
  199. m_crntSwapchain->m_swapchain->Present((g_cvarGrVsync) ? 1 : 0, (g_cvarGrVsync) ? 0 : DXGI_PRESENT_ALLOW_TEARING);
  200. MicroFencePtr presentFence = FenceFactory::getSingleton().newInstance("Present");
  201. presentFence->getImplementation().gpuSignal(GpuQueueType::kGeneral); // Only general can present
  202. LockGuard lock(m_globalMtx);
  203. auto& crntFrame = m_frames[m_crntFrame];
  204. crntFrame.m_fences.emplaceBack(presentFence);
  205. DescriptorFactory::getSingleton().endFrame();
  206. }
  207. void GrManagerImpl::submitInternal(WeakArray<CommandBuffer*> cmdbs, WeakArray<Fence*> waitFences, FencePtr* signalFence)
  208. {
  209. ANKI_TRACE_FUNCTION();
  210. // First thing, create a fence
  211. MicroFencePtr fence = FenceFactory::getSingleton().newInstance("Submit");
  212. // Gather command lists
  213. GrDynamicArray<ID3D12CommandList*> d3dCmdLists;
  214. d3dCmdLists.resizeStorage(cmdbs.getSize());
  215. GpuQueueType queueType = GpuQueueType::kCount;
  216. for(CommandBuffer* cmdb : cmdbs)
  217. {
  218. CommandBufferImpl& impl = static_cast<CommandBufferImpl&>(*cmdb);
  219. MicroCommandBuffer& mcmdb = impl.getMicroCommandBuffer();
  220. d3dCmdLists.emplaceBack(&mcmdb.getCmdList());
  221. if(queueType == GpuQueueType::kCount)
  222. {
  223. queueType = mcmdb.getQueueType();
  224. }
  225. else
  226. {
  227. ANKI_ASSERT(queueType == mcmdb.getQueueType());
  228. }
  229. impl.postSubmitWork(fence.get());
  230. }
  231. // Wait for fences
  232. for(Fence* fence : waitFences)
  233. {
  234. FenceImpl& impl = static_cast<FenceImpl&>(*fence);
  235. impl.m_fence->getImplementation().gpuWait(queueType);
  236. }
  237. // Submit command lists
  238. m_queues[queueType]->ExecuteCommandLists(d3dCmdLists.getSize(), d3dCmdLists.getBegin());
  239. // Signal fence
  240. fence->getImplementation().gpuSignal(queueType);
  241. if(signalFence)
  242. {
  243. FenceImpl* fenceImpl = anki::newInstance<FenceImpl>(GrMemoryPool::getSingleton(), "SignalFence");
  244. fenceImpl->m_fence = fence;
  245. signalFence->reset(fenceImpl);
  246. }
  247. LockGuard lock(m_globalMtx);
  248. m_frames[m_crntFrame].m_fences.emplaceBack(fence.get());
  249. }
  250. void GrManagerImpl::finishInternal()
  251. {
  252. LockGuard<Mutex> lock(m_globalMtx);
  253. // Queue wait
  254. if(FenceFactory::isAllocated())
  255. {
  256. for(GpuQueueType qType : EnumIterable<GpuQueueType>())
  257. {
  258. MicroFencePtr fence = FenceFactory::getSingleton().newInstance();
  259. fence->getImplementation().gpuSignal(qType);
  260. fence->clientWait(kMaxSecond);
  261. }
  262. }
  263. for(PerFrame& frame : m_frames)
  264. {
  265. for(MicroFencePtr& fence : frame.m_fences)
  266. {
  267. const Bool signaled = fence->clientWait(kMaxSecond);
  268. if(!signaled)
  269. {
  270. ANKI_D3D_LOGF("Timeout detected");
  271. }
  272. }
  273. frame.m_fences.destroy();
  274. }
  275. // Since we waited for the GPU do a cleanup as well
  276. const U8 oldFrame = m_crntFrame;
  277. for(U8 frame = 0; frame < m_frames.getSize(); ++frame)
  278. {
  279. m_crntFrame = frame;
  280. deleteObjectsMarkedForDeletion();
  281. }
  282. m_crntFrame = oldFrame;
  283. }
  284. Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
  285. {
  286. ANKI_D3D_LOGI("Initializing D3D backend");
  287. GrMemoryPool::allocateSingleton(init.m_allocCallback, init.m_allocCallbackUserData);
  288. // Validation
  289. UINT dxgiFactoryFlags = 0;
  290. if(g_cvarGrValidation || g_cvarGrGpuValidation)
  291. {
  292. ComPtr<ID3D12Debug> debugInterface;
  293. ANKI_D3D_CHECK(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)));
  294. debugInterface->EnableDebugLayer();
  295. dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
  296. if(g_cvarGrGpuValidation)
  297. {
  298. ComPtr<ID3D12Debug1> debugInterface1;
  299. ANKI_D3D_CHECK(debugInterface->QueryInterface(IID_PPV_ARGS(&debugInterface1)));
  300. debugInterface1->SetEnableGPUBasedValidation(true);
  301. }
  302. ANKI_D3D_LOGI("Validation is enabled (GPU validation %s)", (g_cvarGrGpuValidation) ? "as well" : "no");
  303. }
  304. ComPtr<IDXGIFactory2> factory2;
  305. ANKI_D3D_CHECK(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory2)));
  306. ComPtr<IDXGIFactory6> factory6;
  307. ANKI_D3D_CHECK(factory2->QueryInterface(IID_PPV_ARGS(&factory6)));
  308. // Get adapters
  309. struct Adapter
  310. {
  311. ComPtr<IDXGIAdapter1> m_adapter;
  312. DXGI_ADAPTER_DESC1 m_descr;
  313. };
  314. GrDynamicArray<Adapter> adapters;
  315. ComPtr<IDXGIAdapter1> pAdapter;
  316. UINT adapterIdx = 0;
  317. while(factory6->EnumAdapterByGpuPreference(adapterIdx, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&pAdapter)) != DXGI_ERROR_NOT_FOUND)
  318. {
  319. Adapter& a = *adapters.emplaceBack();
  320. a.m_adapter = pAdapter;
  321. pAdapter->GetDesc1(&a.m_descr);
  322. ++adapterIdx;
  323. }
  324. const U32 chosenPhysDevIdx = min<U32>(g_cvarGrDevice, adapters.getSize() - 1);
  325. ANKI_D3D_LOGI("Physical devices:");
  326. for(U32 i = 0; i < adapters.getSize(); ++i)
  327. {
  328. ANKI_D3D_LOGI((i == chosenPhysDevIdx) ? "\t(Selected) %s" : "\t%s", ws2s(&adapters[i].m_descr.Description[0]).c_str());
  329. }
  330. // Find vendor
  331. switch(adapters[chosenPhysDevIdx].m_descr.VendorId)
  332. {
  333. case 0x13B5:
  334. m_capabilities.m_gpuVendor = GpuVendor::kArm;
  335. break;
  336. case 0x10DE:
  337. m_capabilities.m_gpuVendor = GpuVendor::kNvidia;
  338. break;
  339. case 0x1002:
  340. case 0x1022:
  341. m_capabilities.m_gpuVendor = GpuVendor::kAMD;
  342. break;
  343. case 0x8086:
  344. m_capabilities.m_gpuVendor = GpuVendor::kIntel;
  345. break;
  346. case 0x5143:
  347. m_capabilities.m_gpuVendor = GpuVendor::kQualcomm;
  348. break;
  349. default:
  350. m_capabilities.m_gpuVendor = GpuVendor::kUnknown;
  351. }
  352. ANKI_D3D_LOGI("Vendor identified as %s", &kGPUVendorStrings[m_capabilities.m_gpuVendor][0]);
  353. // Create device
  354. ComPtr<ID3D12Device> dev;
  355. ANKI_D3D_CHECK(D3D12CreateDevice(adapters[chosenPhysDevIdx].m_adapter.Get(), D3D_FEATURE_LEVEL_12_1, IID_PPV_ARGS(&dev)));
  356. ANKI_D3D_CHECK(dev->QueryInterface(IID_PPV_ARGS(&m_device)));
  357. if(g_cvarGrValidation)
  358. {
  359. ComPtr<ID3D12InfoQueue1> infoq;
  360. const HRESULT res = m_device->QueryInterface(IID_PPV_ARGS(&infoq));
  361. if(res == S_OK)
  362. {
  363. ANKI_D3D_CHECK(
  364. infoq->RegisterMessageCallback(d3dDebugMessageCallback, D3D12_MESSAGE_CALLBACK_FLAG_NONE, nullptr, &m_debugMessageCallbackCookie));
  365. }
  366. else
  367. {
  368. ANKI_D3D_LOGW("ID3D12InfoQueue1 not supported");
  369. // At least break when debugging
  370. if(IsDebuggerPresent())
  371. {
  372. ComPtr<ID3D12InfoQueue> infoq;
  373. const HRESULT res = m_device->QueryInterface(IID_PPV_ARGS(&infoq));
  374. if(res == S_OK)
  375. {
  376. infoq->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true);
  377. // infoq->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true);
  378. }
  379. }
  380. }
  381. }
  382. if(g_cvarGrDred)
  383. {
  384. ComPtr<ID3D12DeviceRemovedExtendedDataSettings> dredSettings;
  385. ANKI_D3D_CHECK(D3D12GetDebugInterface(IID_PPV_ARGS(&dredSettings)));
  386. // Turn on AutoBreadcrumbs and Page Fault reporting
  387. dredSettings->SetAutoBreadcrumbsEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
  388. dredSettings->SetPageFaultEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
  389. ANKI_D3D_LOGI("DRED is enabled");
  390. m_canInvokeDred = true;
  391. }
  392. // Create queues
  393. {
  394. D3D12_COMMAND_QUEUE_DESC queueDesc = {};
  395. queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
  396. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
  397. ANKI_D3D_CHECK(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_queues[GpuQueueType::kGeneral])));
  398. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
  399. ANKI_D3D_CHECK(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_queues[GpuQueueType::kCompute])));
  400. ANKI_D3D_CHECK(m_queues[GpuQueueType::kGeneral]->GetTimestampFrequency(&m_timestampFrequency));
  401. }
  402. // Set device capabilities (taken from mesa's dozen driver)
  403. {
  404. D3D12_FEATURE_DATA_D3D12_OPTIONS1 options1;
  405. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS1, &options1, sizeof(options1)));
  406. D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5;
  407. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5)));
  408. D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
  409. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS16, &options16, sizeof(options16)));
  410. D3D12_FEATURE_DATA_ARCHITECTURE architecture = {.NodeIndex = 0};
  411. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &architecture, sizeof(architecture)));
  412. D3D12_FEATURE_DATA_D3D12_OPTIONS21 options21;
  413. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS21, &options21, sizeof(options21)));
  414. if(g_cvarGrWorkGraphcs && options21.WorkGraphsTier == D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
  415. {
  416. ANKI_D3D_LOGW("WorkGraphs can't be enabled. They not supported");
  417. }
  418. else if(g_cvarGrWorkGraphcs && options21.WorkGraphsTier != D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
  419. {
  420. ANKI_D3D_LOGV("WorkGraphs supported");
  421. m_capabilities.m_workGraphs = true;
  422. }
  423. m_d3dCapabilities.m_rebar = options16.GPUUploadHeapSupported;
  424. if(!m_d3dCapabilities.m_rebar)
  425. {
  426. ANKI_D3D_LOGW("ReBAR not supported");
  427. }
  428. if(g_cvarGrRayTracing && options5.RaytracingTier != D3D12_RAYTRACING_TIER_1_1)
  429. {
  430. ANKI_D3D_LOGW("Raytracing can't be enabled. Not supported");
  431. m_capabilities.m_rayTracingEnabled = false;
  432. }
  433. else if(g_cvarGrRayTracing && options5.RaytracingTier == D3D12_RAYTRACING_TIER_1_1)
  434. {
  435. ANKI_D3D_LOGV("Raytracing supported");
  436. m_capabilities.m_rayTracingEnabled = true;
  437. }
  438. else
  439. {
  440. m_capabilities.m_rayTracingEnabled = false;
  441. }
  442. m_capabilities.m_minWaveSize = options1.WaveLaneCountMin;
  443. m_capabilities.m_maxWaveSize = options1.WaveLaneCountMax;
  444. m_capabilities.m_constantBufferBindOffsetAlignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
  445. m_capabilities.m_structuredBufferBindOffsetAlignment = 0; // Not for DX
  446. m_capabilities.m_structuredBufferNaturalAlignment = true;
  447. m_capabilities.m_texelBufferBindOffsetAlignment = 32;
  448. m_capabilities.m_fastConstantsSize = kMaxFastConstantsSize;
  449. m_capabilities.m_computeSharedMemorySize = D3D12_CS_TGSM_REGISTER_COUNT * sizeof(F32);
  450. m_capabilities.m_sbtRecordAlignment = 32; // ?
  451. m_capabilities.m_maxDrawIndirectCount = kMaxU32;
  452. m_capabilities.m_discreteGpu = !architecture.UMA;
  453. m_capabilities.m_majorApiVersion = 12;
  454. m_capabilities.m_vrs = g_cvarGrVrs;
  455. m_capabilities.m_unalignedBbpTextureFormats = false;
  456. m_capabilities.m_dlss = false;
  457. m_capabilities.m_meshShaders = g_cvarGrMeshShaders;
  458. m_capabilities.m_pipelineQuery = true;
  459. m_capabilities.m_barycentrics = true;
  460. m_capabilities.m_shaderGroupHandleSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
  461. // It should be D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT but anki uses a single SBT for raygen, miss and hit groups so the non raygen
  462. // groups should be aligned to the SBT buffer itself
  463. m_capabilities.m_sbtRecordAlignment = D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT;
  464. }
  465. // Other systems
  466. DescriptorFactory::allocateSingleton();
  467. ANKI_CHECK(DescriptorFactory::getSingleton().init());
  468. SwapchainFactory::allocateSingleton();
  469. m_crntSwapchain = SwapchainFactory::getSingleton().newInstance();
  470. RootSignatureFactory::allocateSingleton();
  471. FenceFactory::allocateSingleton();
  472. CommandBufferFactory::allocateSingleton();
  473. IndirectCommandSignatureFactory::allocateSingleton();
  474. ANKI_CHECK(IndirectCommandSignatureFactory::getSingleton().init());
  475. TimestampQueryFactory::allocateSingleton();
  476. PrimitivesPassedClippingFactory::allocateSingleton();
  477. {
  478. BufferInitInfo buffInit("ZeroBuffer");
  479. buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
  480. buffInit.m_size = 1_KB;
  481. buffInit.m_usage = BufferUsageBit::kCopySource;
  482. m_zeroBuffer = newBuffer(buffInit);
  483. void* mapped = m_zeroBuffer->map(0, kMaxPtrSize, BufferMapAccessBit::kWrite);
  484. memset(mapped, 0, buffInit.m_size);
  485. m_zeroBuffer->unmap();
  486. }
  487. return Error::kNone;
  488. }
  489. void GrManagerImpl::destroy()
  490. {
  491. ANKI_D3D_LOGI("Destroying D3D backend");
  492. finishInternal();
  493. // Destroy everything that has a reference to GrObjects.
  494. m_zeroBuffer.reset(nullptr);
  495. m_crntSwapchain.reset(nullptr);
  496. SwapchainFactory::freeSingleton();
  497. for(U8 frame = 0; frame < m_frames.getSize(); ++frame)
  498. {
  499. m_crntFrame = frame;
  500. deleteObjectsMarkedForDeletion();
  501. }
  502. // Destroy systems
  503. PrimitivesPassedClippingFactory::freeSingleton();
  504. TimestampQueryFactory::freeSingleton();
  505. CommandBufferFactory::freeSingleton();
  506. RootSignatureFactory::freeSingleton();
  507. DescriptorFactory::freeSingleton();
  508. IndirectCommandSignatureFactory::freeSingleton();
  509. FenceFactory::freeSingleton();
  510. safeRelease(m_queues[GpuQueueType::kGeneral]);
  511. safeRelease(m_queues[GpuQueueType::kCompute]);
  512. safeRelease(m_device);
  513. // Report objects that didn't cleaned up
  514. {
  515. ComPtr<IDXGIDebug1> dxgiDebug;
  516. if(SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug))))
  517. {
  518. dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL));
  519. }
  520. }
  521. GrMemoryPool::freeSingleton();
  522. }
  523. void GrManagerImpl::invokeDred() const
  524. {
  525. Bool error = false;
  526. do
  527. {
  528. if(m_canInvokeDred)
  529. {
  530. ComPtr<ID3D12DeviceRemovedExtendedData> pDred;
  531. if(!SUCCEEDED(m_device->QueryInterface(IID_PPV_ARGS(&pDred))))
  532. {
  533. error = true;
  534. break;
  535. }
  536. D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT dredAutoBreadcrumbsOutput;
  537. if(!SUCCEEDED(pDred->GetAutoBreadcrumbsOutput(&dredAutoBreadcrumbsOutput)))
  538. {
  539. error = true;
  540. break;
  541. }
  542. D3D12_DRED_PAGE_FAULT_OUTPUT dredPageFaultOutput;
  543. if(!SUCCEEDED(pDred->GetPageFaultAllocationOutput(&dredPageFaultOutput)))
  544. {
  545. error = true;
  546. break;
  547. }
  548. }
  549. } while(false);
  550. }
  551. } // end namespace anki