Added graceful error handling during initialization.

This commit is contained in:
Branimir Karadžić 2015-07-30 18:36:12 -07:00
parent 8adc099b02
commit 5f59978e6b
7 changed files with 816 additions and 450 deletions

View file

@ -432,7 +432,7 @@ BGFX_C_API uint8_t bgfx_get_supported_renderers(bgfx_renderer_type_t _enum[BGFX_
BGFX_C_API const char* bgfx_get_renderer_name(bgfx_renderer_type_t _type); BGFX_C_API const char* bgfx_get_renderer_name(bgfx_renderer_type_t _type);
/**/ /**/
BGFX_C_API void bgfx_init(bgfx_renderer_type_t _type, uint16_t _vendorId, uint16_t _deviceId, bgfx_callback_interface_t* _callback, bgfx_reallocator_interface_t* _allocator); BGFX_C_API bool bgfx_init(bgfx_renderer_type_t _type, uint16_t _vendorId, uint16_t _deviceId, bgfx_callback_interface_t* _callback, bgfx_reallocator_interface_t* _allocator);
/**/ /**/
BGFX_C_API void bgfx_shutdown(); BGFX_C_API void bgfx_shutdown();

View file

@ -709,9 +709,11 @@ namespace bgfx
/// specified, library uses default CRT allocator. The library assumes /// specified, library uses default CRT allocator. The library assumes
/// icustom allocator is thread safe. /// icustom allocator is thread safe.
/// ///
/// @returns `true` if initialization is sucessful.
///
/// @attention C99 equivalent is `bgfx_init`. /// @attention C99 equivalent is `bgfx_init`.
/// ///
void init(RendererType::Enum _type = RendererType::Count, uint16_t _vendorId = BGFX_PCI_ID_NONE, uint16_t _deviceId = 0, CallbackI* _callback = NULL, bx::ReallocatorI* _reallocator = NULL); bool init(RendererType::Enum _type = RendererType::Count, uint16_t _vendorId = BGFX_PCI_ID_NONE, uint16_t _deviceId = 0, CallbackI* _callback = NULL, bx::ReallocatorI* _reallocator = NULL);
/// Shutdown bgfx library. /// Shutdown bgfx library.
/// ///

View file

@ -915,7 +915,7 @@ namespace bgfx
TextureFormat::RGBA8, // D3D9 doesn't support RGBA8 TextureFormat::RGBA8, // D3D9 doesn't support RGBA8
}; };
void Context::init(RendererType::Enum _type) bool Context::init(RendererType::Enum _type)
{ {
BX_CHECK(!m_rendererInitialized, "Already initialized?"); BX_CHECK(!m_rendererInitialized, "Already initialized?");
@ -990,6 +990,19 @@ namespace bgfx
// g_caps is initialized and available after this point. // g_caps is initialized and available after this point.
frame(); frame();
if (!m_rendererInitialized)
{
getCommandBuffer(CommandBuffer::RendererShutdownEnd);
frame();
frame();
m_declRef.shutdown(m_vertexDeclHandle);
m_submit->destroy();
#if BGFX_CONFIG_MULTITHREADED
m_render->destroy();
#endif // BGFX_CONFIG_MULTITHREADED
return false;
}
for (uint32_t ii = 0; ii < BX_COUNTOF(s_emulatedFormats); ++ii) for (uint32_t ii = 0; ii < BX_COUNTOF(s_emulatedFormats); ++ii)
{ {
if (0 == (g_caps.formats[s_emulatedFormats[ii] ] & BGFX_CAPS_FORMAT_TEXTURE_COLOR) ) if (0 == (g_caps.formats[s_emulatedFormats[ii] ] & BGFX_CAPS_FORMAT_TEXTURE_COLOR) )
@ -1020,6 +1033,8 @@ namespace bgfx
m_submit->m_transientIb = createTransientIndexBuffer(BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE); m_submit->m_transientIb = createTransientIndexBuffer(BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE);
frame(); frame();
} }
return true;
} }
void Context::shutdown() void Context::shutdown()
@ -1370,7 +1385,7 @@ namespace bgfx
bool supported; bool supported;
}; };
static const RendererCreator s_rendererCreator[] = static RendererCreator s_rendererCreator[] =
{ {
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NULL_NAME, !!BGFX_CONFIG_RENDERER_NULL }, // Noop { noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NULL_NAME, !!BGFX_CONFIG_RENDERER_NULL }, // Noop
{ d3d9::rendererCreate, d3d9::rendererDestroy, BGFX_RENDERER_DIRECT3D9_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D9 }, // Direct3D9 { d3d9::rendererCreate, d3d9::rendererDestroy, BGFX_RENDERER_DIRECT3D9_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D9 }, // Direct3D9
@ -1467,10 +1482,18 @@ again:
{ {
_type = RendererType::OpenGLES; _type = RendererType::OpenGLES;
} }
else if (s_rendererCreator[RendererType::Direct3D12].supported)
{
_type = RendererType::Direct3D12;
}
else if (s_rendererCreator[RendererType::Vulkan].supported) else if (s_rendererCreator[RendererType::Vulkan].supported)
{ {
_type = RendererType::Vulkan; _type = RendererType::Vulkan;
} }
else
{
_type = RendererType::Null;
}
} }
else if (BX_ENABLED(0 else if (BX_ENABLED(0
|| BX_PLATFORM_ANDROID || BX_PLATFORM_ANDROID
@ -1508,6 +1531,7 @@ again:
if (NULL == renderCtx) if (NULL == renderCtx)
{ {
s_rendererCreator[_type].supported = false;
goto again; goto again;
} }
@ -1532,8 +1556,20 @@ again:
uint8_t command; uint8_t command;
_cmdbuf.read(command); _cmdbuf.read(command);
switch (command)
{
case CommandBuffer::RendererShutdownEnd:
m_exit = true;
return;
case CommandBuffer::End:
return;
default:
{
BX_CHECK(CommandBuffer::RendererInit == command BX_CHECK(CommandBuffer::RendererInit == command
, "RendererInit must be the first command in command buffer before initialization." , "RendererInit must be the first command in command buffer before initialization. Unexpected command %d?"
, command
); );
BX_CHECK(!m_rendererInitialized, "This shouldn't happen! Bad synchronization?"); BX_CHECK(!m_rendererInitialized, "This shouldn't happen! Bad synchronization?");
@ -1541,10 +1577,20 @@ again:
_cmdbuf.read(type); _cmdbuf.read(type);
m_renderCtx = rendererCreate(type); m_renderCtx = rendererCreate(type);
m_rendererInitialized = true; m_rendererInitialized = NULL != m_renderCtx;
}
BX_CHECK(NULL != m_renderCtx, "Should not be NULL at this point."); if (!m_rendererInitialized)
{
_cmdbuf.read(command);
BX_CHECK(CommandBuffer::End == command, "Unexpected command %d?"
, command
);
return;
}
}
break;
}
}
do do
{ {
@ -2015,7 +2061,7 @@ again:
return s_rendererCreator[_type].name; return s_rendererCreator[_type].name;
} }
void init(RendererType::Enum _type, uint16_t _vendorId, uint16_t _deviceId, CallbackI* _callback, bx::ReallocatorI* _allocator) bool init(RendererType::Enum _type, uint16_t _vendorId, uint16_t _deviceId, CallbackI* _callback, bx::ReallocatorI* _allocator)
{ {
BX_CHECK(NULL == s_ctx, "bgfx is already initialized."); BX_CHECK(NULL == s_ctx, "bgfx is already initialized.");
@ -2050,9 +2096,36 @@ again:
BX_TRACE("Init..."); BX_TRACE("Init...");
s_ctx = BX_ALIGNED_NEW(g_allocator, Context, 16); s_ctx = BX_ALIGNED_NEW(g_allocator, Context, 16);
s_ctx->init(_type); if (!s_ctx->init(_type) )
{
BX_TRACE("Init failed.");
BX_ALIGNED_DELETE(g_allocator, s_ctx, 16);
s_ctx = NULL;
if (NULL != s_callbackStub)
{
BX_DELETE(g_allocator, s_callbackStub);
s_callbackStub = NULL;
}
if (NULL != s_allocatorStub)
{
// s_allocatorStub->checkLeaks();
bx::CrtAllocator allocator;
BX_DELETE(&allocator, s_allocatorStub);
s_allocatorStub = NULL;
}
s_threadIndex = 0;
g_callback = NULL;
g_allocator = NULL;
return false;
}
BX_TRACE("Init complete."); BX_TRACE("Init complete.");
return true;
} }
void shutdown() void shutdown()
@ -3243,7 +3316,7 @@ BGFX_C_API const char* bgfx_get_renderer_name(bgfx_renderer_type_t _type)
return bgfx::getRendererName(bgfx::RendererType::Enum(_type) ); return bgfx::getRendererName(bgfx::RendererType::Enum(_type) );
} }
BGFX_C_API void bgfx_init(bgfx_renderer_type_t _type, uint16_t _vendorId, uint16_t _deviceId, bgfx_callback_interface_t* _callback, bgfx_reallocator_interface_t* _allocator) BGFX_C_API bool bgfx_init(bgfx_renderer_type_t _type, uint16_t _vendorId, uint16_t _deviceId, bgfx_callback_interface_t* _callback, bgfx_reallocator_interface_t* _allocator)
{ {
static bgfx::CallbackC99 s_callback; static bgfx::CallbackC99 s_callback;
s_callback.m_interface = _callback; s_callback.m_interface = _callback;

View file

@ -1929,7 +1929,7 @@ namespace bgfx
} }
// game thread // game thread
void init(RendererType::Enum _type); bool init(RendererType::Enum _type);
void shutdown(); void shutdown();
CommandBuffer& getCommandBuffer(CommandBuffer::Enum _cmd) CommandBuffer& getCommandBuffer(CommandBuffer::Enum _cmd)

