Added fall back to noop renderer when device is removed.

This commit is contained in:
Branimir Karadžić
2017-04-07 19:07:20 -07:00
parent 6aae4e6962
commit 8b14a7e977
10 changed files with 118 additions and 62 deletions

View File

@@ -1669,6 +1669,13 @@ namespace bgfx
{
m_renderCtx->flip(m_render->m_hmd);
m_flipped = true;
if (m_renderCtx->isDeviceRemoved() )
{
// Something horribly went wrong, fallback to noop renderer.
m_renderCtx = m_renderNoop;
g_caps.rendererType = m_renderCtx->getRendererType();
}
}
if (apiSemWait(_msecs) )
@@ -1834,7 +1841,7 @@ namespace bgfx
static RendererCreator s_rendererCreator[] =
{
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NOOP_NAME, !!BGFX_CONFIG_RENDERER_NOOP }, // Noop
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NOOP_NAME, true }, // Noop
{ d3d9::rendererCreate, d3d9::rendererDestroy, BGFX_RENDERER_DIRECT3D9_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D9 }, // Direct3D9
{ d3d11::rendererCreate, d3d11::rendererDestroy, BGFX_RENDERER_DIRECT3D11_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D11 }, // Direct3D11
{ d3d12::rendererCreate, d3d12::rendererDestroy, BGFX_RENDERER_DIRECT3D12_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D12 }, // Direct3D12
@@ -1850,8 +1857,6 @@ namespace bgfx
};
BX_STATIC_ASSERT(BX_COUNTOF(s_rendererCreator) == RendererType::Count);
static RendererDestroyFn s_rendererDestroyFn;
struct Condition
{
enum Enum
@@ -1974,7 +1979,6 @@ namespace bgfx
renderCtx = s_rendererCreator[renderer].createFn();
if (NULL != renderCtx)
{
s_rendererDestroyFn = s_rendererCreator[renderer].destroyFn;
break;
}
@@ -1984,9 +1988,12 @@ namespace bgfx
return renderCtx;
}
void rendererDestroy()
void rendererDestroy(RendererContextI* _renderCtx)
{
s_rendererDestroyFn();
if (NULL != _renderCtx)
{
s_rendererCreator[_renderCtx->getRendererType()].destroyFn();
}
}
void Context::rendererExecCommands(CommandBuffer& _cmdbuf)
@@ -2020,8 +2027,9 @@ namespace bgfx
RendererType::Enum type;
_cmdbuf.read(type);
m_renderCtx = rendererCreate(type);
m_rendererInitialized = NULL != m_renderCtx;
m_renderMain = rendererCreate(type);
m_rendererInitialized = NULL != m_renderMain;
if (!m_rendererInitialized)
{
@@ -2031,6 +2039,12 @@ namespace bgfx
);
return;
}
m_renderCtx = m_renderMain;
m_renderNoop = RendererType::Noop != type
? rendererCreate(RendererType::Noop)
: NULL
;
}
break;
}
@@ -2053,8 +2067,15 @@ namespace bgfx
case CommandBuffer::RendererShutdownEnd:
{
BX_CHECK(!m_rendererInitialized && !m_exit, "This shouldn't happen! Bad synchronization?");
rendererDestroy();
m_renderCtx = NULL;
rendererDestroy(m_renderMain);
m_renderMain = NULL;
rendererDestroy(m_renderNoop);
m_renderNoop = NULL;
m_exit = true;
}
// fall through

View File

@@ -2178,6 +2178,7 @@ namespace bgfx
virtual ~RendererContextI() = 0;
virtual RendererType::Enum getRendererType() const = 0;
virtual const char* getRendererName() const = 0;
virtual bool isDeviceRemoved() = 0;
virtual void flip(HMD& _hmd) = 0;
virtual void createIndexBuffer(IndexBufferHandle _handle, Memory* _mem, uint16_t _flags) = 0;
virtual void destroyIndexBuffer(IndexBufferHandle _handle) = 0;
@@ -2244,6 +2245,8 @@ namespace bgfx
, m_frames(0)
, m_debug(BGFX_DEBUG_NONE)
, m_renderCtx(NULL)
, m_renderMain(NULL)
, m_renderNoop(NULL)
, m_rendererInitialized(false)
, m_exit(false)
, m_flipAfterRender(false)
@@ -4308,6 +4311,8 @@ namespace bgfx
ClearQuad m_clearQuad;
RendererContextI* m_renderCtx;
RendererContextI* m_renderMain;
RendererContextI* m_renderNoop;
bool m_rendererInitialized;
bool m_exit;

View File

