![Cedric Guillemet](/assets/img/avatar_default.png)
* premultiplied backbuffer for UWP/SwapchainPanel * init flag * caps and feedback/opengl premul * reduced #ifdef form * removed ifdef
815 lines
26 KiB
C++
815 lines
26 KiB
C++
/*
|
|
* Copyright 2011-2022 Branimir Karadzic. All rights reserved.
|
|
* License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
|
|
*/
|
|
|
|
#include "bgfx_p.h"
|
|
|
|
#if BGFX_CONFIG_RENDERER_DIRECT3D11 || BGFX_CONFIG_RENDERER_DIRECT3D12
|
|
|
|
#include "dxgi.h"
|
|
#include "renderer_d3d.h"
|
|
|
|
#if !BX_PLATFORM_WINDOWS && !BX_PLATFORM_LINUX
|
|
# include <inspectable.h>
|
|
# if BX_PLATFORM_WINRT
|
|
# include <windows.ui.xaml.media.dxinterop.h>
|
|
# endif // BX_PLATFORM_WINRT
|
|
#endif // !BX_PLATFORM_WINDOWS
|
|
|
|
namespace bgfx
|
|
{
|
|
BX_PRAGMA_DIAGNOSTIC_PUSH();
|
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wunused-variable");
|
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunused-const-variable");
|
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunneeded-internal-declaration");
|
|
|
|
#if BX_PLATFORM_WINDOWS
|
|
static PFN_CREATE_DXGI_FACTORY CreateDXGIFactory;
|
|
static PFN_GET_DEBUG_INTERFACE DXGIGetDebugInterface;
|
|
static PFN_GET_DEBUG_INTERFACE1 DXGIGetDebugInterface1;
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
|
|
static const GUID IID_IDXGIFactory = { 0x7b7166ec, 0x21c7, 0x44ae, { 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69 } };
|
|
static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
|
|
static const GUID IID_IDXGIFactory3 = { 0x25483823, 0xcd46, 0x4c7d, { 0x86, 0xca, 0x47, 0xaa, 0x95, 0xb8, 0x37, 0xbd } };
|
|
static const GUID IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } };
|
|
static const GUID IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
|
|
static const GUID IID_IDXGIDevice0 = { 0x54ec77fa, 0x1377, 0x44e6, { 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c } };
|
|
static const GUID IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
|
|
static const GUID IID_IDXGIDevice2 = { 0x05008617, 0xfbfd, 0x4051, { 0xa7, 0x90, 0x14, 0x48, 0x84, 0xb4, 0xf6, 0xa9 } };
|
|
static const GUID IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
|
|
static const GUID IID_IDXGIAdapter = { 0x2411e7e1, 0x12ac, 0x4ccf, { 0xbd, 0x14, 0x97, 0x98, 0xe8, 0x53, 0x4d, 0xc0 } };
|
|
static const GUID IID_IDXGIAdapter2 = { 0x0aa1ae0a, 0xfa0e, 0x4b84, { 0x86, 0x44, 0xe0, 0x5f, 0xf8, 0xe5, 0xac, 0xb5 } };
|
|
static const GUID IID_IDXGIAdapter3 = { 0x645967a4, 0x1392, 0x4310, { 0xa7, 0x98, 0x80, 0x53, 0xce, 0x3e, 0x93, 0xfd } };
|
|
static const GUID IID_IDXGIAdapter4 = { 0x3c8d99d1, 0x4fbf, 0x4181, { 0xa8, 0x2c, 0xaf, 0x66, 0xbf, 0x7b, 0xd2, 0x4e } };
|
|
static const GUID IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
|
|
static const GUID IID_IDXGISwapChain4 = { 0x3d585d5a, 0xbd4a, 0x489e, { 0xb1, 0xf4, 0x3d, 0xbc, 0xb6, 0x45, 0x2f, 0xfb } };
|
|
static const GUID IID_IDXGIOutput6 = { 0x068346e8, 0xaaec, 0x4b84, { 0xad, 0xd7, 0x13, 0x7f, 0x51, 0x3f, 0x77, 0xa1 } };
|
|
|
|
BX_PRAGMA_DIAGNOSTIC_POP();
|
|
|
|
static const DXGI_COLOR_SPACE_TYPE s_colorSpace[] =
|
|
{
|
|
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // gamma 2.2, BT.709
|
|
DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, // gamma 1.0, BT.709
|
|
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, // gamma 2084, BT.2020
|
|
};
|
|
|
|
static const char* s_colorSpaceStr[] =
|
|
{
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn903661(v=vs.85).aspx
|
|
"RGB, 0-255, 2.2, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
|
|
"RGB, 0-255, 1.0, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
|
|
"RGB, 16-235, 2.2, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
|
|
"RGB, 16-235, 2.2, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
|
|
"Reserved", // DXGI_COLOR_SPACE_RESERVED
|
|
"YCbCr, 0-255, 2.2, Image, BT.709, BT.601", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601
|
|
"YCbCr, 16-235, 2.2, Video, BT.601, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601
|
|
"YCbCr, 0-255, 2.2, Video, BT.601, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
|
|
"YCbCr, 16-235, 2.2, Video, BT.709, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709
|
|
"YCbCr, 0-255, 2.2, Video, BT.709, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
|
|
"YCbCr, 16-235, 2.2, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020
|
|
"YCbCr, 0-255, 2.2, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
|
|
"RGB, 0-255, 2084, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
|
|
"YCbCr, 16-235, 2084, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020
|
|
"RGB, 0-255, 2084, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
|
|
"YCbCr, 16-235, 2.2, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020
|
|
"YCbCr, 16-235, 2084, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
|
|
#if BX_PLATFORM_WINDOWS
|
|
"RGB, 0-255, 2.2, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
|
|
"YCbCr, 16-235, HLG, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020
|
|
"YCbCr, 0-255, HLG, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
|
|
// "RGB, 16-235, 2.4, Image, BT.709, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709
|
|
// "RGB, 16-235, 2.4, Image, BT.2020, n/a", // DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020
|
|
// "YCbCr, 16-235, 2.4, Video, BT.709, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709
|
|
// "YCbCr, 16-235, 2.4, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020
|
|
// "YCbCr, 16-235, 2.4, Video, BT.2020, n/a", // DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
"Custom",
|
|
};
|
|
static const DXGI_COLOR_SPACE_TYPE kDxgiLastColorSpace =
|
|
#if BX_PLATFORM_WINDOWS
|
|
DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
|
|
#else
|
|
DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
;
|
|
BX_STATIC_ASSERT(BX_COUNTOF(s_colorSpaceStr) == kDxgiLastColorSpace+2, "Colorspace string table mismatch with DXGI_COLOR_SPACE_*.");
|
|
|
|
static const GUID s_dxgiDeviceIIDs[] =
|
|
{
|
|
IID_IDXGIDevice3,
|
|
IID_IDXGIDevice2,
|
|
IID_IDXGIDevice1,
|
|
IID_IDXGIDevice0,
|
|
};
|
|
|
|
static const GUID s_dxgiSwapChainIIDs[] =
|
|
{
|
|
IID_IDXGISwapChain4,
|
|
IID_IDXGISwapChain3,
|
|
};
|
|
|
|
DxgiSwapChain::DxgiSwapChain()
|
|
{
|
|
}
|
|
|
|
Dxgi::Dxgi()
|
|
: m_dxgiDll(NULL)
|
|
, m_dxgiDebugDll(NULL)
|
|
, m_driverType(D3D_DRIVER_TYPE_NULL)
|
|
, m_factory(NULL)
|
|
, m_adapter(NULL)
|
|
, m_output(NULL)
|
|
, m_tearingSupported(false)
|
|
{
|
|
}
|
|
|
|
bool Dxgi::init(Caps& _caps)
|
|
{
|
|
#if BX_PLATFORM_WINDOWS
|
|
m_dxgiDll = bx::dlopen("dxgi.dll");
|
|
if (NULL == m_dxgiDll)
|
|
{
|
|
BX_TRACE("Init error: Failed to load dxgi.dll.");
|
|
return false;
|
|
}
|
|
|
|
m_dxgiDebugDll = bx::dlopen("dxgidebug.dll");
|
|
if (NULL != m_dxgiDebugDll)
|
|
{
|
|
DXGIGetDebugInterface = (PFN_GET_DEBUG_INTERFACE )bx::dlsym(m_dxgiDebugDll, "DXGIGetDebugInterface");
|
|
DXGIGetDebugInterface1 = (PFN_GET_DEBUG_INTERFACE1)bx::dlsym(m_dxgiDebugDll, "DXGIGetDebugInterface1");
|
|
if (NULL == DXGIGetDebugInterface
|
|
&& NULL == DXGIGetDebugInterface1)
|
|
{
|
|
bx::dlclose(m_dxgiDebugDll);
|
|
m_dxgiDebugDll = NULL;
|
|
}
|
|
}
|
|
|
|
CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgiDll, "CreateDXGIFactory1");
|
|
|
|
if (NULL == CreateDXGIFactory)
|
|
{
|
|
CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgiDll, "CreateDXGIFactory");
|
|
}
|
|
|
|
if (NULL == CreateDXGIFactory)
|
|
{
|
|
BX_TRACE("Init error: Function CreateDXGIFactory not found.");
|
|
return false;
|
|
}
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
|
|
HRESULT hr = S_OK;
|
|
#if BX_PLATFORM_WINRT
|
|
// WinRT requires the IDXGIFactory2 interface, which isn't supported on older platforms
|
|
hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void**)&m_factory);
|
|
#elif BX_PLATFORM_WINDOWS
|
|
hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)&m_factory);
|
|
#endif // BX_PLATFORM_*
|
|
|
|
if (FAILED(hr) )
|
|
{
|
|
BX_TRACE("Init error: Unable to create DXGI factory.");
|
|
return false;
|
|
}
|
|
|
|
m_driverType = BGFX_PCI_ID_SOFTWARE_RASTERIZER == _caps.vendorId
|
|
? D3D_DRIVER_TYPE_WARP
|
|
: D3D_DRIVER_TYPE_HARDWARE
|
|
;
|
|
|
|
if (NULL != m_factory)
|
|
{
|
|
AdapterI* adapter;
|
|
for (uint32_t ii = 0
|
|
; DXGI_ERROR_NOT_FOUND != m_factory->EnumAdapters(ii, reinterpret_cast<IDXGIAdapter**>(&adapter) ) && ii < BX_COUNTOF(_caps.gpu)
|
|
; ++ii
|
|
)
|
|
{
|
|
{
|
|
DXGI_ADAPTER_DESC desc;
|
|
hr = adapter->GetDesc(&desc);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
BX_TRACE("Adapter #%d", ii);
|
|
|
|
char description[BX_COUNTOF(desc.Description)];
|
|
wcstombs(description, desc.Description, BX_COUNTOF(desc.Description) );
|
|
BX_TRACE("\tDescription: %s", description);
|
|
BX_TRACE("\tVendorId: 0x%08x, DeviceId: 0x%08x, SubSysId: 0x%08x, Revision: 0x%08x"
|
|
, desc.VendorId
|
|
, desc.DeviceId
|
|
, desc.SubSysId
|
|
, desc.Revision
|
|
);
|
|
|
|
char dedicatedVideo[16];
|
|
bx::prettify(dedicatedVideo, BX_COUNTOF(dedicatedVideo), desc.DedicatedVideoMemory);
|
|
|
|
char dedicatedSystem[16];
|
|
bx::prettify(dedicatedSystem, BX_COUNTOF(dedicatedSystem), desc.DedicatedSystemMemory);
|
|
|
|
char sharedSystem[16];
|
|
bx::prettify(sharedSystem, BX_COUNTOF(sharedSystem), desc.SharedSystemMemory);
|
|
|
|
BX_TRACE("\tMemory: %s (video), %s (system), %s (shared)"
|
|
, dedicatedVideo
|
|
, dedicatedSystem
|
|
, sharedSystem
|
|
);
|
|
|
|
_caps.gpu[ii].vendorId = (uint16_t)desc.VendorId;
|
|
_caps.gpu[ii].deviceId = (uint16_t)desc.DeviceId;
|
|
++_caps.numGPUs;
|
|
|
|
if (NULL == m_adapter)
|
|
{
|
|
if ( (BGFX_PCI_ID_NONE != _caps.vendorId || 0 != _caps.deviceId)
|
|
&& (BGFX_PCI_ID_NONE == _caps.vendorId || desc.VendorId == _caps.vendorId)
|
|
&& ( 0 == _caps.deviceId || desc.DeviceId == _caps.deviceId) )
|
|
{
|
|
m_adapter = adapter;
|
|
m_adapter->AddRef();
|
|
m_driverType = D3D_DRIVER_TYPE_UNKNOWN;
|
|
}
|
|
|
|
if (BX_ENABLED(BGFX_CONFIG_DEBUG_PERFHUD)
|
|
&& !bx::strFind(description, "PerfHUD").isEmpty() )
|
|
{
|
|
m_adapter = adapter;
|
|
m_driverType = D3D_DRIVER_TYPE_REFERENCE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool hdr10 = false;
|
|
|
|
IDXGIOutput* output;
|
|
for (uint32_t jj = 0
|
|
; SUCCEEDED(adapter->EnumOutputs(jj, &output) )
|
|
; ++jj
|
|
)
|
|
{
|
|
DXGI_OUTPUT_DESC outputDesc;
|
|
hr = output->GetDesc(&outputDesc);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
BX_TRACE("\tOutput #%d", jj);
|
|
|
|
char deviceName[BX_COUNTOF(outputDesc.DeviceName)];
|
|
wcstombs(deviceName, outputDesc.DeviceName, BX_COUNTOF(outputDesc.DeviceName) );
|
|
BX_TRACE("\t\t DeviceName: %s", deviceName);
|
|
BX_TRACE("\t\t DesktopCoordinates: %d, %d, %d, %d"
|
|
, outputDesc.DesktopCoordinates.left
|
|
, outputDesc.DesktopCoordinates.top
|
|
, outputDesc.DesktopCoordinates.right
|
|
, outputDesc.DesktopCoordinates.bottom
|
|
);
|
|
BX_TRACE("\t\t AttachedToDesktop: %d", outputDesc.AttachedToDesktop);
|
|
BX_TRACE("\t\t Rotation: %d", outputDesc.Rotation);
|
|
|
|
#if BX_PLATFORM_WINDOWS
|
|
IDXGIOutput6* output6;
|
|
hr = output->QueryInterface(IID_IDXGIOutput6, (void**)&output6);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
DXGI_OUTPUT_DESC1 desc;
|
|
hr = output6->GetDesc1(&desc);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
BX_TRACE("\t\t BitsPerColor: %d", desc.BitsPerColor);
|
|
BX_TRACE("\t\t Color space: %s (colorspace, range, gamma, sitting, primaries, transform)"
|
|
, s_colorSpaceStr[bx::min<uint32_t>(desc.ColorSpace, kDxgiLastColorSpace+1)]
|
|
);
|
|
BX_TRACE("\t\t RedPrimary: %f, %f", desc.RedPrimary[0], desc.RedPrimary[1]);
|
|
BX_TRACE("\t\t GreenPrimary: %f, %f", desc.GreenPrimary[0], desc.GreenPrimary[1]);
|
|
BX_TRACE("\t\t BluePrimary: %f, %f", desc.BluePrimary[0], desc.BluePrimary[1]);
|
|
BX_TRACE("\t\t WhitePoint: %f, %f", desc.WhitePoint[0], desc.WhitePoint[1]);
|
|
BX_TRACE("\t\t MinLuminance: %f", desc.MinLuminance);
|
|
BX_TRACE("\t\t MaxLuminance: %f", desc.MaxLuminance);
|
|
BX_TRACE("\t\tMaxFullFrameLuminance: %f", desc.MaxFullFrameLuminance);
|
|
BX_TRACE("\t\t HDR support: %s", DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 == desc.ColorSpace ? "true" : "false");
|
|
|
|
hdr10 |= DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 == desc.ColorSpace;
|
|
}
|
|
|
|
// BK - warn only because RenderDoc might be present.
|
|
DX_RELEASE_W(output6, 1);
|
|
}
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
|
|
DX_RELEASE(output, 0);
|
|
}
|
|
}
|
|
|
|
_caps.supported |= hdr10 ? BGFX_CAPS_HDR10 : 0;
|
|
_caps.supported |= BX_ENABLED(BX_PLATFORM_WINRT) ? BGFX_CAPS_TRANSPARENT_BACKBUFFER : 0;
|
|
|
|
DX_RELEASE(adapter, adapter == m_adapter ? 1 : 0);
|
|
}
|
|
|
|
if (NULL == m_adapter)
|
|
{
|
|
hr = m_factory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&m_adapter) );
|
|
BX_WARN(SUCCEEDED(hr), "EnumAdapters failed 0x%08x.", hr);
|
|
m_driverType = D3D_DRIVER_TYPE_UNKNOWN;
|
|
}
|
|
|
|
bx::memSet(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
|
|
hr = m_adapter->GetDesc(&m_adapterDesc);
|
|
BX_WARN(SUCCEEDED(hr), "Adapter GetDesc failed 0x%08x.", hr);
|
|
|
|
m_adapter->EnumOutputs(0, &m_output);
|
|
|
|
_caps.vendorId = 0 == m_adapterDesc.VendorId
|
|
? BGFX_PCI_ID_SOFTWARE_RASTERIZER
|
|
: (uint16_t)m_adapterDesc.VendorId
|
|
;
|
|
_caps.deviceId = (uint16_t)m_adapterDesc.DeviceId;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Dxgi::shutdown()
|
|
{
|
|
DX_RELEASE(m_output, 0);
|
|
DX_RELEASE(m_adapter, 0);
|
|
DX_RELEASE(m_factory, 0);
|
|
|
|
bx::dlclose(m_dxgiDebugDll);
|
|
m_dxgiDebugDll = NULL;
|
|
|
|
bx::dlclose(m_dxgiDll);
|
|
m_dxgiDll = NULL;
|
|
}
|
|
|
|
void Dxgi::update(IUnknown* _device)
|
|
{
|
|
IDXGIDevice* dxgiDevice = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
for (uint32_t ii = 0; ii < BX_COUNTOF(s_dxgiDeviceIIDs) && FAILED(hr); ++ii)
|
|
{
|
|
hr = _device->QueryInterface(s_dxgiDeviceIIDs[ii], (void**)&dxgiDevice);
|
|
BX_TRACE("DXGI device 11.%d, hr %x", BX_COUNTOF(s_dxgiDeviceIIDs) - 1 - ii, hr);
|
|
}
|
|
|
|
if (NULL == m_factory)
|
|
{
|
|
DX_CHECK(dxgiDevice->GetAdapter(reinterpret_cast<IDXGIAdapter**>(&m_adapter) ) );
|
|
|
|
bx::memSet(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
|
|
hr = m_adapter->GetDesc(&m_adapterDesc);
|
|
BX_WARN(SUCCEEDED(hr), "Adapter GetDesc failed 0x%08x.", hr);
|
|
|
|
DX_CHECK(m_adapter->GetParent(IID_IDXGIFactory2, (void**)&m_factory) );
|
|
}
|
|
|
|
DX_RELEASE_I(dxgiDevice);
|
|
}
|
|
|
|
static const GUID IID_ID3D12CommandQueue = { 0x0ec870a6, 0x5d7e, 0x4c22, { 0x8c, 0xfc, 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed } };
|
|
|
|
HRESULT Dxgi::createSwapChain(IUnknown* _device, const SwapChainDesc& _scd, SwapChainI** _swapChain)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
uint32_t scdFlags = _scd.flags;
|
|
|
|
#if BX_PLATFORM_WINDOWS
|
|
IDXGIFactory5* factory5;
|
|
hr = m_factory->QueryInterface(IID_IDXGIFactory5, (void**)&factory5);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
BOOL allowTearing = false;
|
|
// BK - CheckFeatureSupport with DXGI_FEATURE_PRESENT_ALLOW_TEARING
|
|
// will crash on pre Windows 8. Issue #1356.
|
|
hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing) );
|
|
BX_TRACE("Allow tearing is %ssupported.", allowTearing ? "" : "not ");
|
|
|
|
scdFlags |= allowTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
|
scdFlags |= false
|
|
|| _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
|
|
|| _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD
|
|
? 0 // DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
|
|
: 0
|
|
;
|
|
|
|
m_tearingSupported = allowTearing;
|
|
|
|
DX_RELEASE_I(factory5);
|
|
}
|
|
|
|
DXGI_SWAP_CHAIN_DESC scd;
|
|
scd.BufferDesc.Width = _scd.width;
|
|
scd.BufferDesc.Height = _scd.height;
|
|
scd.BufferDesc.RefreshRate.Numerator = 1;
|
|
scd.BufferDesc.RefreshRate.Denominator = 60;
|
|
scd.BufferDesc.Format = _scd.format;
|
|
scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
|
scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
|
scd.SampleDesc.Count = 1;
|
|
scd.SampleDesc.Quality = 0;
|
|
scd.BufferUsage = _scd.bufferUsage;
|
|
scd.BufferCount = _scd.bufferCount;
|
|
scd.OutputWindow = (HWND)_scd.nwh;
|
|
scd.Windowed = _scd.windowed;
|
|
scd.SwapEffect = _scd.swapEffect;
|
|
scd.Flags = scdFlags;
|
|
|
|
hr = m_factory->CreateSwapChain(
|
|
_device
|
|
, &scd
|
|
, reinterpret_cast<IDXGISwapChain**>(_swapChain)
|
|
);
|
|
#else
|
|
DXGI_SWAP_CHAIN_DESC1 scd;
|
|
scd.Width = _scd.width;
|
|
scd.Height = _scd.height;
|
|
scd.Format = _scd.format;
|
|
scd.Stereo = _scd.stereo;
|
|
scd.SampleDesc.Count = 1;
|
|
scd.SampleDesc.Quality = 0;
|
|
scd.BufferUsage = _scd.bufferUsage;
|
|
scd.BufferCount = _scd.bufferCount;
|
|
scd.Scaling = _scd.scaling;
|
|
scd.SwapEffect = _scd.swapEffect;
|
|
scd.AlphaMode = _scd.alphaMode;
|
|
scd.Flags = scdFlags;
|
|
|
|
if (NULL == _scd.ndt)
|
|
{
|
|
hr = m_factory->CreateSwapChainForCoreWindow(
|
|
_device
|
|
, (::IUnknown*)_scd.nwh
|
|
, &scd
|
|
, NULL
|
|
, reinterpret_cast<IDXGISwapChain1**>(_swapChain)
|
|
);
|
|
}
|
|
else if (reinterpret_cast<void*>(1) == _scd.ndt)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = m_factory->CreateSwapChainForComposition(
|
|
_device
|
|
, &scd
|
|
, NULL
|
|
, reinterpret_cast<IDXGISwapChain1**>(_swapChain)
|
|
);
|
|
if (FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
# if BX_PLATFORM_WINRT
|
|
IInspectable *nativeWindow = reinterpret_cast<IInspectable*>(_scd.nwh);
|
|
ISwapChainPanelNative* swapChainPanelNative;
|
|
|
|
hr = nativeWindow->QueryInterface(
|
|
__uuidof(ISwapChainPanelNative)
|
|
, (void**)&swapChainPanelNative
|
|
);
|
|
|
|
if (!FAILED(hr) )
|
|
{
|
|
// Swap Chain Panel
|
|
if (NULL != swapChainPanelNative)
|
|
{
|
|
hr = swapChainPanelNative->SetSwapChain(*_swapChain);
|
|
|
|
if (FAILED(hr) )
|
|
{
|
|
DX_RELEASE(swapChainPanelNative, 0);
|
|
BX_TRACE("Failed to SetSwapChain, hr %x.");
|
|
return hr;
|
|
}
|
|
|
|
DX_RELEASE_I(swapChainPanelNative);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Swap Chain Background Panel
|
|
ISwapChainBackgroundPanelNative* swapChainBackgroundPanelNative = NULL;
|
|
|
|
hr = nativeWindow->QueryInterface(
|
|
__uuidof(ISwapChainBackgroundPanelNative)
|
|
, (void**)&swapChainBackgroundPanelNative
|
|
);
|
|
|
|
if (FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (NULL != swapChainBackgroundPanelNative)
|
|
{
|
|
hr = swapChainBackgroundPanelNative->SetSwapChain(*_swapChain);
|
|
|
|
if (FAILED(hr) )
|
|
{
|
|
DX_RELEASE(swapChainBackgroundPanelNative, 0);
|
|
BX_TRACE("Failed to SetSwapChain, hr %x.");
|
|
return hr;
|
|
}
|
|
|
|
DX_RELEASE_I(swapChainBackgroundPanelNative);
|
|
}
|
|
}
|
|
# endif // BX_PLATFORM_WINRT
|
|
}
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
IDXGIDevice1* dxgiDevice1;
|
|
_device->QueryInterface(IID_IDXGIDevice1, (void**)&dxgiDevice1);
|
|
if (NULL != dxgiDevice1)
|
|
{
|
|
hr = dxgiDevice1->SetMaximumFrameLatency(_scd.maxFrameLatency);
|
|
if (FAILED(hr) )
|
|
{
|
|
BX_TRACE("Failed to set maximum frame latency, hr 0x%08x", hr);
|
|
hr = S_OK;
|
|
}
|
|
DX_RELEASE_I(dxgiDevice1);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr) )
|
|
{
|
|
BX_TRACE("Failed to create swap chain.");
|
|
return hr;
|
|
}
|
|
|
|
#if BX_PLATFORM_WINDOWS
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
for (uint32_t ii = 0; ii < BX_COUNTOF(s_dxgiSwapChainIIDs); ++ii)
|
|
{
|
|
IDXGISwapChain1* swapChain;
|
|
hr = (*_swapChain)->QueryInterface(s_dxgiSwapChainIIDs[ii], (void**)&swapChain);
|
|
BX_TRACE("DXGI swap chain %d, hr %x", 4-ii, hr);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
DX_RELEASE(*_swapChain, 1);
|
|
*_swapChain = reinterpret_cast<SwapChainI*>(swapChain);
|
|
|
|
BX_TRACE("Color space support:");
|
|
for (uint32_t jj = 0; jj < BX_COUNTOF(s_colorSpace); ++jj)
|
|
{
|
|
uint32_t colorSpaceSupport;
|
|
reinterpret_cast<IDXGISwapChain3*>(*_swapChain)->CheckColorSpaceSupport(s_colorSpace[jj], &colorSpaceSupport);
|
|
BX_TRACE("\t%2d: \"%-20s\", 0x%08x, %s"
|
|
, s_colorSpace[jj]
|
|
, s_colorSpaceStr[s_colorSpace[jj]]
|
|
, colorSpaceSupport
|
|
, 0 != (colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)
|
|
? "supported"
|
|
: "-"
|
|
);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
|
|
updateHdr10(*_swapChain, _scd);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
#if BX_PLATFORM_WINRT
|
|
HRESULT Dxgi::removeSwapChain(const SwapChainDesc& _scd, SwapChainI** _swapChain)
|
|
{
|
|
IInspectable *nativeWindow = reinterpret_cast<IInspectable*>(_scd.nwh);
|
|
ISwapChainPanelNative* swapChainPanelNative;
|
|
|
|
HRESULT hr = nativeWindow->QueryInterface(
|
|
__uuidof(ISwapChainPanelNative)
|
|
, (void**)&swapChainPanelNative
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Swap Chain Panel
|
|
if (NULL != swapChainPanelNative)
|
|
{
|
|
// Remove swap chain
|
|
hr = swapChainPanelNative->SetSwapChain(NULL);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DX_RELEASE(swapChainPanelNative, 0);
|
|
BX_TRACE("Failed to SetSwapChain, hr %x.");
|
|
return hr;
|
|
}
|
|
|
|
DX_RELEASE_I(swapChainPanelNative);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Swap Chain Background Panel
|
|
ISwapChainBackgroundPanelNative* swapChainBackgroundPanelNative = NULL;
|
|
|
|
hr = nativeWindow->QueryInterface(
|
|
__uuidof(ISwapChainBackgroundPanelNative)
|
|
, (void**)&swapChainBackgroundPanelNative
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (NULL != swapChainBackgroundPanelNative)
|
|
{
|
|
// Remove swap chain
|
|
hr = swapChainBackgroundPanelNative->SetSwapChain(NULL);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DX_RELEASE(swapChainBackgroundPanelNative, 0);
|
|
BX_TRACE("Failed to SetSwapChain, hr %x.");
|
|
return hr;
|
|
}
|
|
|
|
DX_RELEASE_I(swapChainBackgroundPanelNative);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void Dxgi::updateHdr10(SwapChainI* _swapChain, const SwapChainDesc& _scd)
|
|
{
|
|
#if BX_PLATFORM_WINDOWS
|
|
::IDXGISwapChain4* swapChain4;
|
|
HRESULT hr = _swapChain->QueryInterface(IID_IDXGISwapChain4, (void**)&swapChain4);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
const DXGI_COLOR_SPACE_TYPE colorSpace =
|
|
_scd.format == DXGI_FORMAT_R10G10B10A2_UNORM ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
|
|
: _scd.format == DXGI_FORMAT_R16G16B16A16_FLOAT ? DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
|
|
: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
|
|
;
|
|
|
|
hr = swapChain4->SetColorSpace1(colorSpace);
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
DXGI_OUTPUT_DESC1 desc;
|
|
|
|
IDXGIOutput* output;
|
|
hr = _swapChain->GetContainingOutput(&output);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
IDXGIOutput6* output6;
|
|
hr = output->QueryInterface(IID_IDXGIOutput6, (void**)&output6);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
hr = output6->GetDesc1(&desc);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
BX_TRACE("Display specs:");
|
|
BX_TRACE("\t BitsPerColor: %d", desc.BitsPerColor);
|
|
BX_TRACE("\t Color space: %s (colorspace, range, gamma, sitting, primaries, transform)"
|
|
, s_colorSpaceStr[bx::min<uint32_t>(desc.ColorSpace, kDxgiLastColorSpace+1)]
|
|
);
|
|
BX_TRACE("\t RedPrimary: %f, %f", desc.RedPrimary[0], desc.RedPrimary[1]);
|
|
BX_TRACE("\t GreenPrimary: %f, %f", desc.GreenPrimary[0], desc.GreenPrimary[1]);
|
|
BX_TRACE("\t BluePrimary: %f, %f", desc.BluePrimary[0], desc.BluePrimary[1]);
|
|
BX_TRACE("\t WhitePoint: %f, %f", desc.WhitePoint[0], desc.WhitePoint[1]);
|
|
BX_TRACE("\t MinLuminance: %f", desc.MinLuminance);
|
|
BX_TRACE("\t MaxLuminance: %f", desc.MaxLuminance);
|
|
BX_TRACE("\tMaxFullFrameLuminance: %f", desc.MaxFullFrameLuminance);
|
|
}
|
|
|
|
DX_RELEASE(output6, 1);
|
|
}
|
|
|
|
DX_RELEASE(output, 0);
|
|
}
|
|
|
|
DXGI_HDR_METADATA_HDR10 hdr10;
|
|
hdr10.RedPrimary[0] = uint16_t(desc.RedPrimary[0] * 50000.0f);
|
|
hdr10.RedPrimary[1] = uint16_t(desc.RedPrimary[1] * 50000.0f);
|
|
hdr10.GreenPrimary[0] = uint16_t(desc.GreenPrimary[0] * 50000.0f);
|
|
hdr10.GreenPrimary[1] = uint16_t(desc.GreenPrimary[1] * 50000.0f);
|
|
hdr10.BluePrimary[0] = uint16_t(desc.BluePrimary[0] * 50000.0f);
|
|
hdr10.BluePrimary[1] = uint16_t(desc.BluePrimary[1] * 50000.0f);
|
|
hdr10.WhitePoint[0] = uint16_t(desc.WhitePoint[0] * 50000.0f);
|
|
hdr10.WhitePoint[1] = uint16_t(desc.WhitePoint[1] * 50000.0f);
|
|
hdr10.MaxMasteringLuminance = uint32_t(desc.MaxLuminance * 10000.0f);
|
|
hdr10.MinMasteringLuminance = uint32_t(desc.MinLuminance * 10000.0f);
|
|
hdr10.MaxContentLightLevel = uint16_t(desc.MaxFullFrameLuminance);
|
|
hdr10.MaxFrameAverageLightLevel = uint16_t(desc.MaxFullFrameLuminance);
|
|
hr = swapChain4->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(DXGI_HDR_METADATA_HDR10), &hdr10);
|
|
}
|
|
|
|
DX_RELEASE(swapChain4, 1);
|
|
}
|
|
#else
|
|
BX_UNUSED(_swapChain, _scd);
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
}
|
|
|
|
HRESULT Dxgi::resizeBuffers(SwapChainI* _swapChain, const SwapChainDesc& _scd, const uint32_t* _nodeMask, IUnknown* const* _presentQueue)
|
|
{
|
|
HRESULT hr;
|
|
|
|
uint32_t scdFlags = _scd.flags;
|
|
|
|
#if BX_PLATFORM_WINDOWS
|
|
IDXGIFactory5* factory5;
|
|
hr = m_factory->QueryInterface(IID_IDXGIFactory5, (void**)&factory5);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BOOL allowTearing = false;
|
|
// BK - CheckFeatureSupport with DXGI_FEATURE_PRESENT_ALLOW_TEARING
|
|
// will crash on pre Windows 8. Issue #1356.
|
|
hr = factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing));
|
|
BX_TRACE("Allow tearing is %ssupported.", allowTearing ? "" : "not ");
|
|
|
|
scdFlags |= allowTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
|
scdFlags |= false
|
|
|| _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
|
|
|| _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD
|
|
? 0 // DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
|
|
: 0
|
|
;
|
|
|
|
DX_RELEASE_I(factory5);
|
|
}
|
|
|
|
if (NULL != _nodeMask
|
|
&& NULL != _presentQueue)
|
|
{
|
|
hr = _swapChain->ResizeBuffers1(
|
|
_scd.bufferCount
|
|
, _scd.width
|
|
, _scd.height
|
|
, _scd.format
|
|
, scdFlags
|
|
, _nodeMask
|
|
, _presentQueue
|
|
);
|
|
}
|
|
else
|
|
#endif // BX_PLATFORM_WINDOWS
|
|
{
|
|
BX_UNUSED(_nodeMask, _presentQueue);
|
|
|
|
hr = _swapChain->ResizeBuffers(
|
|
_scd.bufferCount
|
|
, _scd.width
|
|
, _scd.height
|
|
, _scd.format
|
|
, scdFlags
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
updateHdr10(_swapChain, _scd);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void Dxgi::trim()
|
|
{
|
|
#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
|
|
IDXGIDevice3* device;
|
|
HRESULT hr = m_factory->QueryInterface(IID_IDXGIDevice3, (void**)&device);
|
|
if (SUCCEEDED(hr) )
|
|
{
|
|
device->Trim();
|
|
DX_RELEASE(device, 1);
|
|
}
|
|
#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
|
|
}
|
|
|
|
bool Dxgi::tearingSupported() const
|
|
{
|
|
return m_tearingSupported;
|
|
}
|
|
|
|
} // namespace bgfx
|
|
|
|
#endif // BGFX_CONFIG_RENDERER_DIRECT3D11 || BGFX_CONFIG_RENDERER_DIRECT3D12
|