View file

@ -489,8 +489,10 @@ namespace bgfx { namespace d3d11
{ {
} }
void init() bool init()
{ {
uint32_t errorState = 0;
// Must be before device creation, and before RenderDoc. // Must be before device creation, and before RenderDoc.
m_ovr.init(); m_ovr.init();
@ -505,7 +507,14 @@ namespace bgfx { namespace d3d11
#if USE_D3D11_DYNAMIC_LIB #if USE_D3D11_DYNAMIC_LIB
m_d3d11dll = bx::dlopen("d3d11.dll"); m_d3d11dll = bx::dlopen("d3d11.dll");
BGFX_FATAL(NULL != m_d3d11dll, Fatal::UnableToInitialize, "Failed to load d3d11.dll."); BX_WARN(NULL != m_d3d11dll, "Failed to load d3d11.dll.");
if (NULL == m_d3d11dll)
{
goto error;
}
errorState = 1;
m_d3d9dll = NULL; m_d3d9dll = NULL;
@ -514,8 +523,8 @@ namespace bgfx { namespace d3d11
// D3D11_1.h has ID3DUserDefinedAnnotation // D3D11_1.h has ID3DUserDefinedAnnotation
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh446881%28v=vs.85%29.aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/hh446881%28v=vs.85%29.aspx
m_d3d9dll = bx::dlopen("d3d9.dll"); m_d3d9dll = bx::dlopen("d3d9.dll");
BGFX_FATAL(NULL != m_d3d9dll, Fatal::UnableToInitialize, "Failed to load d3d9.dll."); if (NULL != m_d3d9dll)
{
D3DPERF_SetMarker = (PFN_D3DPERF_SET_MARKER )bx::dlsym(m_d3d9dll, "D3DPERF_SetMarker" ); D3DPERF_SetMarker = (PFN_D3DPERF_SET_MARKER )bx::dlsym(m_d3d9dll, "D3DPERF_SetMarker" );
D3DPERF_BeginEvent = (PFN_D3DPERF_BEGIN_EVENT)bx::dlsym(m_d3d9dll, "D3DPERF_BeginEvent"); D3DPERF_BeginEvent = (PFN_D3DPERF_BEGIN_EVENT)bx::dlsym(m_d3d9dll, "D3DPERF_BeginEvent");
D3DPERF_EndEvent = (PFN_D3DPERF_END_EVENT )bx::dlsym(m_d3d9dll, "D3DPERF_EndEvent" ); D3DPERF_EndEvent = (PFN_D3DPERF_END_EVENT )bx::dlsym(m_d3d9dll, "D3DPERF_EndEvent" );
@ -525,15 +534,30 @@ namespace bgfx { namespace d3d11
, "Failed to initialize PIX events." , "Failed to initialize PIX events."
); );
} }
}
D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)bx::dlsym(m_d3d11dll, "D3D11CreateDevice"); D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)bx::dlsym(m_d3d11dll, "D3D11CreateDevice");
BGFX_FATAL(NULL != D3D11CreateDevice, Fatal::UnableToInitialize, "Function D3D11CreateDevice not found."); BX_WARN(NULL != D3D11CreateDevice, "Function D3D11CreateDevice not found.");
if (NULL == D3D11CreateDevice)
{
goto error;
}
m_dxgidll = bx::dlopen("dxgi.dll"); m_dxgidll = bx::dlopen("dxgi.dll");
BGFX_FATAL(NULL != m_dxgidll, Fatal::UnableToInitialize, "Failed to load dxgi.dll."); BX_WARN(NULL != m_dxgidll, "Failed to load dxgi.dll.");
if (NULL == m_dxgidll)
{
goto error;
}
errorState = 2;
CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgidll, "CreateDXGIFactory"); CreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgidll, "CreateDXGIFactory");
BGFX_FATAL(NULL != CreateDXGIFactory, Fatal::UnableToInitialize, "Function CreateDXGIFactory not found."); BX_WARN(NULL != CreateDXGIFactory, "Function CreateDXGIFactory not found.");
if (NULL == CreateDXGIFactory)
{
goto error;
}
m_dxgidebugdll = bx::dlopen("dxgidebug.dll"); m_dxgidebugdll = bx::dlopen("dxgidebug.dll");
if (NULL != m_dxgidebugdll) if (NULL != m_dxgidebugdll)
@ -558,11 +582,16 @@ namespace bgfx { namespace d3d11
#if BX_PLATFORM_WINRT #if BX_PLATFORM_WINRT
// WinRT requires the IDXGIFactory2 interface, which isn't supported on older platforms // WinRT requires the IDXGIFactory2 interface, which isn't supported on older platforms
hr = CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&factory); hr = CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&factory);
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create DXGI factory.");
#else #else
hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)&factory); hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)&factory);
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create DXGI factory.");
#endif // BX_PLATFORM_WINRT #endif // BX_PLATFORM_WINRT
BX_WARN(SUCCEEDED(hr), "Unable to create DXGI factory.");
if (FAILED(hr) )
{
goto error;
}
errorState = 3;
m_device = (ID3D11Device*)g_platformData.context; m_device = (ID3D11Device*)g_platformData.context;
@ -686,7 +715,14 @@ namespace bgfx { namespace d3d11
break; break;
} }
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 device.");
if (FAILED(hr) )
{
goto error;
}
errorState = 4;
if (NULL != m_adapter) if (NULL != m_adapter)
{ {
@ -696,7 +732,14 @@ namespace bgfx { namespace d3d11
else else
{ {
m_device->GetImmediateContext(&m_deviceCtx); m_device->GetImmediateContext(&m_deviceCtx);
BGFX_FATAL(NULL != m_deviceCtx, Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); BX_WARN(NULL != m_deviceCtx, "Unable to create Direct3D11 device.");
if (NULL == m_deviceCtx)
{
goto error;
}
errorState = 4;
} }
IDXGIDevice* device = NULL; IDXGIDevice* device = NULL;
@ -729,7 +772,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
#endif // BX_COMPILER_MSVC #endif // BX_COMPILER_MSVC
} }
} }
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 device.");
if (FAILED(hr) )
{
goto error;
}
// GPA increases device ref count. // GPA increases device ref count.
// RenderDoc makes device ref count 0 here. // RenderDoc makes device ref count 0 here.
@ -750,7 +797,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
} }
hr = adapter->GetDesc(&m_adapterDesc); hr = adapter->GetDesc(&m_adapterDesc);
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 device.");
if (FAILED(hr) )
{
DX_RELEASE(adapter, 2);
goto error;
}
g_caps.vendorId = 0 == m_adapterDesc.VendorId g_caps.vendorId = 0 == m_adapterDesc.VendorId
? BGFX_PCI_ID_SOFTWARE_RASTERIZER ? BGFX_PCI_ID_SOFTWARE_RASTERIZER
: (uint16_t)m_adapterDesc.VendorId : (uint16_t)m_adapterDesc.VendorId
@ -761,8 +814,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{ {
#if BX_PLATFORM_WINRT #if BX_PLATFORM_WINRT
hr = adapter->GetParent(__uuidof(IDXGIFactory2), (void**)&m_factory); hr = adapter->GetParent(__uuidof(IDXGIFactory2), (void**)&m_factory);
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 device.");
DX_RELEASE(adapter, 2); DX_RELEASE(adapter, 2);
if (FAILED(hr) )
{
goto error;
}
memset(&m_scd, 0, sizeof(m_scd) ); memset(&m_scd, 0, sizeof(m_scd) );
m_scd.Width = BGFX_DEFAULT_WIDTH; m_scd.Width = BGFX_DEFAULT_WIDTH;
@ -783,11 +840,14 @@ BX_PRAGMA_DIAGNOSTIC_POP();
, NULL , NULL
, &m_swapChain , &m_swapChain
); );
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain.");
#else #else
hr = adapter->GetParent(IID_IDXGIFactory, (void**)&m_factory); hr = adapter->GetParent(IID_IDXGIFactory, (void**)&m_factory);
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D11 device.");
DX_RELEASE(adapter, 2); DX_RELEASE(adapter, 2);
if (FAILED(hr) )
{
goto error;
}
memset(&m_scd, 0, sizeof(m_scd) ); memset(&m_scd, 0, sizeof(m_scd) );
m_scd.BufferDesc.Width = BGFX_DEFAULT_WIDTH; m_scd.BufferDesc.Width = BGFX_DEFAULT_WIDTH;
@ -806,13 +866,19 @@ BX_PRAGMA_DIAGNOSTIC_POP();
, &m_scd , &m_scd
, &m_swapChain , &m_swapChain
); );
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain.");
DX_CHECK(m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh, 0 DX_CHECK(m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh, 0
| DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_WINDOW_CHANGES
| DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_ALT_ENTER
) ); ) );
#endif // BX_PLATFORM_WINRT #endif // BX_PLATFORM_WINRT
BX_WARN(SUCCEEDED(hr), "Failed to create swap chain.");
if (FAILED(hr) )
{
goto error;
}
errorState = 5;
} }
else else
{ {
@ -853,6 +919,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
} }
} }
#endif // __MINGW__ #endif // __MINGW__
{
UniformHandle handle = BGFX_INVALID_HANDLE; UniformHandle handle = BGFX_INVALID_HANDLE;
for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii) for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii)
@ -1091,6 +1158,55 @@ BX_PRAGMA_DIAGNOSTIC_POP();
postReset(); postReset();
} }
return true;
error:
switch (errorState)
{
default:
case 5:
DX_RELEASE(m_swapChain, 0);
case 4:
DX_RELEASE(m_deviceCtx, 0);
DX_RELEASE(m_device, 0);
case 3:
DX_RELEASE(m_factory, 0);
case 2:
#if USE_D3D11_DYNAMIC_LIB
if (NULL != m_dxgidebugdll)
{
bx::dlclose(m_dxgidebugdll);
m_dxgidebugdll = NULL;
}
if (NULL != m_d3d9dll)
{
bx::dlclose(m_d3d9dll);
m_d3d9dll = NULL;
}
bx::dlclose(m_dxgidll);
m_dxgidll = NULL;
#endif // USE_D3D11_DYNAMIC_LIB
case 1:
#if USE_D3D11_DYNAMIC_LIB
bx::dlclose(m_d3d11dll);
m_d3d11dll = NULL;
#endif // USE_D3D11_DYNAMIC_LIB
case 0:
unloadRenderDoc(m_renderdocdll);
m_ovr.shutdown();
break;
}
return false;
}
void shutdown() void shutdown()
{ {
preReset(); preReset();
@ -1134,11 +1250,14 @@ BX_PRAGMA_DIAGNOSTIC_POP();
m_dxgidebugdll = NULL; m_dxgidebugdll = NULL;
} }
bx::dlclose(m_dxgidll); if (NULL != m_d3d9dll)
m_dxgidll = NULL; {
bx::dlclose(m_d3d9dll); bx::dlclose(m_d3d9dll);
m_d3d9dll = NULL; m_d3d9dll = NULL;
}
bx::dlclose(m_dxgidll);
m_dxgidll = NULL;
bx::dlclose(m_d3d11dll); bx::dlclose(m_d3d11dll);
m_d3d11dll = NULL; m_d3d11dll = NULL;
@ -2735,7 +2854,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
RendererContextI* rendererCreate() RendererContextI* rendererCreate()
{ {
s_renderD3D11 = BX_NEW(g_allocator, RendererContextD3D11); s_renderD3D11 = BX_NEW(g_allocator, RendererContextD3D11);
s_renderD3D11->init(); if (!s_renderD3D11->init() )
{
BX_DELETE(g_allocator, s_renderD3D11);
s_renderD3D11 = NULL;
}
return s_renderD3D11; return s_renderD3D11;
} }