@@ -19,8 +19,7 @@
&& !defined(BGFX_CONFIG_RENDERER_OPENGL) \
&& !defined(BGFX_CONFIG_RENDERER_OPENGLES) \
&& !defined(BGFX_CONFIG_RENDERER_VULKAN) \
&& !defined(BGFX_CONFIG_RENDERER_GNM) \
&& !defined(BGFX_CONFIG_RENDERER_NOOP)
&& !defined(BGFX_CONFIG_RENDERER_GNM)
# ifndef BGFX_CONFIG_RENDERER_DIRECT3D9
# define BGFX_CONFIG_RENDERER_DIRECT3D9 (0 \
@@ -86,18 +85,6 @@
? 1 : 0)
# endif // BGFX_CONFIG_RENDERER_GNM
# ifndef BGFX_CONFIG_RENDERER_NOOP
# define BGFX_CONFIG_RENDERER_NOOP (!(0 \
|| BGFX_CONFIG_RENDERER_DIRECT3D9 \
|| BGFX_CONFIG_RENDERER_DIRECT3D11 \
|| BGFX_CONFIG_RENDERER_DIRECT3D12 \
|| BGFX_CONFIG_RENDERER_METAL \
|| BGFX_CONFIG_RENDERER_OPENGL \
|| BGFX_CONFIG_RENDERER_OPENGLES \
|| BGFX_CONFIG_RENDERER_VULKAN \
|| BGFX_CONFIG_RENDERER_GNM \
? 1 : 0) )
# endif // BGFX_CONFIG_RENDERER_NOOP
#else
# ifndef BGFX_CONFIG_RENDERER_DIRECT3D9
# define BGFX_CONFIG_RENDERER_DIRECT3D9 0
@@ -130,10 +117,6 @@
# ifndef BGFX_CONFIG_RENDERER_GNM
# define BGFX_CONFIG_RENDERER_GNM 0
# endif // BGFX_CONFIG_RENDERER_GNM
# ifndef BGFX_CONFIG_RENDERER_NOOP
# define BGFX_CONFIG_RENDERER_NOOP 0
# endif // BGFX_CONFIG_RENDERER_NOOP
#endif // !defined...
#if BGFX_CONFIG_RENDERER_OPENGL && BGFX_CONFIG_RENDERER_OPENGL < 21

View File

