dxgi.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*
  2. * Copyright 2011-2020 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "bgfx_p.h"
  6. #if BGFX_CONFIG_RENDERER_DIRECT3D11 || BGFX_CONFIG_RENDERER_DIRECT3D12
  7. #include "dxgi.h"
  8. #include "renderer_d3d.h"
  9. #if !BX_PLATFORM_WINDOWS && !BX_PLATFORM_LINUX
  10. # include <inspectable.h>
  11. # if BX_PLATFORM_WINRT
  12. # include <windows.ui.xaml.media.dxinterop.h>
  13. # endif // BX_PLATFORM_WINRT
  14. #endif // !BX_PLATFORM_WINDOWS
  15. namespace bgfx
  16. {
  17. BX_PRAGMA_DIAGNOSTIC_PUSH();
  18. BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wunused-variable");
  19. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunused-const-variable");
  20. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunneeded-internal-declaration");
  21. #if BX_PLATFORM_WINDOWS
  22. static PFN_CREATE_DXGI_FACTORY CreateDXGIFactory;
  23. static PFN_GET_DEBUG_INTERFACE DXGIGetDebugInterface;
  24. static PFN_GET_DEBUG_INTERFACE1 DXGIGetDebugInterface1;
  25. #endif // BX_PLATFORM_WINDOWS
  26. static const GUID IID_IDXGIFactory = { 0x7b7166ec, 0x21c7, 0x44ae, { 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69 } };
  27. static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
  28. static const GUID IID_IDXGIFactory3 = { 0x25483823, 0xcd46, 0x4c7d, { 0x86, 0xca, 0x47, 0xaa, 0x95, 0xb8, 0x37, 0xbd } };
  29. static const GUID IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } };
  30. static const GUID IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
  31. static const GUID IID_IDXGIDevice0 = { 0x54ec77fa, 0x1377, 0x44e6, { 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c } };
  32. static const GUID IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
  33. static const GUID IID_IDXGIDevice2 = { 0x05008617, 0xfbfd, 0x4051, { 0xa7, 0x90, 0x14, 0x48, 0x84, 0xb4, 0xf6, 0xa9 } };
  34. static const GUID IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
  35. static const GUID IID_IDXGIAdapter = { 0x2411e7e1, 0x12ac, 0x4ccf, { 0xbd, 0x14, 0x97, 0x98, 0xe8, 0x53, 0x4d, 0xc0 } };
  36. static const GUID IID_IDXGIAdapter2 = { 0x0aa1ae0a, 0xfa0e, 0x4b84, { 0x86, 0x44, 0xe0, 0x5f, 0xf8, 0xe5, 0xac, 0xb5 } };
  37. static const GUID IID_IDXGIAdapter3 = { 0x645967a4, 0x1392, 0x4310, { 0xa7, 0x98, 0x80, 0x53, 0xce, 0x3e, 0x93, 0xfd } };
  38. static const GUID IID_IDXGIAdapter4 = { 0x3c8d99d1, 0x4fbf, 0x4181, { 0xa8, 0x2c, 0xaf, 0x66, 0xbf, 0x7b, 0xd2, 0x4e } };
  39. static const GUID IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
  40. static const GUID IID_IDXGISwapChain4 = { 0x3d585d5a, 0xbd4a, 0x489e, { 0xb1, 0xf4, 0x3d, 0xbc, 0xb6, 0x45, 0x2f, 0xfb } };
  41. static const GUID IID_IDXGIOutput6 = { 0x068346e8, 0xaaec, 0x4b84, { 0xad, 0xd7, 0x13, 0x7f, 0x51, 0x3f, 0x77, 0xa1 } };
  42. BX_PRAGMA_DIAGNOSTIC_POP();
  43. static const DXGI_COLOR_SPACE_TYPE s_colorSpace[] =
  44. {
  45. DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // gamma 2.2, BT.709
  46. DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, // gamma 1.0, BT.709
  47. DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, // gamma 2084, BT.2020
  48. };
  49. static const char* s_colorSpaceStr[] =
  50. {
  51. // https://msdn.microsoft.com/en-us/library/windows/desktop/dn903661(v=vs.85).aspx
  52. "RGB, 0-255, 2.2, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
  53. "RGB, 0-255, 1.0, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
  54. "RGB, 16-235, 2.2, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
  55. "RGB, 16-235, 2.2, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
  56. "Reserved", // DXGI_COLOR_SPACE_RESERVED
  57. "YCbCr, 0-255, 2.2, Image, BT.709, BT.601", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601
  58. "YCbCr, 16-235, 2.2, Video, BT.601, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601
  59. "YCbCr, 0-255, 2.2, Video, BT.601, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
  60. "YCbCr, 16-235, 2.2, Video, BT.709, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709
  61. "YCbCr, 0-255, 2.2, Video, BT.709, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
  62. "YCbCr, 16-235, 2.2, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020
  63. "YCbCr, 0-255, 2.2, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
  64. "RGB, 0-255, 2084, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
  65. "YCbCr, 16-235, 2084, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020
  66. "RGB, 0-255, 2084, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
  67. "YCbCr, 16-235, 2.2, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020
  68. "YCbCr, 16-235, 2084, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
  69. #if BX_PLATFORM_WINDOWS
  70. "RGB, 0-255, 2.2, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
  71. "YCbCr, 16-235, HLG, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020
  72. "YCbCr, 0-255, HLG, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
  73. // "RGB, 16-235, 2.4, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709
  74. // "RGB, 16-235, 2.4, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020
  75. // "YCbCr, 16-235, 2.4, Video, BT.709, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709
  76. // "YCbCr, 16-235, 2.4, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020
  77. // "YCbCr, 16-235, 2.4, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020
  78. #endif // BX_PLATFORM_WINDOWS
  79. "Custom",
  80. };
  81. static const DXGI_COLOR_SPACE_TYPE kDxgiLastColorSpace =
  82. #if BX_PLATFORM_WINDOWS
  83. DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
  84. #else
  85. DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
  86. #endif // BX_PLATFORM_WINDOWS
  87. ;
  88. BX_STATIC_ASSERT(BX_COUNTOF(s_colorSpaceStr) == kDxgiLastColorSpace+2, "Colorspace string table mismatch with DXGI_COLOR_SPACE_*.");
  89. static const GUID s_dxgiDeviceIIDs[] =
  90. {
  91. IID_IDXGIDevice3,
  92. IID_IDXGIDevice2,
  93. IID_IDXGIDevice1,
  94. IID_IDXGIDevice0,
  95. };
  96. static const GUID s_dxgiSwapChainIIDs[] =
  97. {
  98. IID_IDXGISwapChain4,
  99. IID_IDXGISwapChain3,
  100. };
  101. DxgiSwapChain::DxgiSwapChain()
  102. {
  103. }
  104. Dxgi::Dxgi()
  105. : m_dxgiDll(NULL)
  106. , m_dxgiDebugDll(NULL)
  107. , m_driverType(D3D_DRIVER_TYPE_NULL)
  108. , m_factory(NULL)
  109. , m_adapter(NULL)
  110. , m_output(NULL)
  111. {
  112. }
  113. bool Dxgi::init(Caps& _caps)
  114. {
  115. #if BX_PLATFORM_WINDOWS
  116. m_dxgiDll = bx::dlopen("dxgi.dll");
  117. if (NULL == m_dxgiDll)
  118. {
  119. BX_TRACE("Init error: Failed to load dxgi.dll.");
  120. return false;
  121. }
  122. m_dxgiDebugDll = bx::dlopen("dxgidebug.dll");
  123. if (NULL != m_dxgiDebugDll)
  124. {
  125. DXGIGetDebugInterface = (PFN_GET_DEBUG_INTERFACE )bx::dlsym(m_dxgiDebugDll, "DXGIGetDebugInterface");
  126. DXGIGetDebugInterface1 = (PFN_GET_DEBUG_INTERFACE1)bx::dlsym(m_dxgiDebugDll, "DXGIGetDebugInterface1");
  127. if (NULL == DXGIGetDebugInterface
  128. && NULL == DXGIGetDebugInterface1)
  129. {
  130. bx::dlclose(m_dxgiDebugDll);
  131. m_dxgiDebugDll = NULL;
  132. }
  133. }
  134. CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgiDll, "CreateDXGIFactory1");
  135. if (NULL == CreateDXGIFactory)
  136. {
  137. CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgiDll, "CreateDXGIFactory");
  138. }
  139. if (NULL == CreateDXGIFactory)
  140. {
  141. BX_TRACE("Init error: Function CreateDXGIFactory not found.");
  142. return false;
  143. }
  144. #endif // BX_PLATFORM_WINDOWS
  145. HRESULT hr = S_OK;
  146. #if BX_PLATFORM_WINRT
  147. // WinRT requires the IDXGIFactory2 interface, which isn't supported on older platforms
  148. hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void**)&m_factory);
  149. #elif BX_PLATFORM_WINDOWS
  150. hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)&m_factory);
  151. #endif // BX_PLATFORM_*
  152. if (FAILED(hr) )
  153. {
  154. BX_TRACE("Init error: Unable to create DXGI factory.");
  155. return false;
  156. }
  157. m_driverType = BGFX_PCI_ID_SOFTWARE_RASTERIZER == _caps.vendorId
  158. ? D3D_DRIVER_TYPE_WARP
  159. : D3D_DRIVER_TYPE_HARDWARE
  160. ;
  161. if (NULL != m_factory)
  162. {
  163. AdapterI* adapter;
  164. for (uint32_t ii = 0
  165. ; DXGI_ERROR_NOT_FOUND != m_factory->EnumAdapters(ii, reinterpret_cast<IDXGIAdapter**>(&adapter) ) && ii < BX_COUNTOF(_caps.gpu)
  166. ; ++ii
  167. )
  168. {
  169. {
  170. DXGI_ADAPTER_DESC desc;
  171. hr = adapter->GetDesc(&desc);
  172. if (SUCCEEDED(hr) )
  173. {
  174. BX_TRACE("Adapter #%d", ii);
  175. char description[BX_COUNTOF(desc.Description)];
  176. wcstombs(description, desc.Description, BX_COUNTOF(desc.Description) );
  177. BX_TRACE("\tDescription: %s", description);
  178. BX_TRACE("\tVendorId: 0x%08x, DeviceId: 0x%08x, SubSysId: 0x%08x, Revision: 0x%08x"
  179. , desc.VendorId
  180. , desc.DeviceId
  181. , desc.SubSysId
  182. , desc.Revision
  183. );
  184. BX_TRACE("\tMemory: %" PRIi64 " (video), %" PRIi64 " (system), %" PRIi64 " (shared)"
  185. , desc.DedicatedVideoMemory
  186. , desc.DedicatedSystemMemory
  187. , desc.SharedSystemMemory
  188. );
  189. _caps.gpu[ii].vendorId = (uint16_t)desc.VendorId;
  190. _caps.gpu[ii].deviceId = (uint16_t)desc.DeviceId;
  191. ++_caps.numGPUs;
  192. if (NULL == m_adapter)
  193. {
  194. if ( (BGFX_PCI_ID_NONE != _caps.vendorId || 0 != _caps.deviceId)
  195. && (BGFX_PCI_ID_NONE == _caps.vendorId || desc.VendorId == _caps.vendorId)
  196. && ( 0 == _caps.deviceId || desc.DeviceId == _caps.deviceId) )
  197. {
  198. m_adapter = adapter;
  199. m_adapter->AddRef();
  200. m_driverType = D3D_DRIVER_TYPE_UNKNOWN;
  201. }
  202. if (BX_ENABLED(BGFX_CONFIG_DEBUG_PERFHUD)
  203. && !bx::strFind(description, "PerfHUD").isEmpty() )
  204. {
  205. m_adapter = adapter;
  206. m_driverType = D3D_DRIVER_TYPE_REFERENCE;
  207. }
  208. }
  209. }
  210. }
  211. bool hdr10 = false;
  212. IDXGIOutput* output;
  213. for (uint32_t jj = 0
  214. ; SUCCEEDED(adapter->EnumOutputs(jj, &output) )
  215. ; ++jj
  216. )
  217. {
  218. DXGI_OUTPUT_DESC outputDesc;
  219. hr = output->GetDesc(&outputDesc);
  220. if (SUCCEEDED(hr) )
  221. {
  222. BX_TRACE("\tOutput #%d", jj);
  223. char deviceName[BX_COUNTOF(outputDesc.DeviceName)];
  224. wcstombs(deviceName, outputDesc.DeviceName, BX_COUNTOF(outputDesc.DeviceName) );
  225. BX_TRACE("\t\t DeviceName: %s", deviceName);
  226. BX_TRACE("\t\t DesktopCoordinates: %d, %d, %d, %d"
  227. , outputDesc.DesktopCoordinates.left
  228. , outputDesc.DesktopCoordinates.top
  229. , outputDesc.DesktopCoordinates.right
  230. , outputDesc.DesktopCoordinates.bottom
  231. );
  232. BX_TRACE("\t\t AttachedToDesktop: %d", outputDesc.AttachedToDesktop);
  233. BX_TRACE("\t\t Rotation: %d", outputDesc.Rotation);
  234. #if BX_PLATFORM_WINDOWS
  235. IDXGIOutput6* output6;
  236. hr = output->QueryInterface(IID_IDXGIOutput6, (void**)&output6);
  237. if (SUCCEEDED(hr) )
  238. {
  239. DXGI_OUTPUT_DESC1 desc;
  240. hr = output6->GetDesc1(&desc);
  241. if (SUCCEEDED(hr) )
  242. {
  243. BX_TRACE("\t\t BitsPerColor: %d", desc.BitsPerColor);
  244. BX_TRACE("\t\t Color space: %s (colorspace, range, gamma, sitting, primaries, transform)"
  245. , s_colorSpaceStr[bx::min<uint32_t>(desc.ColorSpace, kDxgiLastColorSpace+1)]
  246. );
  247. BX_TRACE("\t\t RedPrimary: %f, %f", desc.RedPrimary[0], desc.RedPrimary[1]);
  248. BX_TRACE("\t\t GreenPrimary: %f, %f", desc.GreenPrimary[0], desc.GreenPrimary[1]);
  249. BX_TRACE("\t\t BluePrimary: %f, %f", desc.BluePrimary[0], desc.BluePrimary[1]);
  250. BX_TRACE("\t\t WhitePoint: %f, %f", desc.WhitePoint[0], desc.WhitePoint[1]);
  251. BX_TRACE("\t\t MinLuminance: %f", desc.MinLuminance);
  252. BX_TRACE("\t\t MaxLuminance: %f", desc.MaxLuminance);
  253. BX_TRACE("\t\tMaxFullFrameLuminance: %f", desc.MaxFullFrameLuminance);
  254. BX_TRACE("\t\t HDR support: %s", DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 == desc.ColorSpace ? "true" : "false");
  255. hdr10 |= DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 == desc.ColorSpace;
  256. }
  257. // BK - warn only because RenderDoc might be present.
  258. DX_RELEASE_W(output6, 1);
  259. }
  260. #endif // BX_PLATFORM_WINDOWS
  261. DX_RELEASE(output, 0);
  262. }
  263. }
  264. _caps.supported |= hdr10 ? BGFX_CAPS_HDR10 : 0;
  265. DX_RELEASE(adapter, adapter == m_adapter ? 1 : 0);
  266. }
  267. if (NULL == m_adapter)
  268. {
  269. hr = m_factory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&m_adapter) );
  270. BX_WARN(SUCCEEDED(hr), "EnumAdapters failed 0x%08x.", hr);
  271. m_driverType = D3D_DRIVER_TYPE_UNKNOWN;
  272. }
  273. bx::memSet(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
  274. hr = m_adapter->GetDesc(&m_adapterDesc);
  275. BX_WARN(SUCCEEDED(hr), "Adapter GetDesc failed 0x%08x.", hr);
  276. m_adapter->EnumOutputs(0, &m_output);
  277. _caps.vendorId = 0 == m_adapterDesc.VendorId
  278. ? BGFX_PCI_ID_SOFTWARE_RASTERIZER
  279. : (uint16_t)m_adapterDesc.VendorId
  280. ;
  281. _caps.deviceId = (uint16_t)m_adapterDesc.DeviceId;
  282. }
  283. return true;
  284. }
  285. void Dxgi::shutdown()
  286. {
  287. DX_RELEASE(m_output, 0);
  288. DX_RELEASE(m_adapter, 0);
  289. DX_RELEASE(m_factory, 0);
  290. bx::dlclose(m_dxgiDebugDll);
  291. m_dxgiDebugDll = NULL;
  292. bx::dlclose(m_dxgiDll);
  293. m_dxgiDll = NULL;
  294. }
  295. void Dxgi::update(IUnknown* _device)
  296. {
  297. IDXGIDevice* dxgiDevice = NULL;
  298. HRESULT hr = E_FAIL;
  299. for (uint32_t ii = 0; ii < BX_COUNTOF(s_dxgiDeviceIIDs) && FAILED(hr); ++ii)
  300. {
  301. hr = _device->QueryInterface(s_dxgiDeviceIIDs[ii], (void**)&dxgiDevice);
  302. BX_TRACE("DXGI device 11.%d, hr %x", BX_COUNTOF(s_dxgiDeviceIIDs) - 1 - ii, hr);
  303. }
  304. if (NULL == m_factory)
  305. {
  306. DX_CHECK(dxgiDevice->GetAdapter(reinterpret_cast<IDXGIAdapter**>(&m_adapter) ) );
  307. bx::memSet(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
  308. hr = m_adapter->GetDesc(&m_adapterDesc);
  309. BX_WARN(SUCCEEDED(hr), "Adapter GetDesc failed 0x%08x.", hr);
  310. DX_CHECK(m_adapter->GetParent(IID_IDXGIFactory2, (void**)&m_factory) );
  311. }
  312. DX_RELEASE_I(dxgiDevice);
  313. }
  314. static const GUID IID_ID3D12CommandQueue = { 0x0ec870a6, 0x5d7e, 0x4c22, { 0x8c, 0xfc, 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed } };
  315. HRESULT Dxgi::createSwapChain(IUnknown* _device, const SwapChainDesc& _scd, SwapChainI** _swapChain)
  316. {
  317. HRESULT hr = S_OK;
  318. uint32_t scdFlags = _scd.flags;
  319. #if BX_PLATFORM_WINDOWS
  320. IDXGIFactory5* factory5;
  321. hr = m_factory->QueryInterface(IID_IDXGIFactory5, (void**)&factory5);
  322. if (SUCCEEDED(hr) )
  323. {
  324. BOOL allowTearing = false;
  325. // BK - CheckFeatureSupport with DXGI_FEATURE_PRESENT_ALLOW_TEARING
  326. // will crash on pre Windows 8. Issue #1356.
  327. hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing) );
  328. BX_TRACE("Allow tearing is %ssupported.", allowTearing ? "" : "not ");
  329. scdFlags |= allowTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
  330. scdFlags |=
  331. (_scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
  332. || _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
  333. ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
  334. : 0;
  335. DX_RELEASE_I(factory5);
  336. }
  337. DXGI_SWAP_CHAIN_DESC scd;
  338. scd.BufferDesc.Width = _scd.width;
  339. scd.BufferDesc.Height = _scd.height;
  340. scd.BufferDesc.RefreshRate.Numerator = 1;
  341. scd.BufferDesc.RefreshRate.Denominator = 60;
  342. scd.BufferDesc.Format = _scd.format;
  343. scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
  344. scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
  345. scd.SampleDesc.Count = 1;
  346. scd.SampleDesc.Quality = 0;
  347. scd.BufferUsage = _scd.bufferUsage;
  348. scd.BufferCount = _scd.bufferCount;
  349. scd.OutputWindow = (HWND)_scd.nwh;
  350. scd.Windowed = _scd.windowed;
  351. scd.SwapEffect = _scd.swapEffect;
  352. scd.Flags = scdFlags;
  353. hr = m_factory->CreateSwapChain(
  354. _device
  355. , &scd
  356. , reinterpret_cast<IDXGISwapChain**>(_swapChain)
  357. );
  358. if (SUCCEEDED(hr) )
  359. {
  360. IDXGIDevice1* dxgiDevice1;
  361. _device->QueryInterface(IID_IDXGIDevice1, (void**)&dxgiDevice1);
  362. if (NULL != dxgiDevice1)
  363. {
  364. dxgiDevice1->SetMaximumFrameLatency(_scd.maxFrameLatency);
  365. DX_RELEASE_I(dxgiDevice1);
  366. }
  367. }
  368. #else
  369. DXGI_SWAP_CHAIN_DESC1 scd;
  370. scd.Width = _scd.width;
  371. scd.Height = _scd.height;
  372. scd.Format = _scd.format;
  373. scd.Stereo = _scd.stereo;
  374. scd.SampleDesc.Count = 1;
  375. scd.SampleDesc.Quality = 0;
  376. scd.BufferUsage = _scd.bufferUsage;
  377. scd.BufferCount = _scd.bufferCount;
  378. scd.Scaling = _scd.scaling;
  379. scd.SwapEffect = _scd.swapEffect;
  380. scd.AlphaMode = _scd.alphaMode;
  381. scd.Flags = scdFlags;
  382. if (NULL == _scd.ndt)
  383. {
  384. hr = m_factory->CreateSwapChainForCoreWindow(
  385. _device
  386. , (::IUnknown*)_scd.nwh
  387. , &scd
  388. , NULL
  389. , reinterpret_cast<IDXGISwapChain1**>(_swapChain)
  390. );
  391. }
  392. else if (reinterpret_cast<void*>(1) == _scd.ndt)
  393. {
  394. return E_FAIL;
  395. }
  396. else
  397. {
  398. hr = m_factory->CreateSwapChainForComposition(
  399. _device
  400. , &scd
  401. , NULL
  402. , reinterpret_cast<IDXGISwapChain1**>(_swapChain)
  403. );
  404. if (FAILED(hr) )
  405. {
  406. return hr;
  407. }
  408. # if BX_PLATFORM_WINRT
  409. IInspectable *nativeWindow = reinterpret_cast<IInspectable*>(_scd.nwh);
  410. ISwapChainPanelNative* swapChainPanelNative;
  411. hr = nativeWindow->QueryInterface(
  412. __uuidof(ISwapChainPanelNative)
  413. , (void**)&swapChainPanelNative
  414. );
  415. if (!FAILED(hr) )
  416. {
  417. // Swap Chain Panel
  418. if (NULL != swapChainPanelNative)
  419. {
  420. hr = swapChainPanelNative->SetSwapChain(*_swapChain);
  421. if (FAILED(hr) )
  422. {
  423. DX_RELEASE(swapChainPanelNative, 0);
  424. BX_TRACE("Failed to SetSwapChain, hr %x.");
  425. return hr;
  426. }
  427. DX_RELEASE_I(swapChainPanelNative);
  428. }
  429. }
  430. else
  431. {
  432. // Swap Chain Background Panel
  433. ISwapChainBackgroundPanelNative* swapChainBackgroundPanelNative = NULL;
  434. hr = nativeWindow->QueryInterface(
  435. __uuidof(ISwapChainBackgroundPanelNative)
  436. , (void**)&swapChainBackgroundPanelNative
  437. );
  438. if (FAILED(hr) )
  439. {
  440. return hr;
  441. }
  442. if (NULL != swapChainBackgroundPanelNative)
  443. {
  444. hr = swapChainBackgroundPanelNative->SetSwapChain(*_swapChain);
  445. if (FAILED(hr) )
  446. {
  447. DX_RELEASE(swapChainBackgroundPanelNative, 0);
  448. BX_TRACE("Failed to SetSwapChain, hr %x.");
  449. return hr;
  450. }
  451. DX_RELEASE_I(swapChainBackgroundPanelNative);
  452. }
  453. }
  454. # endif // BX_PLATFORM_WINRT
  455. }
  456. #endif // BX_PLATFORM_WINDOWS
  457. if (FAILED(hr) )
  458. {
  459. BX_TRACE("Failed to create swap chain.");
  460. return hr;
  461. }
  462. #if BX_PLATFORM_WINDOWS
  463. if (SUCCEEDED(hr) )
  464. {
  465. for (uint32_t ii = 0; ii < BX_COUNTOF(s_dxgiSwapChainIIDs); ++ii)
  466. {
  467. IDXGISwapChain1* swapChain;
  468. hr = (*_swapChain)->QueryInterface(s_dxgiSwapChainIIDs[ii], (void**)&swapChain);
  469. BX_TRACE("DXGI swap chain %d, hr %x", 4-ii, hr);
  470. if (SUCCEEDED(hr) )
  471. {
  472. DX_RELEASE(*_swapChain, 1);
  473. *_swapChain = reinterpret_cast<SwapChainI*>(swapChain);
  474. BX_TRACE("Color space support:");
  475. for (uint32_t jj = 0; jj < BX_COUNTOF(s_colorSpace); ++jj)
  476. {
  477. uint32_t colorSpaceSupport;
  478. reinterpret_cast<IDXGISwapChain3*>(*_swapChain)->CheckColorSpaceSupport(s_colorSpace[jj], &colorSpaceSupport);
  479. BX_TRACE("\t%2d: \"%-20s\", 0x%08x, %s"
  480. , s_colorSpace[jj]
  481. , s_colorSpaceStr[s_colorSpace[jj]]
  482. , colorSpaceSupport
  483. , 0 != (colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)
  484. ? "supported"
  485. : "-"
  486. );
  487. }
  488. break;
  489. }
  490. }
  491. }
  492. #endif // BX_PLATFORM_WINDOWS
  493. updateHdr10(*_swapChain, _scd);
  494. return S_OK;
  495. }
  496. void Dxgi::updateHdr10(SwapChainI* _swapChain, const SwapChainDesc& _scd)
  497. {
  498. #if BX_PLATFORM_WINDOWS
  499. ::IDXGISwapChain4* swapChain4;
  500. HRESULT hr = _swapChain->QueryInterface(IID_IDXGISwapChain4, (void**)&swapChain4);
  501. if (SUCCEEDED(hr) )
  502. {
  503. const DXGI_COLOR_SPACE_TYPE colorSpace =
  504. _scd.format == DXGI_FORMAT_R10G10B10A2_UNORM ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
  505. : _scd.format == DXGI_FORMAT_R16G16B16A16_FLOAT ? DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
  506. : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
  507. ;
  508. hr = swapChain4->SetColorSpace1(colorSpace);
  509. if (SUCCEEDED(hr) )
  510. {
  511. DXGI_OUTPUT_DESC1 desc;
  512. IDXGIOutput* output;
  513. hr = _swapChain->GetContainingOutput(&output);
  514. if (SUCCEEDED(hr) )
  515. {
  516. IDXGIOutput6* output6;
  517. hr = output->QueryInterface(IID_IDXGIOutput6, (void**)&output6);
  518. if (SUCCEEDED(hr) )
  519. {
  520. hr = output6->GetDesc1(&desc);
  521. if (SUCCEEDED(hr) )
  522. {
  523. BX_TRACE("Display specs:");
  524. BX_TRACE("\t BitsPerColor: %d", desc.BitsPerColor);
  525. BX_TRACE("\t Color space: %s (colorspace, range, gamma, sitting, primaries, transform)"
  526. , s_colorSpaceStr[bx::min<uint32_t>(desc.ColorSpace, kDxgiLastColorSpace+1)]
  527. );
  528. BX_TRACE("\t RedPrimary: %f, %f", desc.RedPrimary[0], desc.RedPrimary[1]);
  529. BX_TRACE("\t GreenPrimary: %f, %f", desc.GreenPrimary[0], desc.GreenPrimary[1]);
  530. BX_TRACE("\t BluePrimary: %f, %f", desc.BluePrimary[0], desc.BluePrimary[1]);
  531. BX_TRACE("\t WhitePoint: %f, %f", desc.WhitePoint[0], desc.WhitePoint[1]);
  532. BX_TRACE("\t MinLuminance: %f", desc.MinLuminance);
  533. BX_TRACE("\t MaxLuminance: %f", desc.MaxLuminance);
  534. BX_TRACE("\tMaxFullFrameLuminance: %f", desc.MaxFullFrameLuminance);
  535. }
  536. DX_RELEASE(output6, 1);
  537. }
  538. DX_RELEASE(output, 0);
  539. }
  540. DXGI_HDR_METADATA_HDR10 hdr10;
  541. hdr10.RedPrimary[0] = uint16_t(desc.RedPrimary[0] * 50000.0f);
  542. hdr10.RedPrimary[1] = uint16_t(desc.RedPrimary[1] * 50000.0f);
  543. hdr10.GreenPrimary[0] = uint16_t(desc.GreenPrimary[0] * 50000.0f);
  544. hdr10.GreenPrimary[1] = uint16_t(desc.GreenPrimary[1] * 50000.0f);
  545. hdr10.BluePrimary[0] = uint16_t(desc.BluePrimary[0] * 50000.0f);
  546. hdr10.BluePrimary[1] = uint16_t(desc.BluePrimary[1] * 50000.0f);
  547. hdr10.WhitePoint[0] = uint16_t(desc.WhitePoint[0] * 50000.0f);
  548. hdr10.WhitePoint[1] = uint16_t(desc.WhitePoint[1] * 50000.0f);
  549. hdr10.MaxMasteringLuminance = uint32_t(desc.MaxLuminance * 10000.0f);
  550. hdr10.MinMasteringLuminance = uint32_t(desc.MinLuminance * 10000.0f);
  551. hdr10.MaxContentLightLevel = uint16_t(desc.MaxFullFrameLuminance);
  552. hdr10.MaxFrameAverageLightLevel = uint16_t(desc.MaxFullFrameLuminance);
  553. hr = swapChain4->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(DXGI_HDR_METADATA_HDR10), &hdr10);
  554. }
  555. DX_RELEASE(swapChain4, 1);
  556. }
  557. #else
  558. BX_UNUSED(_swapChain, _scd);
  559. #endif // BX_PLATFORM_WINDOWS
  560. }
  561. HRESULT Dxgi::resizeBuffers(SwapChainI* _swapChain, const SwapChainDesc& _scd, const uint32_t* _nodeMask, IUnknown* const* _presentQueue)
  562. {
  563. HRESULT hr;
  564. uint32_t scdFlags = _scd.flags;
  565. #if BX_PLATFORM_WINDOWS
  566. IDXGIFactory5* factory5;
  567. hr = m_factory->QueryInterface(IID_IDXGIFactory5, (void**)&factory5);
  568. if (SUCCEEDED(hr))
  569. {
  570. BOOL allowTearing = false;
  571. // BK - CheckFeatureSupport with DXGI_FEATURE_PRESENT_ALLOW_TEARING
  572. // will crash on pre Windows 8. Issue #1356.
  573. hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing));
  574. BX_TRACE("Allow tearing is %ssupported.", allowTearing ? "" : "not ");
  575. scdFlags |= allowTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
  576. scdFlags |= (_scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
  577. || _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
  578. ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
  579. : 0;
  580. DX_RELEASE_I(factory5);
  581. }
  582. if (NULL != _nodeMask
  583. && NULL != _presentQueue)
  584. {
  585. hr = _swapChain->ResizeBuffers1(
  586. _scd.bufferCount
  587. , _scd.width
  588. , _scd.height
  589. , _scd.format
  590. , scdFlags
  591. , _nodeMask
  592. , _presentQueue
  593. );
  594. }
  595. else
  596. #endif // BX_PLATFORM_WINDOWS
  597. {
  598. BX_UNUSED(_nodeMask, _presentQueue);
  599. hr = _swapChain->ResizeBuffers(
  600. _scd.bufferCount
  601. , _scd.width
  602. , _scd.height
  603. , _scd.format
  604. , scdFlags
  605. );
  606. }
  607. if (SUCCEEDED(hr) )
  608. {
  609. updateHdr10(_swapChain, _scd);
  610. }
  611. return hr;
  612. }
  613. void Dxgi::trim()
  614. {
  615. #if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
  616. IDXGIDevice3* device;
  617. HRESULT hr = m_factory->QueryInterface(IID_IDXGIDevice3, (void**)&device);
  618. if (SUCCEEDED(hr) )
  619. {
  620. device->Trim();
  621. DX_RELEASE(device, 1);
  622. }
  623. #endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
  624. }
  625. } // namespace bgfx
  626. #endif // BGFX_CONFIG_RENDERER_DIRECT3D11 || BGFX_CONFIG_RENDERER_DIRECT3D12