View file

@ -413,36 +413,77 @@ namespace bgfx { namespace d3d12
{ {
} }
void init() ~RendererContextD3D12()
{ {
}
bool init()
{
uint32_t errorState = 0;
LUID luid;
m_fbh.idx = invalidHandle; m_fbh.idx = invalidHandle;
memset(m_uniforms, 0, sizeof(m_uniforms) ); memset(m_uniforms, 0, sizeof(m_uniforms) );
memset(&m_resolution, 0, sizeof(m_resolution) ); memset(&m_resolution, 0, sizeof(m_resolution) );
#if USE_D3D12_DYNAMIC_LIB #if USE_D3D12_DYNAMIC_LIB
m_d3d12dll = bx::dlopen("d3d12.dll"); m_d3d12dll = bx::dlopen("d3d12.dll");
BGFX_FATAL(NULL != m_d3d12dll, Fatal::UnableToInitialize, "Failed to load d3d12.dll."); BX_WARN(NULL != m_d3d12dll, "Failed to load d3d12.dll.");
if (NULL == m_d3d12dll)
{
goto error;
}
errorState = 1;
D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)bx::dlsym(m_d3d12dll, "D3D12CreateDevice"); D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)bx::dlsym(m_d3d12dll, "D3D12CreateDevice");
BGFX_FATAL(NULL != D3D12CreateDevice, Fatal::UnableToInitialize, "Function D3D12CreateDevice not found."); BX_WARN(NULL != D3D12CreateDevice, "Function D3D12CreateDevice not found.");
D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)bx::dlsym(m_d3d12dll, "D3D12GetDebugInterface"); D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)bx::dlsym(m_d3d12dll, "D3D12GetDebugInterface");
BGFX_FATAL(NULL != D3D12GetDebugInterface, Fatal::UnableToInitialize, "Function D3D12GetDebugInterface not found."); BX_WARN(NULL != D3D12GetDebugInterface, "Function D3D12GetDebugInterface not found.");
D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)bx::dlsym(m_d3d12dll, "D3D12SerializeRootSignature"); D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)bx::dlsym(m_d3d12dll, "D3D12SerializeRootSignature");
BGFX_FATAL(NULL != D3D12SerializeRootSignature, Fatal::UnableToInitialize, "Function D3D12SerializeRootSignature not found."); BX_WARN(NULL != D3D12SerializeRootSignature, "Function D3D12SerializeRootSignature not found.");
if (NULL == D3D12CreateDevice
|| NULL == D3D12GetDebugInterface
|| NULL == D3D12SerializeRootSignature)
{
goto error;
}
m_dxgidll = bx::dlopen("dxgi.dll"); m_dxgidll = bx::dlopen("dxgi.dll");
BGFX_FATAL(NULL != m_dxgidll, Fatal::UnableToInitialize, "Failed to load dxgi.dll."); BX_WARN(NULL != m_dxgidll, "Failed to load dxgi.dll.");
if (NULL == m_dxgidll)
{
goto error;
}
errorState = 2;
CreateDXGIFactory1 = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgidll, "CreateDXGIFactory1"); CreateDXGIFactory1 = (PFN_CREATE_DXGI_FACTORY)bx::dlsym(m_dxgidll, "CreateDXGIFactory1");
BGFX_FATAL(NULL != CreateDXGIFactory1, Fatal::UnableToInitialize, "Function CreateDXGIFactory1 not found."); BX_WARN(NULL != CreateDXGIFactory1, "Function CreateDXGIFactory1 not found.");
if (NULL == CreateDXGIFactory1)
{
goto error;
}
#else
errorState = 2;
#endif // USE_D3D12_DYNAMIC_LIB #endif // USE_D3D12_DYNAMIC_LIB
HRESULT hr; HRESULT hr;
hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)&m_factory); hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)&m_factory);
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create DXGI factory."); BX_WARN(SUCCEEDED(hr), "Unable to create DXGI factory.");
if (FAILED(hr) )
{
goto error;
}
errorState = 3;
m_adapter = NULL; m_adapter = NULL;
m_driverType = D3D_DRIVER_TYPE_HARDWARE; m_driverType = D3D_DRIVER_TYPE_HARDWARE;
@ -511,15 +552,22 @@ namespace bgfx { namespace d3d12
, __uuidof(ID3D12Device) , __uuidof(ID3D12Device)
, (void**)&m_device , (void**)&m_device
); );
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D12 device."); BX_WARN(SUCCEEDED(hr), "Unable to create Direct3D12 device.");
if (NULL != m_adapter) if (NULL != m_adapter)
{ {
DX_RELEASE(m_adapter, 2); DX_RELEASE(m_adapter, 2);
} }
if (FAILED(hr) )
{
goto error;
}
errorState = 4;
memset(&m_adapterDesc, 0, sizeof(m_adapterDesc) ); memset(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
LUID luid = m_device->GetAdapterLuid(); luid = m_device->GetAdapterLuid();
for (uint32_t ii = 0; DXGI_ERROR_NOT_FOUND != m_factory->EnumAdapters(ii, &adapter); ++ii) for (uint32_t ii = 0; DXGI_ERROR_NOT_FOUND != m_factory->EnumAdapters(ii, &adapter); ++ii)
{ {
adapter->GetDesc(&m_adapterDesc); adapter->GetDesc(&m_adapterDesc);
@ -569,7 +617,13 @@ namespace bgfx { namespace d3d12
, &m_scd , &m_scd
, &m_swapChain , &m_swapChain
); );
BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); BX_WARN(SUCCEEDED(hr), "Failed to create swap chain.");
if (FAILED(hr) )
{
goto error;
}
{
m_resolution.m_width = BGFX_DEFAULT_WIDTH; m_resolution.m_width = BGFX_DEFAULT_WIDTH;
m_resolution.m_height = BGFX_DEFAULT_HEIGHT; m_resolution.m_height = BGFX_DEFAULT_HEIGHT;
@ -767,8 +821,31 @@ namespace bgfx { namespace d3d12
postReset(); postReset();
} }
return true;
~RendererContextD3D12() error:
switch (errorState)
{
default:
case 4:
m_cmd.shutdown();
DX_RELEASE(m_device, 0);
case 3:
DX_RELEASE(m_factory, 0);
#if USE_D3D12_DYNAMIC_LIB
case 2:
bx::dlclose(m_dxgidll);
case 1:
bx::dlclose(m_d3d12dll);
#endif // USE_D3D12_DYNAMIC_LIB
case 0:
break;
}
return false;
}
void shutdown()
{ {
preReset(); preReset();
@ -811,6 +888,7 @@ namespace bgfx { namespace d3d12
m_cmd.shutdown(); m_cmd.shutdown();
DX_RELEASE(m_device, 0); DX_RELEASE(m_device, 0);
DX_RELEASE(m_factory, 0);
#if USE_D3D12_DYNAMIC_LIB #if USE_D3D12_DYNAMIC_LIB
bx::dlclose(m_d3d12dll); bx::dlclose(m_d3d12dll);
@ -2188,12 +2266,17 @@ data.NumQualityLevels = 0;
RendererContextI* rendererCreate() RendererContextI* rendererCreate()
{ {
s_renderD3D12 = BX_NEW(g_allocator, RendererContextD3D12); s_renderD3D12 = BX_NEW(g_allocator, RendererContextD3D12);
s_renderD3D12->init(); if (!s_renderD3D12->init() )
{
BX_DELETE(g_allocator, s_renderD3D12);
s_renderD3D12 = NULL;
}
return s_renderD3D12; return s_renderD3D12;
} }
void rendererDestroy() void rendererDestroy()
{ {
s_renderD3D12->shutdown();
BX_DELETE(g_allocator, s_renderD3D12); BX_DELETE(g_allocator, s_renderD3D12);
s_renderD3D12 = NULL; s_renderD3D12 = NULL;
} }

View file

@ -291,8 +291,10 @@ namespace bgfx { namespace d3d9
{ {
} }
void init() bool init()
{ {
uint32_t errorState = 0;
m_fbh.idx = invalidHandle; m_fbh.idx = invalidHandle;
memset(m_uniforms, 0, sizeof(m_uniforms) ); memset(m_uniforms, 0, sizeof(m_uniforms) );
memset(&m_resolution, 0, sizeof(m_resolution) ); memset(&m_resolution, 0, sizeof(m_resolution) );
@ -323,7 +325,14 @@ namespace bgfx { namespace d3d9
m_params.BackBufferHeight = rect.bottom-rect.top; m_params.BackBufferHeight = rect.bottom-rect.top;
m_d3d9dll = bx::dlopen("d3d9.dll"); m_d3d9dll = bx::dlopen("d3d9.dll");
BGFX_FATAL(NULL != m_d3d9dll, Fatal::UnableToInitialize, "Failed to load d3d9.dll."); BX_WARN(NULL != m_d3d9dll, "Failed to load d3d9.dll.");
if (NULL == m_d3d9dll)
{
goto error;
}
errorState = 1;
if (BX_ENABLED(BGFX_CONFIG_DEBUG_PIX) ) if (BX_ENABLED(BGFX_CONFIG_DEBUG_PIX) )
{ {
@ -351,12 +360,25 @@ namespace bgfx { namespace d3d9
#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX #endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX
{ {
Direct3DCreate9 = (Direct3DCreate9Fn)bx::dlsym(m_d3d9dll, "Direct3DCreate9"); Direct3DCreate9 = (Direct3DCreate9Fn)bx::dlsym(m_d3d9dll, "Direct3DCreate9");
BGFX_FATAL(NULL != Direct3DCreate9, Fatal::UnableToInitialize, "Function Direct3DCreate9 not found."); BX_WARN(NULL != Direct3DCreate9, "Function Direct3DCreate9 not found.");
if (NULL == Direct3DCreate9)
{
goto error;
}
m_d3d9 = Direct3DCreate9(D3D_SDK_VERSION); m_d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
m_pool = D3DPOOL_MANAGED; m_pool = D3DPOOL_MANAGED;
} }
BGFX_FATAL(m_d3d9, Fatal::UnableToInitialize, "Unable to create Direct3D."); BX_WARN(NULL != m_d3d9, "Unable to create Direct3D.");
if (NULL == m_d3d9)
{
goto error;
}
errorState = 2;
m_adapter = D3DADAPTER_DEFAULT; m_adapter = D3DADAPTER_DEFAULT;
m_deviceType = BGFX_PCI_ID_SOFTWARE_RASTERIZER == g_caps.vendorId m_deviceType = BGFX_PCI_ID_SOFTWARE_RASTERIZER == g_caps.vendorId
@ -442,7 +464,14 @@ namespace bgfx { namespace d3d9
#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX #endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX
} }
BGFX_FATAL(m_device, Fatal::UnableToInitialize, "Unable to create Direct3D9 device."); BX_WARN(NULL != m_device, "Unable to create Direct3D9 device.");
if (NULL == m_device)
{
goto error;
}
errorState = 3;
m_numWindows = 1; m_numWindows = 1;
@ -456,15 +485,23 @@ namespace bgfx { namespace d3d9
DX_CHECK(m_device->GetDeviceCaps(&m_caps) ); DX_CHECK(m_device->GetDeviceCaps(&m_caps) );
// For shit GPUs that can create DX9 device but can't do simple stuff. GTFO! // For shit GPUs that can create DX9 device but can't do simple stuff. GTFO!
BGFX_FATAL( (D3DPTEXTURECAPS_SQUAREONLY & m_caps.TextureCaps) == 0, Fatal::MinimumRequiredSpecs, "D3DPTEXTURECAPS_SQUAREONLY"); BX_WARN( (D3DPTEXTURECAPS_SQUAREONLY & m_caps.TextureCaps) == 0, "D3DPTEXTURECAPS_SQUAREONLY");
BGFX_FATAL( (D3DPTEXTURECAPS_MIPMAP & m_caps.TextureCaps) == D3DPTEXTURECAPS_MIPMAP, Fatal::MinimumRequiredSpecs, "D3DPTEXTURECAPS_MIPMAP"); BX_WARN( (D3DPTEXTURECAPS_MIPMAP & m_caps.TextureCaps) == D3DPTEXTURECAPS_MIPMAP, "D3DPTEXTURECAPS_MIPMAP");
BGFX_FATAL( (D3DPTEXTURECAPS_ALPHA & m_caps.TextureCaps) == D3DPTEXTURECAPS_ALPHA, Fatal::MinimumRequiredSpecs, "D3DPTEXTURECAPS_ALPHA"); BX_WARN( (D3DPTEXTURECAPS_ALPHA & m_caps.TextureCaps) == D3DPTEXTURECAPS_ALPHA, "D3DPTEXTURECAPS_ALPHA");
BGFX_FATAL(m_caps.VertexShaderVersion >= D3DVS_VERSION(2, 0) && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 1) BX_WARN(m_caps.VertexShaderVersion >= D3DVS_VERSION(2, 0) && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 1)
, Fatal::MinimumRequiredSpecs
, "Shader Model Version (vs: %x, ps: %x)." , "Shader Model Version (vs: %x, ps: %x)."
, m_caps.VertexShaderVersion , m_caps.VertexShaderVersion
, m_caps.PixelShaderVersion , m_caps.PixelShaderVersion
); );
if ( (D3DPTEXTURECAPS_SQUAREONLY & m_caps.TextureCaps) != 0
|| (D3DPTEXTURECAPS_MIPMAP & m_caps.TextureCaps) != D3DPTEXTURECAPS_MIPMAP
|| (D3DPTEXTURECAPS_ALPHA & m_caps.TextureCaps) != D3DPTEXTURECAPS_ALPHA
|| !(m_caps.VertexShaderVersion >= D3DVS_VERSION(2, 0) && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 1) ) )
{
goto error;
}
BX_TRACE("Max vertex shader 3.0 instr. slots: %d", m_caps.MaxVertexShader30InstructionSlots); BX_TRACE("Max vertex shader 3.0 instr. slots: %d", m_caps.MaxVertexShader30InstructionSlots);
BX_TRACE("Max vertex shader constants: %d", m_caps.MaxVertexShaderConst); BX_TRACE("Max vertex shader constants: %d", m_caps.MaxVertexShaderConst);
BX_TRACE("Max fragment shader 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots); BX_TRACE("Max fragment shader 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots);
@ -632,6 +669,50 @@ namespace bgfx { namespace d3d9
postReset(); postReset();
m_initialized = true; m_initialized = true;
return true;
error:
switch (errorState)
{
default:
case 3:
#if BGFX_CONFIG_RENDERER_DIRECT3D9EX
if (NULL != m_d3d9ex)
{
DX_RELEASE(m_deviceEx, 1);
DX_RELEASE(m_device, 0);
}
else
#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX
{
DX_RELEASE(m_device, 0);
}
case 2:
#if BGFX_CONFIG_RENDERER_DIRECT3D9EX
if (NULL != m_d3d9ex)
{
DX_RELEASE(m_d3d9, 1);
DX_RELEASE(m_d3d9ex, 0);
}
else
#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX
{
DX_RELEASE(m_d3d9, 0);
}
#if BX_PLATFORM_WINDOWS
case 1:
bx::dlclose(m_d3d9dll);
#endif // BX_PLATFORM_WINDOWS
case 0:
break;
}
return false;
} }
void shutdown() void shutdown()
@ -1800,7 +1881,11 @@ namespace bgfx { namespace d3d9
RendererContextI* rendererCreate() RendererContextI* rendererCreate()
{ {
s_renderD3D9 = BX_NEW(g_allocator, RendererContextD3D9); s_renderD3D9 = BX_NEW(g_allocator, RendererContextD3D9);
s_renderD3D9->init(); if (!s_renderD3D9->init() )
{
BX_DELETE(g_allocator, s_renderD3D9);
s_renderD3D9 = NULL;
}
return s_renderD3D9; return s_renderD3D9;
} }