@@ -455,6 +455,35 @@ namespace bgfx { namespace d3d11
;
}
static const char* getLostReason(HRESULT _hr)
{
switch (_hr)
{
// The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.
case DXGI_ERROR_DEVICE_REMOVED: return "DXGI_ERROR_DEVICE_REMOVED";
// The GPU will not respond to more commands, most likely because of an invalid command passed by the calling application.
case DXGI_ERROR_DEVICE_HUNG: return "DXGI_ERROR_DEVICE_HUNG";
// The GPU will not respond to more commands, most likely because some other application submitted invalid commands.
// The calling application should re-create the device and continue.
case DXGI_ERROR_DEVICE_RESET: return "DXGI_ERROR_DEVICE_RESET";
// An internal issue prevented the driver from carrying out the specified operation. The driver's state is probably
// suspect, and the application should not continue.
case DXGI_ERROR_DRIVER_INTERNAL_ERROR: return "DXGI_ERROR_DRIVER_INTERNAL_ERROR";
// A resource is not available at the time of the call, but may become available later.
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: return "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE";
case S_OK: return "S_OK";
default: break;
}
return "Unknown HRESULT?";
}
template <typename Ty>
static BX_NO_INLINE void setDebugObjectName(Ty* _interface, const char* _format, ...)
{
@@ -654,7 +683,7 @@ namespace bgfx { namespace d3d11
, m_adapter(NULL)
, m_factory(NULL)
, m_swapChain(NULL)
, m_lost(0)
, m_lost(false)
, m_numWindows(0)
, m_device(NULL)
, m_deviceCtx(NULL)
@@ -2263,9 +2292,15 @@ BX_PRAGMA_DIAGNOSTIC_POP();
capturePostReset();
}
bool isDeviceRemoved() BX_OVERRIDE
{
return m_lost;
}
void flip(HMD& _hmd) BX_OVERRIDE
{
if (NULL != m_swapChain)
if (NULL != m_swapChain
&& !m_lost)
{
HRESULT hr = S_OK;
uint32_t syncInterval = BX_ENABLED(!BX_PLATFORM_WINDOWS)
@@ -2298,15 +2333,14 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
}
if (isLost(hr) )
{
++m_lost;
BGFX_FATAL(10 > m_lost, bgfx::Fatal::DeviceLost, "Device is lost. FAILED 0x%08x", hr);
}
else
{
m_lost = 0;
}
m_lost = d3d11::isLost(hr);
BGFX_FATAL(!m_lost
, bgfx::Fatal::DeviceLost
, "Device is lost. FAILED 0x%08x %s (%s)"
, hr
, getLostReason(hr)
, DXGI_ERROR_DEVICE_REMOVED == hr ? getLostReason(m_device->GetDeviceRemovedReason() ) : "no info"
);
}
}
@@ -3551,7 +3585,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
#endif // BX_PLATFORM_WINDOWS
bool m_needPresent;
uint16_t m_lost;
bool m_lost;
uint16_t m_numWindows;
FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS];
@@ -5273,7 +5307,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
void RendererContextD3D11::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter)
{
if (updateResolution(_render->m_resolution) )
if (m_lost
|| updateResolution(_render->m_resolution) )
{
return;
}

View File

@@ -1260,7 +1260,7 @@ namespace bgfx { namespace d3d12
return BGFX_RENDERER_DIRECT3D12_NAME;
}
static bool isLost(HRESULT _hr)
static bool isDeviceRemoved(HRESULT _hr)
{
return DXGI_ERROR_DEVICE_REMOVED == _hr
|| DXGI_ERROR_DEVICE_HUNG == _hr
@@ -1270,6 +1270,11 @@ namespace bgfx { namespace d3d12
;
}
bool isDeviceRemoved() BX_OVERRIDE
{
return false;
}
void flip(HMD& /*_hmd*/) BX_OVERRIDE
{
if (NULL != m_swapChain)
@@ -1294,7 +1299,7 @@ namespace bgfx { namespace d3d12
m_presentElapsed = now - start;
if (FAILED(hr)
&& isLost(hr) )
&& isDeviceRemoved(hr) )
{
++m_lost;
BGFX_FATAL(10 > m_lost, bgfx::Fatal::DeviceLost, "Device is lost. FAILED 0x%08x", hr);
@@ -5337,7 +5342,7 @@ data.NumQualityLevels = 0;
buffer.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
scratchBuffer.allocUav(srvHandle[stage], buffer);
}
else
else
{
buffer.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
scratchBuffer.allocSrv(srvHandle[stage], buffer);

View File

@@ -1458,6 +1458,11 @@ namespace bgfx { namespace d3d9
m_flushQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
}
bool isDeviceRemoved() BX_OVERRIDE
{
return false;
}
void flip(HMD& /*_hmd*/) BX_OVERRIDE
{
if (NULL != m_swapChain)
@@ -1488,7 +1493,7 @@ namespace bgfx { namespace d3d9
}
#if BX_PLATFORM_WINDOWS
if (isLost(hr) )
if (d3d9::isLost(hr) )
{
do
{

View File

@@ -2289,6 +2289,11 @@ namespace bgfx { namespace gl
return BGFX_RENDERER_OPENGL_NAME;
}
bool isDeviceRemoved() BX_OVERRIDE
{
return false;
}
void flip(HMD& _hmd)
{
if (m_flip)

View File

@@ -1069,6 +1069,11 @@ namespace bgfx { namespace mtl
}
}
bool isDeviceRemoved() BX_OVERRIDE
{
return false;
}
void flip(HMD& /*_hmd*/) BX_OVERRIDE
{
if (NULL == m_commandBuffer)

View File

@@ -5,8 +5,6 @@
#include "bgfx_p.h"
#if BGFX_CONFIG_RENDERER_NOOP
namespace bgfx { namespace noop
{
struct RendererContextNOOP : public RendererContextI
@@ -52,6 +50,11 @@ namespace bgfx { namespace noop
return BGFX_RENDERER_NOOP_NAME;
}
bool isDeviceRemoved() BX_OVERRIDE
{
return false;
}
void flip(HMD& /*_hmd*/) BX_OVERRIDE
{
}
@@ -224,19 +227,3 @@ namespace bgfx { namespace noop
s_renderNOOP = NULL;
}
} /* namespace noop */ } // namespace bgfx
#else
namespace bgfx { namespace noop
{
RendererContextI* rendererCreate()
{
return NULL;
}
void rendererDestroy()
{
}
} /* namespace noop */ } // namespace bgfx
#endif // BGFX_CONFIG_RENDERER_NOOP

View File

@@ -1919,6 +1919,11 @@ VK_IMPORT_DEVICE
return BGFX_RENDERER_VULKAN_NAME;
}
bool isDeviceRemoved() BX_OVERRIDE
{
return false;
}
void flip(HMD& /*_hmd*/) BX_OVERRIDE
{
if (VK_NULL_HANDLE != m_swapchain)