Răsfoiți Sursa

Added fall back to noop renderer when device is removed.

Branimir Karadžić 8 ani în urmă
părinte
comite
8b14a7e977

+ 30 - 9
src/bgfx.cpp

@@ -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

+ 5 - 0
src/bgfx_p.h

@@ -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;

+ 1 - 18
src/config.h

@@ -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

+ 48 - 13
src/renderer_d3d11.cpp

@@ -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;
 		}

+ 8 - 3
src/renderer_d3d12.cpp

@@ -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);

+ 6 - 1
src/renderer_d3d9.cpp

@@ -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
 						{

+ 5 - 0
src/renderer_gl.cpp

@@ -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)

+ 5 - 0
src/renderer_mtl.mm

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

+ 5 - 18
src/renderer_noop.cpp

@@ -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

+ 5 - 0
src/renderer_vk.cpp

@@ -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)