D3DCommon.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // Copyright 2019 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "VideoBackends/D3DCommon/D3DCommon.h"
  4. #include <d3d11.h>
  5. #include <d3d12.h>
  6. #include <dxgi1_3.h>
  7. #include <wrl/client.h>
  8. #include "Common/Assert.h"
  9. #include "Common/DynamicLibrary.h"
  10. #include "Common/HRWrap.h"
  11. #include "Common/MsgHandler.h"
  12. #include "Common/StringUtil.h"
  13. #include "VideoCommon/TextureConfig.h"
  14. #include "VideoCommon/VideoConfig.h"
  15. namespace D3DCommon
  16. {
  17. pD3DCompile d3d_compile;
  18. static Common::DynamicLibrary s_dxgi_library;
  19. static Common::DynamicLibrary s_d3dcompiler_library;
  20. static bool s_libraries_loaded = false;
  21. static HRESULT (*create_dxgi_factory)(REFIID riid, _COM_Outptr_ void** ppFactory);
  22. static HRESULT (*create_dxgi_factory2)(UINT Flags, REFIID riid, void** ppFactory);
  23. bool LoadLibraries()
  24. {
  25. if (s_libraries_loaded)
  26. return true;
  27. if (!s_dxgi_library.Open("dxgi.dll"))
  28. {
  29. PanicAlertFmtT("Failed to load dxgi.dll");
  30. return false;
  31. }
  32. if (!s_d3dcompiler_library.Open(D3DCOMPILER_DLL_A))
  33. {
  34. PanicAlertFmtT("Failed to load {0}. If you are using Windows 7, try installing the "
  35. "KB4019990 update package.",
  36. D3DCOMPILER_DLL_A);
  37. s_dxgi_library.Close();
  38. return false;
  39. }
  40. // Required symbols.
  41. if (!s_d3dcompiler_library.GetSymbol("D3DCompile", &d3d_compile) ||
  42. !s_dxgi_library.GetSymbol("CreateDXGIFactory", &create_dxgi_factory))
  43. {
  44. PanicAlertFmtT("Failed to find one or more D3D symbols");
  45. s_d3dcompiler_library.Close();
  46. s_dxgi_library.Close();
  47. return false;
  48. }
  49. // Optional symbols.
  50. s_dxgi_library.GetSymbol("CreateDXGIFactory2", &create_dxgi_factory2);
  51. s_libraries_loaded = true;
  52. return true;
  53. }
  54. void UnloadLibraries()
  55. {
  56. create_dxgi_factory = nullptr;
  57. create_dxgi_factory2 = nullptr;
  58. d3d_compile = nullptr;
  59. s_d3dcompiler_library.Close();
  60. s_dxgi_library.Close();
  61. s_libraries_loaded = false;
  62. }
  63. Microsoft::WRL::ComPtr<IDXGIFactory> CreateDXGIFactory(bool debug_device)
  64. {
  65. Microsoft::WRL::ComPtr<IDXGIFactory> factory;
  66. // Use Win8.1 version if available.
  67. if (create_dxgi_factory2 &&
  68. SUCCEEDED(create_dxgi_factory2(debug_device ? DXGI_CREATE_FACTORY_DEBUG : 0,
  69. IID_PPV_ARGS(factory.GetAddressOf()))))
  70. {
  71. return factory;
  72. }
  73. // Fallback to original version, without debug support.
  74. HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(factory.ReleaseAndGetAddressOf()));
  75. if (FAILED(hr))
  76. {
  77. PanicAlertFmt("CreateDXGIFactory() failed: {}", Common::HRWrap(hr));
  78. return nullptr;
  79. }
  80. return factory;
  81. }
  82. std::vector<std::string> GetAdapterNames()
  83. {
  84. Microsoft::WRL::ComPtr<IDXGIFactory> factory;
  85. HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(factory.GetAddressOf()));
  86. if (FAILED(hr))
  87. return {};
  88. std::vector<std::string> adapters;
  89. Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
  90. while (factory->EnumAdapters(static_cast<UINT>(adapters.size()),
  91. adapter.ReleaseAndGetAddressOf()) != DXGI_ERROR_NOT_FOUND)
  92. {
  93. std::string name;
  94. DXGI_ADAPTER_DESC desc;
  95. if (SUCCEEDED(adapter->GetDesc(&desc)))
  96. name = WStringToUTF8(desc.Description);
  97. adapters.push_back(std::move(name));
  98. }
  99. return adapters;
  100. }
  101. DXGI_FORMAT GetDXGIFormatForAbstractFormat(AbstractTextureFormat format, bool typeless)
  102. {
  103. switch (format)
  104. {
  105. case AbstractTextureFormat::DXT1:
  106. return DXGI_FORMAT_BC1_UNORM;
  107. case AbstractTextureFormat::DXT3:
  108. return DXGI_FORMAT_BC2_UNORM;
  109. case AbstractTextureFormat::DXT5:
  110. return DXGI_FORMAT_BC3_UNORM;
  111. case AbstractTextureFormat::BPTC:
  112. return DXGI_FORMAT_BC7_UNORM;
  113. case AbstractTextureFormat::RGBA8:
  114. return typeless ? DXGI_FORMAT_R8G8B8A8_TYPELESS : DXGI_FORMAT_R8G8B8A8_UNORM;
  115. case AbstractTextureFormat::BGRA8:
  116. return typeless ? DXGI_FORMAT_B8G8R8A8_TYPELESS : DXGI_FORMAT_B8G8R8A8_UNORM;
  117. case AbstractTextureFormat::RGB10_A2:
  118. return typeless ? DXGI_FORMAT_R10G10B10A2_TYPELESS : DXGI_FORMAT_R10G10B10A2_UNORM;
  119. case AbstractTextureFormat::RGBA16F:
  120. return typeless ? DXGI_FORMAT_R16G16B16A16_TYPELESS : DXGI_FORMAT_R16G16B16A16_FLOAT;
  121. case AbstractTextureFormat::R16:
  122. return typeless ? DXGI_FORMAT_R16_TYPELESS : DXGI_FORMAT_R16_UNORM;
  123. case AbstractTextureFormat::R32F:
  124. return typeless ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_R32_FLOAT;
  125. case AbstractTextureFormat::D16:
  126. return DXGI_FORMAT_R16_TYPELESS;
  127. case AbstractTextureFormat::D24_S8:
  128. return DXGI_FORMAT_R24G8_TYPELESS;
  129. case AbstractTextureFormat::D32F:
  130. return DXGI_FORMAT_R32_TYPELESS;
  131. case AbstractTextureFormat::D32F_S8:
  132. return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
  133. default:
  134. PanicAlertFmt("Unhandled texture format.");
  135. return DXGI_FORMAT_R8G8B8A8_UNORM;
  136. }
  137. }
  138. DXGI_FORMAT GetSRVFormatForAbstractFormat(AbstractTextureFormat format)
  139. {
  140. switch (format)
  141. {
  142. case AbstractTextureFormat::DXT1:
  143. return DXGI_FORMAT_BC1_UNORM;
  144. case AbstractTextureFormat::DXT3:
  145. return DXGI_FORMAT_BC2_UNORM;
  146. case AbstractTextureFormat::DXT5:
  147. return DXGI_FORMAT_BC3_UNORM;
  148. case AbstractTextureFormat::BPTC:
  149. return DXGI_FORMAT_BC7_UNORM;
  150. case AbstractTextureFormat::RGBA8:
  151. return DXGI_FORMAT_R8G8B8A8_UNORM;
  152. case AbstractTextureFormat::BGRA8:
  153. return DXGI_FORMAT_B8G8R8A8_UNORM;
  154. case AbstractTextureFormat::RGB10_A2:
  155. return DXGI_FORMAT_R10G10B10A2_UNORM;
  156. case AbstractTextureFormat::RGBA16F:
  157. return DXGI_FORMAT_R16G16B16A16_FLOAT;
  158. case AbstractTextureFormat::R16:
  159. return DXGI_FORMAT_R16_UNORM;
  160. case AbstractTextureFormat::R32F:
  161. return DXGI_FORMAT_R32_FLOAT;
  162. case AbstractTextureFormat::D16:
  163. return DXGI_FORMAT_R16_UNORM;
  164. case AbstractTextureFormat::D24_S8:
  165. return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
  166. case AbstractTextureFormat::D32F:
  167. return DXGI_FORMAT_R32_FLOAT;
  168. case AbstractTextureFormat::D32F_S8:
  169. return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
  170. default:
  171. PanicAlertFmt("Unhandled SRV format");
  172. return DXGI_FORMAT_UNKNOWN;
  173. }
  174. }
  175. DXGI_FORMAT GetRTVFormatForAbstractFormat(AbstractTextureFormat format, bool integer)
  176. {
  177. switch (format)
  178. {
  179. case AbstractTextureFormat::RGBA8:
  180. return integer ? DXGI_FORMAT_R8G8B8A8_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
  181. case AbstractTextureFormat::BGRA8:
  182. return DXGI_FORMAT_B8G8R8A8_UNORM;
  183. case AbstractTextureFormat::RGB10_A2:
  184. return DXGI_FORMAT_R10G10B10A2_UNORM;
  185. case AbstractTextureFormat::RGBA16F:
  186. return DXGI_FORMAT_R16G16B16A16_FLOAT;
  187. case AbstractTextureFormat::R16:
  188. return integer ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R16_UNORM;
  189. case AbstractTextureFormat::R32F:
  190. return DXGI_FORMAT_R32_FLOAT;
  191. default:
  192. PanicAlertFmt("Unhandled RTV format");
  193. return DXGI_FORMAT_UNKNOWN;
  194. }
  195. }
  196. DXGI_FORMAT GetDSVFormatForAbstractFormat(AbstractTextureFormat format)
  197. {
  198. switch (format)
  199. {
  200. case AbstractTextureFormat::D16:
  201. return DXGI_FORMAT_D16_UNORM;
  202. case AbstractTextureFormat::D24_S8:
  203. return DXGI_FORMAT_D24_UNORM_S8_UINT;
  204. case AbstractTextureFormat::D32F:
  205. return DXGI_FORMAT_D32_FLOAT;
  206. case AbstractTextureFormat::D32F_S8:
  207. return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
  208. default:
  209. PanicAlertFmt("Unhandled DSV format");
  210. return DXGI_FORMAT_UNKNOWN;
  211. }
  212. }
  213. AbstractTextureFormat GetAbstractFormatForDXGIFormat(DXGI_FORMAT format)
  214. {
  215. switch (format)
  216. {
  217. case DXGI_FORMAT_R8G8B8A8_UINT:
  218. case DXGI_FORMAT_R8G8B8A8_UNORM:
  219. case DXGI_FORMAT_R8G8B8A8_TYPELESS:
  220. return AbstractTextureFormat::RGBA8;
  221. case DXGI_FORMAT_B8G8R8A8_UNORM:
  222. case DXGI_FORMAT_B8G8R8A8_TYPELESS:
  223. return AbstractTextureFormat::BGRA8;
  224. case DXGI_FORMAT_R10G10B10A2_UNORM:
  225. case DXGI_FORMAT_R10G10B10A2_TYPELESS:
  226. return AbstractTextureFormat::RGB10_A2;
  227. case DXGI_FORMAT_R16G16B16A16_FLOAT:
  228. case DXGI_FORMAT_R16G16B16A16_TYPELESS:
  229. return AbstractTextureFormat::RGBA16F;
  230. case DXGI_FORMAT_R16_UINT:
  231. case DXGI_FORMAT_R16_UNORM:
  232. case DXGI_FORMAT_R16_TYPELESS:
  233. return AbstractTextureFormat::R16;
  234. case DXGI_FORMAT_R32_FLOAT:
  235. case DXGI_FORMAT_R32_TYPELESS:
  236. return AbstractTextureFormat::R32F;
  237. case DXGI_FORMAT_D16_UNORM:
  238. return AbstractTextureFormat::D16;
  239. case DXGI_FORMAT_D24_UNORM_S8_UINT:
  240. return AbstractTextureFormat::D24_S8;
  241. case DXGI_FORMAT_D32_FLOAT:
  242. return AbstractTextureFormat::D32F;
  243. case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
  244. return AbstractTextureFormat::D32F_S8;
  245. case DXGI_FORMAT_BC1_UNORM:
  246. return AbstractTextureFormat::DXT1;
  247. case DXGI_FORMAT_BC2_UNORM:
  248. return AbstractTextureFormat::DXT3;
  249. case DXGI_FORMAT_BC3_UNORM:
  250. return AbstractTextureFormat::DXT5;
  251. case DXGI_FORMAT_BC7_UNORM:
  252. return AbstractTextureFormat::BPTC;
  253. default:
  254. return AbstractTextureFormat::Undefined;
  255. }
  256. }
  257. void SetDebugObjectName(IUnknown* resource, std::string_view name)
  258. {
  259. if (!g_ActiveConfig.bEnableValidationLayer)
  260. return;
  261. Microsoft::WRL::ComPtr<ID3D11DeviceChild> child11;
  262. Microsoft::WRL::ComPtr<ID3D12DeviceChild> child12;
  263. if (SUCCEEDED(resource->QueryInterface(IID_PPV_ARGS(child11.GetAddressOf()))))
  264. {
  265. child11->SetPrivateData(WKPDID_D3DDebugObjectName, static_cast<UINT>(name.length()),
  266. name.data());
  267. }
  268. else if (SUCCEEDED(resource->QueryInterface(IID_PPV_ARGS(child12.GetAddressOf()))))
  269. {
  270. child12->SetPrivateData(WKPDID_D3DDebugObjectName, static_cast<UINT>(name.length()),
  271. name.data());
  272. }
  273. }
  274. } // namespace D3DCommon