ComputeSystemDX12Impl.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2025 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #ifdef JPH_USE_DX12
  6. #include <Jolt/Compute/DX12/ComputeSystemDX12Impl.h>
  7. #ifdef JPH_DEBUG
  8. #include <d3d12sdklayers.h>
  9. #endif
  10. JPH_NAMESPACE_BEGIN
  11. ComputeSystemDX12Impl::~ComputeSystemDX12Impl()
  12. {
  13. Shutdown();
  14. mDXGIFactory.Reset();
  15. #ifdef JPH_DEBUG
  16. // Test for leaks
  17. ComPtr<IDXGIDebug1> dxgi_debug;
  18. if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgi_debug))))
  19. dxgi_debug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
  20. #endif
  21. }
  22. bool ComputeSystemDX12Impl::Initialize()
  23. {
  24. #if defined(JPH_DEBUG)
  25. // Enable the D3D12 debug layer
  26. ComPtr<ID3D12Debug> debug_controller;
  27. if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller))))
  28. debug_controller->EnableDebugLayer();
  29. #endif
  30. // Create DXGI factory
  31. if (HRFailed(CreateDXGIFactory1(IID_PPV_ARGS(&mDXGIFactory))))
  32. return false;
  33. // Find adapter
  34. ComPtr<IDXGIAdapter1> adapter;
  35. ComPtr<ID3D12Device> device;
  36. HRESULT result = E_FAIL;
  37. // First check if we have the Windows 1803 IDXGIFactory6 interface
  38. ComPtr<IDXGIFactory6> factory6;
  39. if (SUCCEEDED(mDXGIFactory->QueryInterface(IID_PPV_ARGS(&factory6))))
  40. {
  41. for (int search_software = 0; search_software < 2 && device == nullptr; ++search_software)
  42. for (UINT index = 0; factory6->EnumAdapterByGpuPreference(index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(&adapter)) != DXGI_ERROR_NOT_FOUND; ++index)
  43. {
  44. DXGI_ADAPTER_DESC1 desc;
  45. adapter->GetDesc1(&desc);
  46. // We don't want software renderers in the first pass
  47. int is_software = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0? 1 : 0;
  48. if (search_software != is_software)
  49. continue;
  50. // Check to see whether the adapter supports Direct3D 12
  51. #if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
  52. int prev_state = _CrtSetDbgFlag(0); // Temporarily disable leak detection as this call reports false positives
  53. #endif
  54. result = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device));
  55. #if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
  56. _CrtSetDbgFlag(prev_state);
  57. #endif
  58. if (SUCCEEDED(result))
  59. break;
  60. }
  61. }
  62. else
  63. {
  64. // Fall back to the older method that may not get the fastest GPU
  65. for (int search_software = 0; search_software < 2 && device == nullptr; ++search_software)
  66. for (UINT index = 0; mDXGIFactory->EnumAdapters1(index, &adapter) != DXGI_ERROR_NOT_FOUND; ++index)
  67. {
  68. DXGI_ADAPTER_DESC1 desc;
  69. adapter->GetDesc1(&desc);
  70. // We don't want software renderers in the first pass
  71. int is_software = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0? 1 : 0;
  72. if (search_software != is_software)
  73. continue;
  74. // Check to see whether the adapter supports Direct3D 12
  75. #if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
  76. int prev_state = _CrtSetDbgFlag(0); // Temporarily disable leak detection as this call reports false positives
  77. #endif
  78. result = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device));
  79. #if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
  80. _CrtSetDbgFlag(prev_state);
  81. #endif
  82. if (SUCCEEDED(result))
  83. break;
  84. }
  85. }
  86. // Check if we managed to obtain a device
  87. if (HRFailed(result))
  88. return false;
  89. // Initialize the compute interface
  90. ComputeSystemDX12::Initialize(device.Get(), EDebug::DebugSymbols);
  91. #ifdef JPH_DEBUG
  92. // Enable breaking on errors
  93. ComPtr<ID3D12InfoQueue> info_queue;
  94. if (SUCCEEDED(device.As(&info_queue)))
  95. {
  96. info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
  97. info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
  98. info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
  99. // Disable an error that triggers on Windows 11 with a hybrid graphic system
  100. // See: https://stackoverflow.com/questions/69805245/directx-12-application-is-crashing-in-windows-11
  101. D3D12_MESSAGE_ID hide[] =
  102. {
  103. D3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE,
  104. };
  105. D3D12_INFO_QUEUE_FILTER filter = { };
  106. filter.DenyList.NumIDs = static_cast<UINT>( std::size( hide ) );
  107. filter.DenyList.pIDList = hide;
  108. info_queue->AddStorageFilterEntries( &filter );
  109. }
  110. #endif // JPH_DEBUG
  111. return true;
  112. }
  113. ComputeSystem *CreateComputeSystemDX12()
  114. {
  115. ComputeSystemDX12Impl *compute = new ComputeSystemDX12Impl();
  116. if (compute->Initialize())
  117. return compute;
  118. delete compute;
  119. return nullptr;
  120. }
  121. JPH_NAMESPACE_END
  122. #endif // JPH_USE_DX12