D3DGrManager.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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/D3DFrameGarbageCollector.h>
  8. #include <AnKi/Gr/D3D/D3DAccelerationStructure.h>
  9. #include <AnKi/Gr/D3D/D3DTexture.h>
  10. #include <AnKi/Gr/D3D/D3DCommandBuffer.h>
  11. #include <AnKi/Gr/D3D/D3DShader.h>
  12. #include <AnKi/Gr/D3D/D3DShaderProgram.h>
  13. #include <AnKi/Gr/D3D/D3DTexture.h>
  14. #include <AnKi/Gr/D3D/D3DPipelineQuery.h>
  15. #include <AnKi/Gr/D3D/D3DSampler.h>
  16. #include <AnKi/Gr/RenderGraph.h>
  17. #include <AnKi/Gr/D3D/D3DGrUpscaler.h>
  18. #include <AnKi/Gr/D3D/D3DTimestampQuery.h>
  19. #include <AnKi/ShaderCompiler/Common.h>
  20. #include <AnKi/Util/Tracer.h>
  21. #if ANKI_WINDOWING_SYSTEM_SDL
  22. # include <AnKi/Window/NativeWindowSdl.h>
  23. # include <SDL_syswm.h>
  24. #endif
  25. // Use the Agility SDK
  26. extern "C" {
  27. __declspec(dllexport) extern const UINT D3D12SDKVersion = 614; // Number taken from the download page
  28. __declspec(dllexport) extern const char* D3D12SDKPath = ".\\"; // The D3D12Core.dll should be in the same dir as the .exe
  29. }
  30. namespace anki {
  31. BoolCVar g_validationCVar(CVarSubsystem::kGr, "Validation", false, "Enable or not validation");
  32. static BoolCVar g_gpuValidationCVar(CVarSubsystem::kGr, "GpuValidation", false, "Enable or not GPU validation");
  33. BoolCVar g_vsyncCVar(CVarSubsystem::kGr, "Vsync", false, "Enable or not vsync");
  34. BoolCVar g_debugMarkersCVar(CVarSubsystem::kGr, "DebugMarkers", false, "Enable or not debug markers");
  35. BoolCVar g_meshShadersCVar(CVarSubsystem::kGr, "MeshShaders", false, "Enable or not mesh shaders");
  36. static NumericCVar<U8> g_deviceCVar(CVarSubsystem::kGr, "Device", 0, 0, 16, "Choose an available device. Devices are sorted by performance");
  37. static BoolCVar g_rayTracingCVar(CVarSubsystem::kGr, "RayTracing", false, "Try enabling ray tracing");
  38. static BoolCVar g_dredCVar(CVarSubsystem::kGr, "Dred", false, "Enable DRED");
  39. static BoolCVar g_vrsCVar(CVarSubsystem::kGr, "Vrs", false, "Enable or not VRS");
  40. static BoolCVar g_workGraphcsCVar(CVarSubsystem::kGr, "WorkGraphs", false, "Enable or not WorkGraphs");
  41. static void NTAPI d3dDebugMessageCallback([[maybe_unused]] D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
  42. [[maybe_unused]] D3D12_MESSAGE_ID id, LPCSTR pDescription, [[maybe_unused]] void* pContext)
  43. {
  44. if(id == D3D12_MESSAGE_ID_INCOMPATIBLE_BARRIER_LAYOUT)
  45. {
  46. // Skip for now
  47. return;
  48. }
  49. if(!Logger::isAllocated())
  50. {
  51. printf("d3dDebugMessageCallback : %s", pDescription);
  52. return;
  53. }
  54. else
  55. {
  56. switch(severity)
  57. {
  58. case D3D12_MESSAGE_SEVERITY_CORRUPTION:
  59. case D3D12_MESSAGE_SEVERITY_ERROR:
  60. ANKI_D3D_LOGE("%s", pDescription);
  61. break;
  62. case D3D12_MESSAGE_SEVERITY_WARNING:
  63. ANKI_D3D_LOGW("%s", pDescription);
  64. break;
  65. case D3D12_MESSAGE_SEVERITY_INFO:
  66. case D3D12_MESSAGE_SEVERITY_MESSAGE:
  67. ANKI_D3D_LOGI("%s", pDescription);
  68. break;
  69. }
  70. }
  71. }
  72. template<>
  73. template<>
  74. GrManager& MakeSingletonPtr<GrManager>::allocateSingleton<>()
  75. {
  76. ANKI_ASSERT(m_global == nullptr);
  77. m_global = new GrManagerImpl;
  78. #if ANKI_ASSERTIONS_ENABLED
  79. ++g_singletonsAllocated;
  80. #endif
  81. return *m_global;
  82. }
  83. template<>
  84. void MakeSingletonPtr<GrManager>::freeSingleton()
  85. {
  86. if(m_global)
  87. {
  88. delete static_cast<GrManagerImpl*>(m_global);
  89. m_global = nullptr;
  90. #if ANKI_ASSERTIONS_ENABLED
  91. --g_singletonsAllocated;
  92. #endif
  93. }
  94. }
  95. GrManager::GrManager()
  96. {
  97. }
  98. GrManager::~GrManager()
  99. {
  100. }
  101. Error GrManager::init(GrManagerInitInfo& inf)
  102. {
  103. ANKI_D3D_SELF(GrManagerImpl);
  104. return self.initInternal(inf);
  105. }
  106. TexturePtr GrManager::acquireNextPresentableTexture()
  107. {
  108. ANKI_D3D_SELF(GrManagerImpl);
  109. self.m_crntSwapchain->m_backbufferIdx = self.m_crntSwapchain->m_swapchain->GetCurrentBackBufferIndex();
  110. return self.m_crntSwapchain->m_textures[self.m_crntSwapchain->m_backbufferIdx];
  111. }
  112. void GrManager::swapBuffers()
  113. {
  114. ANKI_TRACE_SCOPED_EVENT(D3DSwapBuffers);
  115. ANKI_D3D_SELF(GrManagerImpl);
  116. self.m_crntSwapchain->m_swapchain->Present((g_vsyncCVar.get()) ? 1 : 0, (g_vsyncCVar.get()) ? 0 : DXGI_PRESENT_ALLOW_TEARING);
  117. MicroFencePtr presentFence = FenceFactory::getSingleton().newInstance();
  118. presentFence->gpuSignal(GpuQueueType::kGeneral);
  119. auto& crntFrame = self.m_frames[self.m_crntFrame];
  120. if(crntFrame.m_presentFence) [[likely]]
  121. {
  122. // Wait prev fence
  123. const Bool signaled = crntFrame.m_presentFence->clientWait(kMaxSecond);
  124. if(!signaled)
  125. {
  126. ANKI_D3D_LOGF("Frame fence didn't signal");
  127. }
  128. }
  129. crntFrame.m_presentFence = presentFence;
  130. self.m_crntFrame = (self.m_crntFrame + 1) % self.m_frames.getSize();
  131. FrameGarbageCollector::getSingleton().endFrame(presentFence.get());
  132. }
  133. void GrManager::finish()
  134. {
  135. if(FenceFactory::isAllocated())
  136. {
  137. for(GpuQueueType qType : EnumIterable<GpuQueueType>())
  138. {
  139. MicroFencePtr fence = FenceFactory::getSingleton().newInstance();
  140. fence->gpuSignal(qType);
  141. fence->clientWait(kMaxSecond);
  142. }
  143. }
  144. }
  145. #define ANKI_NEW_GR_OBJECT(type) \
  146. type##Ptr GrManager::new##type(const type##InitInfo& init) \
  147. { \
  148. type##Ptr ptr(type::newInstance(init)); \
  149. if(!ptr.isCreated()) [[unlikely]] \
  150. { \
  151. ANKI_D3D_LOGF("Failed to create a " ANKI_STRINGIZE(type) " object"); \
  152. } \
  153. return ptr; \
  154. }
  155. #define ANKI_NEW_GR_OBJECT_NO_INIT_INFO(type) \
  156. type##Ptr GrManager::new##type() \
  157. { \
  158. type##Ptr ptr(type::newInstance()); \
  159. if(!ptr.isCreated()) [[unlikely]] \
  160. { \
  161. ANKI_D3D_LOGF("Failed to create a " ANKI_STRINGIZE(type) " object"); \
  162. } \
  163. return ptr; \
  164. }
  165. ANKI_NEW_GR_OBJECT(Buffer)
  166. ANKI_NEW_GR_OBJECT(Texture)
  167. ANKI_NEW_GR_OBJECT(Sampler)
  168. ANKI_NEW_GR_OBJECT(Shader)
  169. ANKI_NEW_GR_OBJECT(ShaderProgram)
  170. ANKI_NEW_GR_OBJECT(CommandBuffer)
  171. ANKI_NEW_GR_OBJECT_NO_INIT_INFO(TimestampQuery)
  172. ANKI_NEW_GR_OBJECT(PipelineQuery)
  173. ANKI_NEW_GR_OBJECT_NO_INIT_INFO(RenderGraph)
  174. ANKI_NEW_GR_OBJECT(AccelerationStructure)
  175. ANKI_NEW_GR_OBJECT(GrUpscaler)
  176. #undef ANKI_NEW_GR_OBJECT
  177. #undef ANKI_NEW_GR_OBJECT_NO_INIT_INFO
  178. GrManagerImpl::~GrManagerImpl()
  179. {
  180. destroy();
  181. }
  182. void GrManager::submit(WeakArray<CommandBuffer*> cmdbs, WeakArray<Fence*> waitFences, FencePtr* signalFence)
  183. {
  184. ANKI_D3D_SELF(GrManagerImpl);
  185. // First thing, create a fence
  186. MicroFencePtr fence = FenceFactory::getSingleton().newInstance();
  187. // Gather command lists
  188. GrDynamicArray<ID3D12CommandList*> d3dCmdLists;
  189. d3dCmdLists.resizeStorage(cmdbs.getSize());
  190. GpuQueueType queueType = GpuQueueType::kCount;
  191. for(CommandBuffer* cmdb : cmdbs)
  192. {
  193. CommandBufferImpl& impl = static_cast<CommandBufferImpl&>(*cmdb);
  194. MicroCommandBuffer& mcmdb = impl.getMicroCommandBuffer();
  195. d3dCmdLists.emplaceBack(&mcmdb.getCmdList());
  196. if(queueType == GpuQueueType::kCount)
  197. {
  198. queueType = mcmdb.getQueueType();
  199. }
  200. else
  201. {
  202. ANKI_ASSERT(queueType == mcmdb.getQueueType());
  203. }
  204. mcmdb.setFence(fence.get());
  205. impl.postSubmitWork(fence.get());
  206. }
  207. // Wait for fences
  208. for(Fence* fence : waitFences)
  209. {
  210. FenceImpl& impl = static_cast<FenceImpl&>(*fence);
  211. impl.m_fence->gpuWait(queueType);
  212. }
  213. // Submit command lists
  214. self.m_queues[queueType]->ExecuteCommandLists(d3dCmdLists.getSize(), d3dCmdLists.getBegin());
  215. // Signal fence
  216. fence->gpuSignal(queueType);
  217. if(signalFence)
  218. {
  219. FenceImpl* fenceImpl = anki::newInstance<FenceImpl>(GrMemoryPool::getSingleton(), "SignalFence");
  220. fenceImpl->m_fence = fence;
  221. signalFence->reset(fenceImpl);
  222. }
  223. }
  224. Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
  225. {
  226. ANKI_D3D_LOGI("Initializing D3D backend");
  227. GrMemoryPool::allocateSingleton(init.m_allocCallback, init.m_allocCallbackUserData);
  228. // Validation
  229. UINT dxgiFactoryFlags = 0;
  230. if(g_validationCVar.get())
  231. {
  232. ComPtr<ID3D12Debug> debugInterface;
  233. ANKI_D3D_CHECK(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)));
  234. debugInterface->EnableDebugLayer();
  235. dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
  236. if(g_gpuValidationCVar.get())
  237. {
  238. ComPtr<ID3D12Debug1> debugInterface1;
  239. ANKI_D3D_CHECK(debugInterface->QueryInterface(IID_PPV_ARGS(&debugInterface1)));
  240. debugInterface1->SetEnableGPUBasedValidation(true);
  241. }
  242. ANKI_D3D_LOGI("Validation is enabled (GPU validation %s)", (g_gpuValidationCVar.get()) ? "as well" : "no");
  243. }
  244. ComPtr<IDXGIFactory2> factory2;
  245. ANKI_D3D_CHECK(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory2)));
  246. ComPtr<IDXGIFactory6> factory6;
  247. ANKI_D3D_CHECK(factory2->QueryInterface(IID_PPV_ARGS(&factory6)));
  248. // Get adapters
  249. struct Adapter
  250. {
  251. ComPtr<IDXGIAdapter1> m_adapter;
  252. DXGI_ADAPTER_DESC1 m_descr;
  253. };
  254. GrDynamicArray<Adapter> adapters;
  255. ComPtr<IDXGIAdapter1> pAdapter;
  256. UINT adapterIdx = 0;
  257. while(factory6->EnumAdapterByGpuPreference(adapterIdx, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&pAdapter)) != DXGI_ERROR_NOT_FOUND)
  258. {
  259. Adapter& a = *adapters.emplaceBack();
  260. a.m_adapter = pAdapter;
  261. pAdapter->GetDesc1(&a.m_descr);
  262. ++adapterIdx;
  263. }
  264. const U32 chosenPhysDevIdx = min<U32>(g_deviceCVar.get(), adapters.getSize() - 1);
  265. ANKI_D3D_LOGI("Physical devices:");
  266. for(U32 i = 0; i < adapters.getSize(); ++i)
  267. {
  268. ANKI_D3D_LOGI((i == chosenPhysDevIdx) ? "\t(Selected) %s" : "\t%s", ws2s(&adapters[i].m_descr.Description[0]).c_str());
  269. }
  270. // Find vendor
  271. switch(adapters[chosenPhysDevIdx].m_descr.VendorId)
  272. {
  273. case 0x13B5:
  274. m_capabilities.m_gpuVendor = GpuVendor::kArm;
  275. m_capabilities.m_minWaveSize = 16;
  276. m_capabilities.m_maxWaveSize = 16;
  277. break;
  278. case 0x10DE:
  279. m_capabilities.m_gpuVendor = GpuVendor::kNvidia;
  280. m_capabilities.m_minWaveSize = 32;
  281. m_capabilities.m_maxWaveSize = 32;
  282. break;
  283. case 0x1002:
  284. case 0x1022:
  285. m_capabilities.m_gpuVendor = GpuVendor::kAMD;
  286. m_capabilities.m_minWaveSize = 32;
  287. m_capabilities.m_maxWaveSize = 64;
  288. break;
  289. case 0x8086:
  290. m_capabilities.m_gpuVendor = GpuVendor::kIntel;
  291. m_capabilities.m_minWaveSize = 8;
  292. m_capabilities.m_maxWaveSize = 32;
  293. break;
  294. case 0x5143:
  295. m_capabilities.m_gpuVendor = GpuVendor::kQualcomm;
  296. m_capabilities.m_minWaveSize = 64;
  297. m_capabilities.m_maxWaveSize = 128;
  298. break;
  299. default:
  300. m_capabilities.m_gpuVendor = GpuVendor::kUnknown;
  301. // Choose something really low
  302. m_capabilities.m_minWaveSize = 8;
  303. m_capabilities.m_maxWaveSize = 8;
  304. }
  305. ANKI_D3D_LOGI("Vendor identified as %s", &kGPUVendorStrings[m_capabilities.m_gpuVendor][0]);
  306. // Create device
  307. ComPtr<ID3D12Device> dev;
  308. ANKI_D3D_CHECK(D3D12CreateDevice(adapters[chosenPhysDevIdx].m_adapter.Get(), D3D_FEATURE_LEVEL_12_1, IID_PPV_ARGS(&dev)));
  309. ANKI_D3D_CHECK(dev->QueryInterface(IID_PPV_ARGS(&m_device)));
  310. if(g_validationCVar.get())
  311. {
  312. ComPtr<ID3D12InfoQueue1> infoq;
  313. const HRESULT res = m_device->QueryInterface(IID_PPV_ARGS(&infoq));
  314. if(res == S_OK)
  315. {
  316. ANKI_D3D_CHECK(
  317. infoq->RegisterMessageCallback(d3dDebugMessageCallback, D3D12_MESSAGE_CALLBACK_FLAG_NONE, nullptr, &m_debugMessageCallbackCookie));
  318. }
  319. else
  320. {
  321. ANKI_D3D_LOGW("ID3D12InfoQueue1 not supported");
  322. }
  323. }
  324. if(g_dredCVar.get())
  325. {
  326. ComPtr<ID3D12DeviceRemovedExtendedDataSettings> dredSettings;
  327. ANKI_D3D_CHECK(D3D12GetDebugInterface(IID_PPV_ARGS(&dredSettings)));
  328. // Turn on AutoBreadcrumbs and Page Fault reporting
  329. dredSettings->SetAutoBreadcrumbsEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
  330. dredSettings->SetPageFaultEnablement(D3D12_DRED_ENABLEMENT_FORCED_ON);
  331. ANKI_D3D_LOGI("DRED is enabled");
  332. m_canInvokeDred = true;
  333. }
  334. // Create queues
  335. {
  336. D3D12_COMMAND_QUEUE_DESC queueDesc = {};
  337. queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
  338. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
  339. ANKI_D3D_CHECK(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_queues[GpuQueueType::kGeneral])));
  340. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
  341. ANKI_D3D_CHECK(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_queues[GpuQueueType::kCompute])));
  342. ANKI_D3D_CHECK(m_queues[GpuQueueType::kGeneral]->GetTimestampFrequency(&m_timestampFrequency));
  343. }
  344. // Set device capabilities (taken from mesa's dozen driver)
  345. {
  346. D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
  347. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS16, &options16, sizeof(options16)));
  348. D3D12_FEATURE_DATA_ARCHITECTURE architecture = {.NodeIndex = 0};
  349. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &architecture, sizeof(architecture)));
  350. D3D12_FEATURE_DATA_D3D12_OPTIONS21 options21;
  351. ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS21, &options21, sizeof(options21)));
  352. if(g_workGraphcsCVar.get() && options21.WorkGraphsTier == D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
  353. {
  354. ANKI_D3D_LOGW("WorkGraphs can't be enabled. They not supported");
  355. }
  356. else if(g_workGraphcsCVar.get() && options21.WorkGraphsTier != D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
  357. {
  358. ANKI_D3D_LOGV("WorkGraphs supported");
  359. m_capabilities.m_workGraphs = true;
  360. }
  361. m_d3dCapabilities.m_rebar = options16.GPUUploadHeapSupported;
  362. if(!m_d3dCapabilities.m_rebar)
  363. {
  364. ANKI_D3D_LOGW("ReBAR not supported");
  365. }
  366. m_capabilities.m_constantBufferBindOffsetAlignment = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
  367. m_capabilities.m_structuredBufferBindOffsetAlignment = 0; // Not for DX
  368. m_capabilities.m_structuredBufferNaturalAlignment = true;
  369. m_capabilities.m_texelBufferBindOffsetAlignment = 32;
  370. m_capabilities.m_fastConstantsSize = kMaxFastConstantsSize;
  371. m_capabilities.m_computeSharedMemorySize = D3D12_CS_TGSM_REGISTER_COUNT * sizeof(F32);
  372. m_capabilities.m_accelerationStructureBuildScratchOffsetAlignment = 32; // ?
  373. m_capabilities.m_sbtRecordAlignment = 32; // ?
  374. m_capabilities.m_maxDrawIndirectCount = kMaxU32;
  375. m_capabilities.m_discreteGpu = !architecture.UMA;
  376. m_capabilities.m_majorApiVersion = 12;
  377. m_capabilities.m_rayTracingEnabled = g_rayTracingCVar.get();
  378. m_capabilities.m_64bitAtomics = true;
  379. m_capabilities.m_vrs = g_vrsCVar.get();
  380. m_capabilities.m_samplingFilterMinMax = true;
  381. m_capabilities.m_unalignedBbpTextureFormats = false;
  382. m_capabilities.m_dlss = false;
  383. m_capabilities.m_meshShaders = g_meshShadersCVar.get();
  384. m_capabilities.m_pipelineQuery = true;
  385. m_capabilities.m_barycentrics = true;
  386. }
  387. // Other systems
  388. DescriptorFactory::allocateSingleton();
  389. ANKI_CHECK(DescriptorFactory::getSingleton().init());
  390. SwapchainFactory::allocateSingleton();
  391. m_crntSwapchain = SwapchainFactory::getSingleton().newInstance();
  392. RootSignatureFactory::allocateSingleton();
  393. FenceFactory::allocateSingleton();
  394. CommandBufferFactory::allocateSingleton();
  395. FrameGarbageCollector::allocateSingleton();
  396. IndirectCommandSignatureFactory::allocateSingleton();
  397. ANKI_CHECK(IndirectCommandSignatureFactory::getSingleton().init());
  398. TimestampQueryFactory::allocateSingleton();
  399. PrimitivesPassedClippingFactory::allocateSingleton();
  400. return Error::kNone;
  401. }
  402. void GrManagerImpl::destroy()
  403. {
  404. ANKI_D3D_LOGI("Destroying D3D backend");
  405. waitAllQueues();
  406. // Cleanup self
  407. m_crntSwapchain.reset(nullptr);
  408. m_frames = {};
  409. // Destroy systems
  410. CommandBufferFactory::freeSingleton();
  411. PrimitivesPassedClippingFactory::freeSingleton();
  412. TimestampQueryFactory::freeSingleton();
  413. SwapchainFactory::freeSingleton();
  414. FrameGarbageCollector::freeSingleton();
  415. RootSignatureFactory::freeSingleton();
  416. DescriptorFactory::freeSingleton();
  417. IndirectCommandSignatureFactory::freeSingleton();
  418. FenceFactory::freeSingleton();
  419. safeRelease(m_queues[GpuQueueType::kGeneral]);
  420. safeRelease(m_queues[GpuQueueType::kCompute]);
  421. safeRelease(m_device);
  422. // Report objects that didn't cleaned up
  423. {
  424. ComPtr<IDXGIDebug1> dxgiDebug;
  425. if(SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug))))
  426. {
  427. dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL));
  428. }
  429. }
  430. GrMemoryPool::freeSingleton();
  431. }
  432. void GrManagerImpl::waitAllQueues()
  433. {
  434. if(FenceFactory::isAllocated())
  435. {
  436. for(GpuQueueType queueType : EnumIterable<GpuQueueType>())
  437. {
  438. MicroFencePtr fence = FenceFactory::getSingleton().newInstance();
  439. fence->gpuSignal(queueType);
  440. fence->clientWait(kMaxSecond);
  441. }
  442. }
  443. }
  444. void GrManagerImpl::invokeDred() const
  445. {
  446. Bool error = false;
  447. do
  448. {
  449. if(m_canInvokeDred)
  450. {
  451. ComPtr<ID3D12DeviceRemovedExtendedData> pDred;
  452. if(!SUCCEEDED(m_device->QueryInterface(IID_PPV_ARGS(&pDred))))
  453. {
  454. error = true;
  455. break;
  456. }
  457. D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT dredAutoBreadcrumbsOutput;
  458. if(!SUCCEEDED(pDred->GetAutoBreadcrumbsOutput(&dredAutoBreadcrumbsOutput)))
  459. {
  460. error = true;
  461. break;
  462. }
  463. D3D12_DRED_PAGE_FAULT_OUTPUT dredPageFaultOutput;
  464. if(!SUCCEEDED(pDred->GetPageFaultAllocationOutput(&dredPageFaultOutput)))
  465. {
  466. error = true;
  467. break;
  468. }
  469. }
  470. } while(false);
  471. }
  472. } // end namespace anki