diff --git a/include/bgfx.c99.h b/include/bgfx.c99.h index 9193e157..f53db820 100644 --- a/include/bgfx.c99.h +++ b/include/bgfx.c99.h @@ -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 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(); diff --git a/include/bgfx.h b/include/bgfx.h index e018417a..3a960681 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -709,9 +709,11 @@ namespace bgfx /// specified, library uses default CRT allocator. The library assumes /// icustom allocator is thread safe. /// + /// @returns `true` if initialization is sucessful. + /// /// @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. /// diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 90d44132..5f9f76be 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -915,7 +915,7 @@ namespace bgfx 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?"); @@ -990,6 +990,19 @@ namespace bgfx // g_caps is initialized and available after this point. 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) { 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); frame(); } + + return true; } void Context::shutdown() @@ -1370,7 +1385,7 @@ namespace bgfx bool supported; }; - static const RendererCreator s_rendererCreator[] = + static RendererCreator s_rendererCreator[] = { { 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 @@ -1467,10 +1482,18 @@ again: { _type = RendererType::OpenGLES; } + else if (s_rendererCreator[RendererType::Direct3D12].supported) + { + _type = RendererType::Direct3D12; + } else if (s_rendererCreator[RendererType::Vulkan].supported) { _type = RendererType::Vulkan; } + else + { + _type = RendererType::Null; + } } else if (BX_ENABLED(0 || BX_PLATFORM_ANDROID @@ -1508,6 +1531,7 @@ again: if (NULL == renderCtx) { + s_rendererCreator[_type].supported = false; goto again; } @@ -1532,20 +1556,42 @@ again: uint8_t command; _cmdbuf.read(command); - BX_CHECK(CommandBuffer::RendererInit == command - , "RendererInit must be the first command in command buffer before initialization." - ); - BX_CHECK(!m_rendererInitialized, "This shouldn't happen! Bad synchronization?"); + switch (command) + { + case CommandBuffer::RendererShutdownEnd: + m_exit = true; + return; - RendererType::Enum type; - _cmdbuf.read(type); + case CommandBuffer::End: + return; - m_renderCtx = rendererCreate(type); - m_rendererInitialized = true; + default: + { + BX_CHECK(CommandBuffer::RendererInit == command + , "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?"); + + RendererType::Enum type; + _cmdbuf.read(type); + + m_renderCtx = rendererCreate(type); + m_rendererInitialized = NULL != m_renderCtx; + + if (!m_rendererInitialized) + { + _cmdbuf.read(command); + BX_CHECK(CommandBuffer::End == command, "Unexpected command %d?" + , command + ); + return; + } + } + break; + } } - BX_CHECK(NULL != m_renderCtx, "Should not be NULL at this point."); - do { uint8_t command; @@ -2015,7 +2061,7 @@ again: 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."); @@ -2050,9 +2096,36 @@ again: BX_TRACE("Init..."); 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."); + return true; } 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) ); } -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; s_callback.m_interface = _callback; diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 0407cf77..510538f1 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -1929,7 +1929,7 @@ namespace bgfx } // game thread - void init(RendererType::Enum _type); + bool init(RendererType::Enum _type); void shutdown(); CommandBuffer& getCommandBuffer(CommandBuffer::Enum _cmd) diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index bbb575a6..130ba69c 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -489,8 +489,10 @@ namespace bgfx { namespace d3d11 { } - void init() + bool init() { + uint32_t errorState = 0; + // Must be before device creation, and before RenderDoc. m_ovr.init(); @@ -505,7 +507,14 @@ namespace bgfx { namespace d3d11 #if USE_D3D11_DYNAMIC_LIB 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; @@ -514,26 +523,41 @@ namespace bgfx { namespace d3d11 // D3D11_1.h has ID3DUserDefinedAnnotation // http://msdn.microsoft.com/en-us/library/windows/desktop/hh446881%28v=vs.85%29.aspx m_d3d9dll = bx::dlopen("d3d9.dll"); - BGFX_FATAL(NULL != m_d3d9dll, Fatal::UnableToInitialize, "Failed to load d3d9.dll."); - - 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_EndEvent = (PFN_D3DPERF_END_EVENT )bx::dlsym(m_d3d9dll, "D3DPERF_EndEvent" ); - BX_CHECK(NULL != D3DPERF_SetMarker - && NULL != D3DPERF_BeginEvent - && NULL != D3DPERF_EndEvent - , "Failed to initialize PIX events." - ); + if (NULL != m_d3d9dll) + { + 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_EndEvent = (PFN_D3DPERF_END_EVENT )bx::dlsym(m_d3d9dll, "D3DPERF_EndEvent" ); + BX_CHECK(NULL != D3DPERF_SetMarker + && NULL != D3DPERF_BeginEvent + && NULL != D3DPERF_EndEvent + , "Failed to initialize PIX events." + ); + } } 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"); - 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"); - 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"); if (NULL != m_dxgidebugdll) @@ -558,11 +582,16 @@ namespace bgfx { namespace d3d11 #if BX_PLATFORM_WINRT // WinRT requires the IDXGIFactory2 interface, which isn't supported on older platforms hr = CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&factory); - BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create DXGI factory."); #else hr = CreateDXGIFactory(IID_IDXGIFactory, (void**)&factory); - BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create DXGI factory."); #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; @@ -686,7 +715,14 @@ namespace bgfx { namespace d3d11 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) { @@ -696,7 +732,14 @@ namespace bgfx { namespace d3d11 else { 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; @@ -729,7 +772,11 @@ BX_PRAGMA_DIAGNOSTIC_POP(); #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. // RenderDoc makes device ref count 0 here. @@ -750,7 +797,13 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } 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 ? BGFX_PCI_ID_SOFTWARE_RASTERIZER : (uint16_t)m_adapterDesc.VendorId @@ -761,8 +814,12 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { #if BX_PLATFORM_WINRT 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); + if (FAILED(hr) ) + { + goto error; + } memset(&m_scd, 0, sizeof(m_scd) ); m_scd.Width = BGFX_DEFAULT_WIDTH; @@ -783,11 +840,14 @@ BX_PRAGMA_DIAGNOSTIC_POP(); , NULL , &m_swapChain ); - BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); #else 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); + if (FAILED(hr) ) + { + goto error; + } memset(&m_scd, 0, sizeof(m_scd) ); m_scd.BufferDesc.Width = BGFX_DEFAULT_WIDTH; @@ -806,13 +866,19 @@ BX_PRAGMA_DIAGNOSTIC_POP(); , &m_scd , &m_swapChain ); - BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); DX_CHECK(m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh, 0 | DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER ) ); #endif // BX_PLATFORM_WINRT + BX_WARN(SUCCEEDED(hr), "Failed to create swap chain."); + if (FAILED(hr) ) + { + goto error; + } + + errorState = 5; } else { @@ -853,242 +919,292 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } } #endif // __MINGW__ + { - UniformHandle handle = BGFX_INVALID_HANDLE; - for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii) - { - m_uniformReg.add(handle, getPredefinedUniformName(PredefinedUniform::Enum(ii) ), &m_predefinedUniforms[ii]); - } - - g_caps.supported |= (0 - | BGFX_CAPS_TEXTURE_3D - | BGFX_CAPS_VERTEX_ATTRIB_HALF - | BGFX_CAPS_FRAGMENT_DEPTH - | (getIntelExtensions(m_device) ? BGFX_CAPS_FRAGMENT_ORDERING : 0) - | BGFX_CAPS_SWAP_CHAIN - | (m_ovr.isInitialized() ? BGFX_CAPS_HMD : 0) - | BGFX_CAPS_DRAW_INDIRECT - ); - - if (m_featureLevel <= D3D_FEATURE_LEVEL_9_2) - { - g_caps.maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; - g_caps.maxFBAttachments = uint8_t(bx::uint32_min(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); - } - else if (m_featureLevel == D3D_FEATURE_LEVEL_9_3) - { - g_caps.maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; - g_caps.maxFBAttachments = uint8_t(bx::uint32_min(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); - } - else - { - g_caps.supported |= BGFX_CAPS_TEXTURE_COMPARE_ALL; - g_caps.maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; - g_caps.maxFBAttachments = uint8_t(bx::uint32_min(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); - } - - // 32-bit indices only supported on 9_2+. - if (m_featureLevel >= D3D_FEATURE_LEVEL_9_2) - { - g_caps.supported |= BGFX_CAPS_INDEX32; - } - - // Independent blend only supported on 10_1+. - if (m_featureLevel >= D3D_FEATURE_LEVEL_10_1) - { - g_caps.supported |= BGFX_CAPS_BLEND_INDEPENDENT; - } - - // Compute support is optional on 10_0 and 10_1 targets. - if (m_featureLevel == D3D_FEATURE_LEVEL_10_0 - || m_featureLevel == D3D_FEATURE_LEVEL_10_1) - { - struct D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS + UniformHandle handle = BGFX_INVALID_HANDLE; + for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii) { - BOOL ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; - }; + m_uniformReg.add(handle, getPredefinedUniformName(PredefinedUniform::Enum(ii) ), &m_predefinedUniforms[ii]); + } - D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS data; - hr = m_device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &data, sizeof(data) ); - if (SUCCEEDED(hr) - && data.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x) + g_caps.supported |= (0 + | BGFX_CAPS_TEXTURE_3D + | BGFX_CAPS_VERTEX_ATTRIB_HALF + | BGFX_CAPS_FRAGMENT_DEPTH + | (getIntelExtensions(m_device) ? BGFX_CAPS_FRAGMENT_ORDERING : 0) + | BGFX_CAPS_SWAP_CHAIN + | (m_ovr.isInitialized() ? BGFX_CAPS_HMD : 0) + | BGFX_CAPS_DRAW_INDIRECT + ); + + if (m_featureLevel <= D3D_FEATURE_LEVEL_9_2) + { + g_caps.maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + g_caps.maxFBAttachments = uint8_t(bx::uint32_min(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); + } + else if (m_featureLevel == D3D_FEATURE_LEVEL_9_3) + { + g_caps.maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + g_caps.maxFBAttachments = uint8_t(bx::uint32_min(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); + } + else + { + g_caps.supported |= BGFX_CAPS_TEXTURE_COMPARE_ALL; + g_caps.maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + g_caps.maxFBAttachments = uint8_t(bx::uint32_min(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); + } + + // 32-bit indices only supported on 9_2+. + if (m_featureLevel >= D3D_FEATURE_LEVEL_9_2) + { + g_caps.supported |= BGFX_CAPS_INDEX32; + } + + // Independent blend only supported on 10_1+. + if (m_featureLevel >= D3D_FEATURE_LEVEL_10_1) + { + g_caps.supported |= BGFX_CAPS_BLEND_INDEPENDENT; + } + + // Compute support is optional on 10_0 and 10_1 targets. + if (m_featureLevel == D3D_FEATURE_LEVEL_10_0 + || m_featureLevel == D3D_FEATURE_LEVEL_10_1) + { + struct D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS + { + BOOL ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; + }; + + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS data; + hr = m_device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &data, sizeof(data) ); + if (SUCCEEDED(hr) + && data.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x) + { + g_caps.supported |= BGFX_CAPS_COMPUTE; + } + } + else if (m_featureLevel >= D3D_FEATURE_LEVEL_11_0) { g_caps.supported |= BGFX_CAPS_COMPUTE; } - } - else if (m_featureLevel >= D3D_FEATURE_LEVEL_11_0) - { - g_caps.supported |= BGFX_CAPS_COMPUTE; - } - // Instancing fully supported on 9_3+, optionally partially supported at lower levels. - if (m_featureLevel >= D3D_FEATURE_LEVEL_9_3) - { - g_caps.supported |= BGFX_CAPS_INSTANCING; - } - else - { - struct D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT - { - BOOL SimpleInstancingSupported; - }; - - D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT data; - hr = m_device->CheckFeatureSupport(D3D11_FEATURE(11) /*D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT*/, &data, sizeof(data) ); - if (SUCCEEDED(hr) - && data.SimpleInstancingSupported) + // Instancing fully supported on 9_3+, optionally partially supported at lower levels. + if (m_featureLevel >= D3D_FEATURE_LEVEL_9_3) { g_caps.supported |= BGFX_CAPS_INSTANCING; } - } - - // shadow compare is optional on 9_1 through 9_3 targets - if (m_featureLevel <= D3D_FEATURE_LEVEL_9_3) - { - struct D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT + else { - BOOL SupportsDepthAsTextureWithLessEqualComparisonFilter; - }; - - D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT data; - hr = m_device->CheckFeatureSupport(D3D11_FEATURE(9) /*D3D11_FEATURE_D3D9_SHADOW_SUPPORT*/, &data, sizeof(data) ); - if (SUCCEEDED(hr) - && data.SupportsDepthAsTextureWithLessEqualComparisonFilter) - { - g_caps.supported |= BGFX_CAPS_TEXTURE_COMPARE_LEQUAL; - } - } - - for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) - { - uint8_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE; - - const DXGI_FORMAT fmt = isDepth(TextureFormat::Enum(ii) ) - ? s_textureFormat[ii].m_fmtDsv - : s_textureFormat[ii].m_fmt - ; - const DXGI_FORMAT fmtSrgb = s_textureFormat[ii].m_fmtSrgb; - - if (DXGI_FORMAT_UNKNOWN != fmt) - { - struct D3D11_FEATURE_DATA_FORMAT_SUPPORT + struct D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT { - DXGI_FORMAT InFormat; - UINT OutFormatSupport; + BOOL SimpleInstancingSupported; }; - D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2 - data.InFormat = fmt; - hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); - if (SUCCEEDED(hr) ) + D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT data; + hr = m_device->CheckFeatureSupport(D3D11_FEATURE(11) /*D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT*/, &data, sizeof(data) ); + if (SUCCEEDED(hr) + && data.SimpleInstancingSupported) { - support |= 0 != (data.OutFormatSupport & (0 - | D3D11_FORMAT_SUPPORT_TEXTURE2D - | D3D11_FORMAT_SUPPORT_TEXTURE3D - | D3D11_FORMAT_SUPPORT_TEXTURECUBE - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_COLOR - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - - support |= 0 != (data.OutFormatSupport & (0 - | D3D11_FORMAT_SUPPORT_BUFFER - | D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER - | D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_VERTEX - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - - support |= 0 != (data.OutFormatSupport & (0 - | D3D11_FORMAT_SUPPORT_SHADER_LOAD - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - - support |= 0 != (data.OutFormatSupport & (0 - | D3D11_FORMAT_SUPPORT_RENDER_TARGET - | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; + g_caps.supported |= BGFX_CAPS_INSTANCING; } - else + } + + // shadow compare is optional on 9_1 through 9_3 targets + if (m_featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + struct D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT { - BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) ); + BOOL SupportsDepthAsTextureWithLessEqualComparisonFilter; + }; + + D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT data; + hr = m_device->CheckFeatureSupport(D3D11_FEATURE(9) /*D3D11_FEATURE_D3D9_SHADOW_SUPPORT*/, &data, sizeof(data) ); + if (SUCCEEDED(hr) + && data.SupportsDepthAsTextureWithLessEqualComparisonFilter) + { + g_caps.supported |= BGFX_CAPS_TEXTURE_COMPARE_LEQUAL; } + } - if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE) ) + for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) + { + uint8_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE; + + const DXGI_FORMAT fmt = isDepth(TextureFormat::Enum(ii) ) + ? s_textureFormat[ii].m_fmtDsv + : s_textureFormat[ii].m_fmt + ; + const DXGI_FORMAT fmtSrgb = s_textureFormat[ii].m_fmtSrgb; + + if (DXGI_FORMAT_UNKNOWN != fmt) { - // clear image flag for additional testing - support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE; + struct D3D11_FEATURE_DATA_FORMAT_SUPPORT + { + DXGI_FORMAT InFormat; + UINT OutFormatSupport; + }; - data.InFormat = s_textureFormat[ii].m_fmt; - hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) ); + D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2 + data.InFormat = fmt; + hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); if (SUCCEEDED(hr) ) { support |= 0 != (data.OutFormatSupport & (0 - | D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD - | D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE + | D3D11_FORMAT_SUPPORT_TEXTURE2D + | D3D11_FORMAT_SUPPORT_TEXTURE3D + | D3D11_FORMAT_SUPPORT_TEXTURECUBE + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_COLOR + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + support |= 0 != (data.OutFormatSupport & (0 + | D3D11_FORMAT_SUPPORT_BUFFER + | D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER + | D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_VERTEX + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + support |= 0 != (data.OutFormatSupport & (0 + | D3D11_FORMAT_SUPPORT_SHADER_LOAD ) ) ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE : BGFX_CAPS_FORMAT_TEXTURE_NONE ; + + support |= 0 != (data.OutFormatSupport & (0 + | D3D11_FORMAT_SUPPORT_RENDER_TARGET + | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + } + else + { + BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) ); + } + + if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE) ) + { + // clear image flag for additional testing + support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE; + + data.InFormat = s_textureFormat[ii].m_fmt; + hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) ); + if (SUCCEEDED(hr) ) + { + support |= 0 != (data.OutFormatSupport & (0 + | D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD + | D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + } } } + + if (DXGI_FORMAT_UNKNOWN != fmtSrgb) + { + struct D3D11_FEATURE_DATA_FORMAT_SUPPORT + { + DXGI_FORMAT InFormat; + UINT OutFormatSupport; + }; + + D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2 + data.InFormat = fmtSrgb; + hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); + if (SUCCEEDED(hr) ) + { + support |= 0 != (data.OutFormatSupport & (0 + | D3D11_FORMAT_SUPPORT_TEXTURE2D + | D3D11_FORMAT_SUPPORT_TEXTURE3D + | D3D11_FORMAT_SUPPORT_TEXTURECUBE + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_COLOR_SRGB + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + } + else + { + BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) ); + } + } + + g_caps.formats[ii] = support; } - if (DXGI_FORMAT_UNKNOWN != fmtSrgb) + // Init reserved part of view name. + for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) { - struct D3D11_FEATURE_DATA_FORMAT_SUPPORT - { - DXGI_FORMAT InFormat; - UINT OutFormatSupport; - }; - - D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2 - data.InFormat = fmtSrgb; - hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); - if (SUCCEEDED(hr) ) - { - support |= 0 != (data.OutFormatSupport & (0 - | D3D11_FORMAT_SUPPORT_TEXTURE2D - | D3D11_FORMAT_SUPPORT_TEXTURE3D - | D3D11_FORMAT_SUPPORT_TEXTURECUBE - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_COLOR_SRGB - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - } - else - { - BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) ); - } + char name[BGFX_CONFIG_MAX_VIEW_NAME_RESERVED+1]; + bx::snprintf(name, sizeof(name), "%3d ", ii); + mbstowcs(s_viewNameW[ii], name, BGFX_CONFIG_MAX_VIEW_NAME_RESERVED); } - g_caps.formats[ii] = support; + #if !defined(__MINGW32__) + if (BX_ENABLED(BGFX_CONFIG_DEBUG) + && NULL != m_infoQueue) + { + m_infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); + } + #endif // !defined(__MINGW32__) + + updateMsaa(); + postReset(); } - // Init reserved part of view name. - for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) + return true; + + error: + switch (errorState) { - char name[BGFX_CONFIG_MAX_VIEW_NAME_RESERVED+1]; - bx::snprintf(name, sizeof(name), "%3d ", ii); - mbstowcs(s_viewNameW[ii], name, BGFX_CONFIG_MAX_VIEW_NAME_RESERVED); + 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; } -#if !defined(__MINGW32__) - if (BX_ENABLED(BGFX_CONFIG_DEBUG) - && NULL != m_infoQueue) - { - m_infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); - } -#endif // !defined(__MINGW32__) - - updateMsaa(); - postReset(); + return false; } void shutdown() @@ -1123,7 +1239,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); DX_RELEASE(m_swapChain, 0); DX_RELEASE(m_deviceCtx, 0); DX_RELEASE(m_device, 0); - DX_RELEASE(m_factory,0); + DX_RELEASE(m_factory, 0); unloadRenderDoc(m_renderdocdll); @@ -1134,12 +1250,15 @@ BX_PRAGMA_DIAGNOSTIC_POP(); m_dxgidebugdll = NULL; } + if (NULL != m_d3d9dll) + { + bx::dlclose(m_d3d9dll); + m_d3d9dll = NULL; + } + bx::dlclose(m_dxgidll); m_dxgidll = NULL; - bx::dlclose(m_d3d9dll); - m_d3d9dll = NULL; - bx::dlclose(m_d3d11dll); m_d3d11dll = NULL; #endif // USE_D3D11_DYNAMIC_LIB @@ -2735,7 +2854,11 @@ BX_PRAGMA_DIAGNOSTIC_POP(); RendererContextI* rendererCreate() { 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; } diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index b493302c..2c4f686f 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -413,36 +413,77 @@ namespace bgfx { namespace d3d12 { } - void init() + ~RendererContextD3D12() { + } + + bool init() + { + uint32_t errorState = 0; + LUID luid; + m_fbh.idx = invalidHandle; memset(m_uniforms, 0, sizeof(m_uniforms) ); memset(&m_resolution, 0, sizeof(m_resolution) ); #if USE_D3D12_DYNAMIC_LIB 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"); - 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"); - 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"); - 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"); - 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"); - 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 HRESULT hr; 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_driverType = D3D_DRIVER_TYPE_HARDWARE; @@ -511,15 +552,22 @@ namespace bgfx { namespace d3d12 , __uuidof(ID3D12Device) , (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) { DX_RELEASE(m_adapter, 2); } + if (FAILED(hr) ) + { + goto error; + } + + errorState = 4; + 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) { adapter->GetDesc(&m_adapterDesc); @@ -569,206 +617,235 @@ namespace bgfx { namespace d3d12 , &m_scd , &m_swapChain ); - BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); - m_resolution.m_width = BGFX_DEFAULT_WIDTH; - m_resolution.m_height = BGFX_DEFAULT_HEIGHT; - - DX_CHECK(m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh - , 0 - | DXGI_MWA_NO_WINDOW_CHANGES - | DXGI_MWA_NO_ALT_ENTER - ) ); - - m_numWindows = 1; - - if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) + BX_WARN(SUCCEEDED(hr), "Failed to create swap chain."); + if (FAILED(hr) ) { - hr = m_device->QueryInterface(__uuidof(ID3D12InfoQueue), (void**)&m_infoQueue); + goto error; + } - if (SUCCEEDED(hr) ) + { + m_resolution.m_width = BGFX_DEFAULT_WIDTH; + m_resolution.m_height = BGFX_DEFAULT_HEIGHT; + + DX_CHECK(m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh + , 0 + | DXGI_MWA_NO_WINDOW_CHANGES + | DXGI_MWA_NO_ALT_ENTER + ) ); + + m_numWindows = 1; + + if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) { - m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); - m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); - m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, false); + hr = m_device->QueryInterface(__uuidof(ID3D12InfoQueue), (void**)&m_infoQueue); - D3D12_INFO_QUEUE_FILTER filter; - memset(&filter, 0, sizeof(filter) ); - - D3D12_MESSAGE_CATEGORY catlist[] = - { - D3D12_MESSAGE_CATEGORY_STATE_SETTING, - D3D12_MESSAGE_CATEGORY_EXECUTION, - }; - filter.DenyList.NumCategories = BX_COUNTOF(catlist); - filter.DenyList.pCategoryList = catlist; - m_infoQueue->PushStorageFilter(&filter); - - DX_RELEASE(m_infoQueue, 19); - } - } - - D3D12_DESCRIPTOR_HEAP_DESC rtvDescHeap; - rtvDescHeap.NumDescriptors = 0 - + BX_COUNTOF(m_backBufferColor) - + BGFX_CONFIG_MAX_FRAME_BUFFERS*BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS - ; - rtvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - rtvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - rtvDescHeap.NodeMask = 0; - DX_CHECK(m_device->CreateDescriptorHeap(&rtvDescHeap - , __uuidof(ID3D12DescriptorHeap) - , (void**)&m_rtvDescriptorHeap - ) ); - - D3D12_DESCRIPTOR_HEAP_DESC dsvDescHeap; - dsvDescHeap.NumDescriptors = 0 - + 1 // reserved for depth backbuffer. - + BGFX_CONFIG_MAX_FRAME_BUFFERS - ; - dsvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; - dsvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - dsvDescHeap.NodeMask = 0; - DX_CHECK(m_device->CreateDescriptorHeap(&dsvDescHeap - , __uuidof(ID3D12DescriptorHeap) - , (void**)&m_dsvDescriptorHeap - ) ); - - for (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii) - { - m_scratchBuffer[ii].create(BGFX_CONFIG_MAX_DRAW_CALLS*1024 - , BGFX_CONFIG_MAX_TEXTURES + BGFX_CONFIG_MAX_SHADERS + BGFX_CONFIG_MAX_DRAW_CALLS - ); - } - m_samplerAllocator.create(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER - , 1024 - , BGFX_CONFIG_MAX_TEXTURE_SAMPLERS - ); - - D3D12_DESCRIPTOR_RANGE descRange[] = - { - { D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, - { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, - { D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, - { D3D12_DESCRIPTOR_RANGE_TYPE_UAV, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, - }; - BX_STATIC_ASSERT(BX_COUNTOF(descRange) == Rdt::Count); - - D3D12_ROOT_PARAMETER rootParameter[] = - { - { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::Sampler] }, D3D12_SHADER_VISIBILITY_ALL }, - { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::SRV] }, D3D12_SHADER_VISIBILITY_ALL }, - { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::CBV] }, D3D12_SHADER_VISIBILITY_ALL }, -// { D3D12_ROOT_PARAMETER_TYPE_CBV, { 0, 0 }, D3D12_SHADER_VISIBILITY_ALL }, - { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::UAV] }, D3D12_SHADER_VISIBILITY_ALL }, - }; -// rootParameter[Rdt::CBV].Constants.ShaderRegister = 0; -// rootParameter[Rdt::CBV].Constants.RegisterSpace = 100; -// rootParameter[Rdt::CBV].Constants.Num32BitValues = 0; - - D3D12_ROOT_SIGNATURE_DESC descRootSignature; - descRootSignature.NumParameters = BX_COUNTOF(rootParameter); - descRootSignature.pParameters = rootParameter; - descRootSignature.NumStaticSamplers = 0; - descRootSignature.pStaticSamplers = NULL; - descRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - - ID3DBlob* outBlob; - ID3DBlob* errorBlob; - DX_CHECK(D3D12SerializeRootSignature(&descRootSignature - , D3D_ROOT_SIGNATURE_VERSION_1 - , &outBlob - , &errorBlob - ) ); - - DX_CHECK(m_device->CreateRootSignature(0 - , outBlob->GetBufferPointer() - , outBlob->GetBufferSize() - , __uuidof(ID3D12RootSignature) - , (void**)&m_rootSignature - ) ); - - UniformHandle handle = BGFX_INVALID_HANDLE; - for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii) - { - m_uniformReg.add(handle, getPredefinedUniformName(PredefinedUniform::Enum(ii) ), &m_predefinedUniforms[ii]); - } - - g_caps.supported |= ( 0 - | BGFX_CAPS_TEXTURE_3D - | BGFX_CAPS_TEXTURE_COMPARE_ALL - | BGFX_CAPS_INSTANCING - | BGFX_CAPS_VERTEX_ATTRIB_HALF - | BGFX_CAPS_FRAGMENT_DEPTH - | BGFX_CAPS_BLEND_INDEPENDENT - | BGFX_CAPS_COMPUTE - | BGFX_CAPS_FRAGMENT_ORDERING -// | BGFX_CAPS_SWAP_CHAIN - ); - g_caps.maxTextureSize = 16384; - g_caps.maxFBAttachments = bx::uint32_min(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS); - - for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) - { - uint8_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE; - - const DXGI_FORMAT fmt = isDepth(TextureFormat::Enum(ii) ) - ? s_textureFormat[ii].m_fmtDsv - : s_textureFormat[ii].m_fmt - ; - - if (DXGI_FORMAT_UNKNOWN != fmt) - { - D3D12_FEATURE_DATA_FORMAT_SUPPORT data; - data.Format = fmt; - hr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); if (SUCCEEDED(hr) ) { - support |= 0 != (data.Support1 & (0 - | D3D12_FORMAT_SUPPORT1_TEXTURE2D - | D3D12_FORMAT_SUPPORT1_TEXTURE3D - | D3D12_FORMAT_SUPPORT1_TEXTURECUBE - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_COLOR - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; + m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true); + m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true); + m_infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, false); - support |= 0 != (data.Support1 & (0 - | D3D12_FORMAT_SUPPORT1_BUFFER - | D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER - | D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_VERTEX - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; + D3D12_INFO_QUEUE_FILTER filter; + memset(&filter, 0, sizeof(filter) ); - support |= 0 != (data.Support1 & (0 - | D3D12_FORMAT_SUPPORT1_SHADER_LOAD - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; + D3D12_MESSAGE_CATEGORY catlist[] = + { + D3D12_MESSAGE_CATEGORY_STATE_SETTING, + D3D12_MESSAGE_CATEGORY_EXECUTION, + }; + filter.DenyList.NumCategories = BX_COUNTOF(catlist); + filter.DenyList.pCategoryList = catlist; + m_infoQueue->PushStorageFilter(&filter); - support |= 0 != (data.Support1 & (0 - | D3D12_FORMAT_SUPPORT1_RENDER_TARGET - | D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL - ) ) - ? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - } - else - { - BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) ); + DX_RELEASE(m_infoQueue, 19); } } - g_caps.formats[ii] = support; + D3D12_DESCRIPTOR_HEAP_DESC rtvDescHeap; + rtvDescHeap.NumDescriptors = 0 + + BX_COUNTOF(m_backBufferColor) + + BGFX_CONFIG_MAX_FRAME_BUFFERS*BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + ; + rtvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + rtvDescHeap.NodeMask = 0; + DX_CHECK(m_device->CreateDescriptorHeap(&rtvDescHeap + , __uuidof(ID3D12DescriptorHeap) + , (void**)&m_rtvDescriptorHeap + ) ); + + D3D12_DESCRIPTOR_HEAP_DESC dsvDescHeap; + dsvDescHeap.NumDescriptors = 0 + + 1 // reserved for depth backbuffer. + + BGFX_CONFIG_MAX_FRAME_BUFFERS + ; + dsvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + dsvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + dsvDescHeap.NodeMask = 0; + DX_CHECK(m_device->CreateDescriptorHeap(&dsvDescHeap + , __uuidof(ID3D12DescriptorHeap) + , (void**)&m_dsvDescriptorHeap + ) ); + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii) + { + m_scratchBuffer[ii].create(BGFX_CONFIG_MAX_DRAW_CALLS*1024 + , BGFX_CONFIG_MAX_TEXTURES + BGFX_CONFIG_MAX_SHADERS + BGFX_CONFIG_MAX_DRAW_CALLS + ); + } + m_samplerAllocator.create(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + , 1024 + , BGFX_CONFIG_MAX_TEXTURE_SAMPLERS + ); + + D3D12_DESCRIPTOR_RANGE descRange[] = + { + { D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, + { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, + { D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, + { D3D12_DESCRIPTOR_RANGE_TYPE_UAV, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, + }; + BX_STATIC_ASSERT(BX_COUNTOF(descRange) == Rdt::Count); + + D3D12_ROOT_PARAMETER rootParameter[] = + { + { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::Sampler] }, D3D12_SHADER_VISIBILITY_ALL }, + { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::SRV] }, D3D12_SHADER_VISIBILITY_ALL }, + { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::CBV] }, D3D12_SHADER_VISIBILITY_ALL }, + // { D3D12_ROOT_PARAMETER_TYPE_CBV, { 0, 0 }, D3D12_SHADER_VISIBILITY_ALL }, + { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, { 1, &descRange[Rdt::UAV] }, D3D12_SHADER_VISIBILITY_ALL }, + }; + // rootParameter[Rdt::CBV].Constants.ShaderRegister = 0; + // rootParameter[Rdt::CBV].Constants.RegisterSpace = 100; + // rootParameter[Rdt::CBV].Constants.Num32BitValues = 0; + + D3D12_ROOT_SIGNATURE_DESC descRootSignature; + descRootSignature.NumParameters = BX_COUNTOF(rootParameter); + descRootSignature.pParameters = rootParameter; + descRootSignature.NumStaticSamplers = 0; + descRootSignature.pStaticSamplers = NULL; + descRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ID3DBlob* outBlob; + ID3DBlob* errorBlob; + DX_CHECK(D3D12SerializeRootSignature(&descRootSignature + , D3D_ROOT_SIGNATURE_VERSION_1 + , &outBlob + , &errorBlob + ) ); + + DX_CHECK(m_device->CreateRootSignature(0 + , outBlob->GetBufferPointer() + , outBlob->GetBufferSize() + , __uuidof(ID3D12RootSignature) + , (void**)&m_rootSignature + ) ); + + UniformHandle handle = BGFX_INVALID_HANDLE; + for (uint32_t ii = 0; ii < PredefinedUniform::Count; ++ii) + { + m_uniformReg.add(handle, getPredefinedUniformName(PredefinedUniform::Enum(ii) ), &m_predefinedUniforms[ii]); + } + + g_caps.supported |= ( 0 + | BGFX_CAPS_TEXTURE_3D + | BGFX_CAPS_TEXTURE_COMPARE_ALL + | BGFX_CAPS_INSTANCING + | BGFX_CAPS_VERTEX_ATTRIB_HALF + | BGFX_CAPS_FRAGMENT_DEPTH + | BGFX_CAPS_BLEND_INDEPENDENT + | BGFX_CAPS_COMPUTE + | BGFX_CAPS_FRAGMENT_ORDERING + // | BGFX_CAPS_SWAP_CHAIN + ); + g_caps.maxTextureSize = 16384; + g_caps.maxFBAttachments = bx::uint32_min(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS); + + for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) + { + uint8_t support = BGFX_CAPS_FORMAT_TEXTURE_NONE; + + const DXGI_FORMAT fmt = isDepth(TextureFormat::Enum(ii) ) + ? s_textureFormat[ii].m_fmtDsv + : s_textureFormat[ii].m_fmt + ; + + if (DXGI_FORMAT_UNKNOWN != fmt) + { + D3D12_FEATURE_DATA_FORMAT_SUPPORT data; + data.Format = fmt; + hr = m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) ); + if (SUCCEEDED(hr) ) + { + support |= 0 != (data.Support1 & (0 + | D3D12_FORMAT_SUPPORT1_TEXTURE2D + | D3D12_FORMAT_SUPPORT1_TEXTURE3D + | D3D12_FORMAT_SUPPORT1_TEXTURECUBE + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_COLOR + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + support |= 0 != (data.Support1 & (0 + | D3D12_FORMAT_SUPPORT1_BUFFER + | D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER + | D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_VERTEX + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + support |= 0 != (data.Support1 & (0 + | D3D12_FORMAT_SUPPORT1_SHADER_LOAD + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + support |= 0 != (data.Support1 & (0 + | D3D12_FORMAT_SUPPORT1_RENDER_TARGET + | D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL + ) ) + ? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + } + else + { + BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) ); + } + } + + g_caps.formats[ii] = support; + } + + postReset(); + } + return true; + + 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; } - postReset(); + return false; } - ~RendererContextD3D12() + void shutdown() { preReset(); @@ -811,6 +888,7 @@ namespace bgfx { namespace d3d12 m_cmd.shutdown(); DX_RELEASE(m_device, 0); + DX_RELEASE(m_factory, 0); #if USE_D3D12_DYNAMIC_LIB bx::dlclose(m_d3d12dll); @@ -2188,12 +2266,17 @@ data.NumQualityLevels = 0; RendererContextI* rendererCreate() { 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; } void rendererDestroy() { + s_renderD3D12->shutdown(); BX_DELETE(g_allocator, s_renderD3D12); s_renderD3D12 = NULL; } diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 81db0c44..ef309606 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -291,8 +291,10 @@ namespace bgfx { namespace d3d9 { } - void init() + bool init() { + uint32_t errorState = 0; + m_fbh.idx = invalidHandle; memset(m_uniforms, 0, sizeof(m_uniforms) ); memset(&m_resolution, 0, sizeof(m_resolution) ); @@ -323,7 +325,14 @@ namespace bgfx { namespace d3d9 m_params.BackBufferHeight = rect.bottom-rect.top; 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) ) { @@ -351,12 +360,25 @@ namespace bgfx { namespace d3d9 #endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX { 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_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_deviceType = BGFX_PCI_ID_SOFTWARE_RASTERIZER == g_caps.vendorId @@ -442,7 +464,14 @@ namespace bgfx { namespace d3d9 #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; @@ -456,15 +485,23 @@ namespace bgfx { namespace d3d9 DX_CHECK(m_device->GetDeviceCaps(&m_caps) ); // 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"); - BGFX_FATAL( (D3DPTEXTURECAPS_MIPMAP & m_caps.TextureCaps) == D3DPTEXTURECAPS_MIPMAP, Fatal::MinimumRequiredSpecs, "D3DPTEXTURECAPS_MIPMAP"); - BGFX_FATAL( (D3DPTEXTURECAPS_ALPHA & m_caps.TextureCaps) == D3DPTEXTURECAPS_ALPHA, Fatal::MinimumRequiredSpecs, "D3DPTEXTURECAPS_ALPHA"); - BGFX_FATAL(m_caps.VertexShaderVersion >= D3DVS_VERSION(2, 0) && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 1) - , Fatal::MinimumRequiredSpecs + BX_WARN( (D3DPTEXTURECAPS_SQUAREONLY & m_caps.TextureCaps) == 0, "D3DPTEXTURECAPS_SQUAREONLY"); + BX_WARN( (D3DPTEXTURECAPS_MIPMAP & m_caps.TextureCaps) == D3DPTEXTURECAPS_MIPMAP, "D3DPTEXTURECAPS_MIPMAP"); + BX_WARN( (D3DPTEXTURECAPS_ALPHA & m_caps.TextureCaps) == D3DPTEXTURECAPS_ALPHA, "D3DPTEXTURECAPS_ALPHA"); + BX_WARN(m_caps.VertexShaderVersion >= D3DVS_VERSION(2, 0) && m_caps.PixelShaderVersion >= D3DPS_VERSION(2, 1) , "Shader Model Version (vs: %x, ps: %x)." , m_caps.VertexShaderVersion , 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 constants: %d", m_caps.MaxVertexShaderConst); BX_TRACE("Max fragment shader 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots); @@ -632,6 +669,50 @@ namespace bgfx { namespace d3d9 postReset(); 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() @@ -1800,7 +1881,11 @@ namespace bgfx { namespace d3d9 RendererContextI* rendererCreate() { 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; }