Ver Fonte

Combine OVRBufferI and OVRMirrorI into a single interface

Simplify the renderer interface for VR to separate the OVR
implementation from the overall HMD foundation.

Part of merging OpenVR back upstream.
Matthew Endsley há 9 anos atrás
pai
commit
eec95aeef6
6 ficheiros alterados com 397 adições e 396 exclusões
  1. 14 25
      src/hmd_ovr.cpp
  2. 16 20
      src/hmd_ovr.h
  3. 167 155
      src/renderer_d3d11.cpp
  4. 14 17
      src/renderer_d3d11.h
  5. 170 159
      src/renderer_gl.cpp
  6. 16 20
      src/renderer_gl.h

+ 14 - 25
src/hmd_ovr.cpp

@@ -24,11 +24,10 @@ namespace bgfx
 	OVR::OVR()
 	OVR::OVR()
 		: m_hmd(NULL)
 		: m_hmd(NULL)
 		, m_enabled(false)
 		, m_enabled(false)
-		, m_mirror(NULL)
+		, m_render(NULL)
 		, m_frameIndex(0)
 		, m_frameIndex(0)
 		, m_sensorSampleTime(0)
 		, m_sensorSampleTime(0)
 	{
 	{
-		memset(m_eyeBuffers, 0, sizeof(m_eyeBuffers));
 	}
 	}
 
 
 	OVR::~OVR()
 	OVR::~OVR()
@@ -73,19 +72,10 @@ namespace bgfx
 	{
 	{
 		BX_CHECK(!m_enabled, "HMD not disabled.");
 		BX_CHECK(!m_enabled, "HMD not disabled.");
 
 
-		for (uint32_t ii = 0; ii < 2; ++ii)
-		{
-			if (NULL != m_eyeBuffers[ii])
-			{
-				m_eyeBuffers[ii]->destroy(m_hmd);
-				m_eyeBuffers[ii] = NULL;
-			}
-		}
-
-		if (NULL != m_mirror)
+		if (NULL != m_render)
 		{
 		{
-			m_mirror->destroy(m_hmd);
-			m_mirror = NULL;
+			m_render->destroy(m_hmd);
+			m_render = NULL;
 		}
 		}
 
 
 		ovr_Destroy(m_hmd);
 		ovr_Destroy(m_hmd);
@@ -97,13 +87,13 @@ namespace bgfx
 	{
 	{
 		_viewport->m_x      = 0;
 		_viewport->m_x      = 0;
 		_viewport->m_y      = 0;
 		_viewport->m_y      = 0;
-		_viewport->m_width  = m_eyeBuffers[_eye]->m_eyeTextureSize.w;
-		_viewport->m_height = m_eyeBuffers[_eye]->m_eyeTextureSize.h;
+		_viewport->m_width  = m_render->m_eyeTextureSize[_eye].w;
+		_viewport->m_height  = m_render->m_eyeTextureSize[_eye].h;
 	}
 	}
 
 
 	void OVR::renderEyeStart(uint8_t _eye)
 	void OVR::renderEyeStart(uint8_t _eye)
 	{
 	{
-		m_eyeBuffers[_eye]->render(m_hmd);
+		m_render->startEyeRender(m_hmd, _eye);
 	}
 	}
 
 
 	bool OVR::postReset()
 	bool OVR::postReset()
@@ -128,8 +118,7 @@ namespace bgfx
 		if (m_enabled)
 		if (m_enabled)
 		{
 		{
 			// on window resize this will recreate the mirror texture in ovrPostReset
 			// on window resize this will recreate the mirror texture in ovrPostReset
-			m_mirror->destroy(m_hmd);
-			m_mirror = NULL;
+			m_render->preReset(m_hmd);
 			m_enabled = false;
 			m_enabled = false;
 		}
 		}
 	}
 	}
@@ -154,8 +143,8 @@ namespace bgfx
 
 
 		for (uint32_t ii = 0; ii < 2; ++ii)
 		for (uint32_t ii = 0; ii < 2; ++ii)
 		{
 		{
-			m_eyeBuffers[ii]->postRender(m_hmd);
-			result = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[ii]->m_textureSwapChain);
+			m_render->postRender(m_hmd, ii);
+			result = ovr_CommitTextureSwapChain(m_hmd, m_render->m_textureSwapChain[ii]);
 			if (!OVR_SUCCESS(result) )
 			if (!OVR_SUCCESS(result) )
 			{
 			{
 				return DeviceLost;
 				return DeviceLost;
@@ -177,11 +166,11 @@ namespace bgfx
 
 
 		for (uint32_t ii = 0; ii < 2; ++ii)
 		for (uint32_t ii = 0; ii < 2; ++ii)
 		{
 		{
-			eyeLayer.ColorTexture[ii]    = m_eyeBuffers[ii]->m_textureSwapChain;
+			eyeLayer.ColorTexture[ii]    = m_render->m_textureSwapChain[ii];
 			eyeLayer.Viewport[ii].Pos.x  = 0;
 			eyeLayer.Viewport[ii].Pos.x  = 0;
 			eyeLayer.Viewport[ii].Pos.y  = 0;
 			eyeLayer.Viewport[ii].Pos.y  = 0;
-			eyeLayer.Viewport[ii].Size.w = m_eyeBuffers[ii]->m_eyeTextureSize.w;
-			eyeLayer.Viewport[ii].Size.h = m_eyeBuffers[ii]->m_eyeTextureSize.h;
+			eyeLayer.Viewport[ii].Size.w = m_render->m_eyeTextureSize[ii].w;
+			eyeLayer.Viewport[ii].Size.h = m_render->m_eyeTextureSize[ii].h;
 			eyeLayer.Fov[ii]             = m_hmdDesc.DefaultEyeFov[ii];
 			eyeLayer.Fov[ii]             = m_hmdDesc.DefaultEyeFov[ii];
 			eyeLayer.RenderPose[ii]      = m_pose[ii];
 			eyeLayer.RenderPose[ii]      = m_pose[ii];
 			eyeLayer.SensorSampleTime    = m_sensorSampleTime;
 			eyeLayer.SensorSampleTime    = m_sensorSampleTime;
@@ -199,7 +188,7 @@ namespace bgfx
 		// perform mirror texture blit right after the entire frame is submitted to HMD
 		// perform mirror texture blit right after the entire frame is submitted to HMD
 		if (result != ovrSuccess_NotVisible)
 		if (result != ovrSuccess_NotVisible)
 		{
 		{
-			m_mirror->blit(m_hmd);
+			m_render->blitMirror(m_hmd);
 		}
 		}
 
 
 		m_hmdToEyeOffset[0] = m_erd[0].HmdToEyeOffset;
 		m_hmdToEyeOffset[0] = m_erd[0].HmdToEyeOffset;

+ 16 - 20
src/hmd_ovr.h

@@ -27,29 +27,26 @@
 
 
 namespace bgfx
 namespace bgfx
 {
 {
-	// single eye buffer
-	struct OVRBufferI
+	// render data for both eyes and mirrored output
+	struct BX_NO_VTABLE OVRRenderI
 	{
 	{
-		virtual ~OVRBufferI() {};
-		virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) = 0;
+		virtual ~OVRRenderI() = 0;
+		virtual void create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) = 0;
 		virtual void destroy(const ovrSession& _session) = 0;
 		virtual void destroy(const ovrSession& _session) = 0;
-		virtual void render(const ovrSession& _session) = 0;
-		virtual void postRender(const ovrSession& _session) = 0;
-		ovrSizei m_eyeTextureSize;
-		ovrTextureSwapChain m_textureSwapChain;
+		virtual void preReset(const ovrSession& _session) = 0;
+		virtual void startEyeRender(const ovrSession& _session, int _eyeIdx) = 0;
+		virtual void postRender(const ovrSession& _session, int _eyeIdx) = 0;
+		virtual void blitMirror(const ovrSession& _session) = 0;
+
+		ovrSizei m_eyeTextureSize[2];
+		ovrTextureSwapChain m_textureSwapChain[2];
+		ovrMirrorTexture m_mirrorTexture;
+		ovrMirrorTextureDesc m_mirrorTextureDesc;
 	};
 	};
 
 
-	// mirrored window output
-	struct OVRMirrorI
+	inline OVRRenderI::~OVRRenderI()
 	{
 	{
-		virtual ~OVRMirrorI() {};
-		virtual void create(const ovrSession& _session, int windowWidth, int windowHeight) = 0;
-		virtual void destroy(const ovrSession& _session) = 0;
-		virtual void blit(const ovrSession& _session) = 0;
-
-		ovrMirrorTexture     m_mirrorTexture;
-		ovrMirrorTextureDesc m_mirrorTextureDesc;
-	};
+	}
 
 
 	struct OVR
 	struct OVR
 	{
 	{
@@ -93,8 +90,7 @@ namespace bgfx
 		ovrPosef    m_pose[2];
 		ovrPosef    m_pose[2];
 		ovrVector3f m_hmdToEyeOffset[2];
 		ovrVector3f m_hmdToEyeOffset[2];
 		ovrSizei    m_hmdSize;
 		ovrSizei    m_hmdSize;
-		OVRBufferI *m_eyeBuffers[2];
-		OVRMirrorI *m_mirror;
+		OVRRenderI *m_render;
 		uint64_t    m_frameIndex;
 		uint64_t    m_frameIndex;
 		double      m_sensorSampleTime;
 		double      m_sensorSampleTime;
 		bool m_enabled;
 		bool m_enabled;

+ 167 - 155
src/renderer_d3d11.cpp

@@ -3152,19 +3152,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 				{
 				{
 					const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
 					const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
 
 
-					for (uint32_t ii = 0; ii < 2; ++ii)
-					{
-						// eye buffers need to be initialized only once during application lifetime
-						if (NULL == m_ovr.m_eyeBuffers[ii])
-						{
-							m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii];
-							m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
-						}
-					}
-
-					// recreate mirror texture
-					m_ovr.m_mirror = &m_ovrMirror;
-					m_ovr.m_mirror->create(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height);
+					m_ovr.m_render = &m_ovrRender;
+					m_ovr.m_render->create(m_ovr.m_hmd, msaaSamples, m_resolution.m_width, m_resolution.m_height);
 				}
 				}
 			}
 			}
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
@@ -3566,8 +3555,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 
 
 		OVR m_ovr;
 		OVR m_ovr;
 #if BGFX_CONFIG_USE_OVR
 #if BGFX_CONFIG_USE_OVR
-		OVRMirrorD3D11 m_ovrMirror;
-		OVRBufferD3D11 m_ovrBuffers[2];
+		OVRRenderD3D11 m_ovrRender;
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
 	};
 	};
 
 
@@ -3622,204 +3610,228 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 	}
 	}
 
 
 #if BGFX_CONFIG_USE_OVR
 #if BGFX_CONFIG_USE_OVR
-	void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
+	OVRRenderD3D11::OVRRenderD3D11()
 	{
 	{
-		ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
-		m_eyeTextureSize = ovr_GetFovTextureSize(_session, (ovrEyeType)_eyeIdx, hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f);
-		m_msaaTexture = NULL;
-		m_msaaRtv = NULL;
-		m_msaaSv  = NULL;
-
-		ovrTextureSwapChainDesc desc = {};
-		desc.Type = ovrTexture_2D;
-		desc.ArraySize = 1;
-		desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
-		desc.Width  = m_eyeTextureSize.w;
-		desc.Height = m_eyeTextureSize.h;
-		desc.MipLevels   = 1;
-		desc.SampleCount = 1;
-		desc.MiscFlags = ovrTextureMisc_DX_Typeless;
-		desc.BindFlags = ovrTextureBind_DX_RenderTarget;
-		desc.StaticImage = ovrFalse;
-
-		ID3D11Device* device = s_renderD3D11->m_device;
+		m_mirrorTexture = NULL;
+		memset(m_textureSwapChain, 0, sizeof(m_textureSwapChain));
+	}
 
 
-		ovrResult result = ovr_CreateTextureSwapChainDX(_session, device, &desc, &m_textureSwapChain);
+	void OVRRenderD3D11::create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight)
+	{
+		ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
 
 
-		if (!OVR_SUCCESS(result) )
+		for (int eye = 0; eye < 2; ++eye)
 		{
 		{
-			BX_CHECK(false, "Could not create D3D11 OVR swap texture");
-		}
+			if (NULL == m_textureSwapChain[eye])
+			{
+				m_eyeTextureSize[eye] = ovr_GetFovTextureSize(_session, (ovrEyeType)eye, hmdDesc.DefaultEyeFov[eye], 1.0f);
+				m_msaaTexture[eye] = NULL;
+				m_msaaRtv[eye] = NULL;
+				m_msaaSv[eye]  = NULL;
+
+				ovrTextureSwapChainDesc desc = {};
+				desc.Type = ovrTexture_2D;
+				desc.ArraySize = 1;
+				desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+				desc.Width  = m_eyeTextureSize[eye].w;
+				desc.Height = m_eyeTextureSize[eye].h;
+				desc.MipLevels   = 1;
+				desc.SampleCount = 1;
+				desc.MiscFlags = ovrTextureMisc_DX_Typeless;
+				desc.BindFlags = ovrTextureBind_DX_RenderTarget;
+				desc.StaticImage = ovrFalse;
+
+				ID3D11Device* device = s_renderD3D11->m_device;
+
+				ovrResult result = ovr_CreateTextureSwapChainDX(_session, device, &desc, &m_textureSwapChain[eye]);
+
+				if (!OVR_SUCCESS(result) )
+				{
+					BX_CHECK(false, "Could not create D3D11 OVR swap texture");
+				}
 
 
-		memset(m_eyeRtv, 0, sizeof(m_eyeRtv) );
-		int textureCount = 0;
-		ovr_GetTextureSwapChainLength(_session, m_textureSwapChain, &textureCount);
+				memset(m_eyeRtv[eye], 0, sizeof(m_eyeRtv[eye]) );
+				int textureCount = 0;
+				ovr_GetTextureSwapChainLength(_session, m_textureSwapChain[eye], &textureCount);
 
 
-		for (int ii = 0; ii < textureCount; ++ii)
-		{
-			ID3D11Texture2D* tex = NULL;
-			ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, ii, IID_PPV_ARGS(&tex) );
-			D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
-			rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-			rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-
-			ID3D11RenderTargetView* rtv;
-			DX_CHECK(device->CreateRenderTargetView(tex, &rtvd, &rtv) );
-			m_eyeRtv[ii] = rtv;
-			DX_RELEASE(tex, 1);
+				for (int ii = 0; ii < textureCount; ++ii)
+				{
+					ID3D11Texture2D* tex = NULL;
+					ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain[eye], ii, IID_PPV_ARGS(&tex) );
+					D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
+					rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+					rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+
+					ID3D11RenderTargetView* rtv;
+					DX_CHECK(device->CreateRenderTargetView(tex, &rtvd, &rtv) );
+					m_eyeRtv[eye][ii] = rtv;
+					DX_RELEASE(tex, 1);
+				}
+
+				// setup depth buffer
+				D3D11_TEXTURE2D_DESC dbDesc;
+				dbDesc.Width = m_eyeTextureSize[eye].w;
+				dbDesc.Height = m_eyeTextureSize[eye].h;
+				dbDesc.MipLevels = 1;
+				dbDesc.ArraySize = 1;
+				dbDesc.Format = DXGI_FORMAT_D32_FLOAT;
+				dbDesc.SampleDesc.Count = _msaaSamples;
+				dbDesc.SampleDesc.Quality = 0;
+				dbDesc.Usage = D3D11_USAGE_DEFAULT;
+				dbDesc.CPUAccessFlags = 0;
+				dbDesc.MiscFlags = 0;
+				dbDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+				ID3D11Texture2D* tex;
+				DX_CHECK(device->CreateTexture2D(&dbDesc, NULL, &tex) );
+				DX_CHECK(device->CreateDepthStencilView(tex, NULL, &m_depthBuffer[eye]) );
+				DX_RELEASE(tex, 0);
+
+				// create MSAA render target
+				if (_msaaSamples > 1)
+				{
+					D3D11_TEXTURE2D_DESC dsDesc;
+					dsDesc.Width = m_eyeTextureSize[eye].w;
+					dsDesc.Height = m_eyeTextureSize[eye].h;
+					dsDesc.MipLevels = 1;
+					dsDesc.ArraySize = 1;
+					dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+					dsDesc.SampleDesc.Count = _msaaSamples;
+					dsDesc.SampleDesc.Quality = 0;
+					dsDesc.Usage = D3D11_USAGE_DEFAULT;
+					dsDesc.CPUAccessFlags = 0;
+					dsDesc.MiscFlags = 0;
+					dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+
+					ID3D11Device* device = s_renderD3D11->m_device;
+					DX_CHECK(device->CreateTexture2D(&dsDesc, NULL, &m_msaaTexture[eye]));
+					DX_CHECK(device->CreateShaderResourceView(m_msaaTexture[eye], NULL, &m_msaaSv[eye]));
+					DX_CHECK(device->CreateRenderTargetView(m_msaaTexture[eye], NULL, &m_msaaRtv[eye]));
+				}
+			}
 		}
 		}
 
 
-		// setup depth buffer
-		D3D11_TEXTURE2D_DESC dbDesc;
-		dbDesc.Width = m_eyeTextureSize.w;
-		dbDesc.Height = m_eyeTextureSize.h;
-		dbDesc.MipLevels = 1;
-		dbDesc.ArraySize = 1;
-		dbDesc.Format = DXGI_FORMAT_D32_FLOAT;
-		dbDesc.SampleDesc.Count = _msaaSamples;
-		dbDesc.SampleDesc.Quality = 0;
-		dbDesc.Usage = D3D11_USAGE_DEFAULT;
-		dbDesc.CPUAccessFlags = 0;
-		dbDesc.MiscFlags = 0;
-		dbDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
-		ID3D11Texture2D* tex;
-		DX_CHECK(device->CreateTexture2D(&dbDesc, NULL, &tex) );
-		DX_CHECK(device->CreateDepthStencilView(tex, NULL, &m_depthBuffer) );
-		DX_RELEASE(tex, 0);
-
-		// create MSAA render target
-		if (_msaaSamples > 1)
-		{
-			D3D11_TEXTURE2D_DESC dsDesc;
-			dsDesc.Width = m_eyeTextureSize.w;
-			dsDesc.Height = m_eyeTextureSize.h;
-			dsDesc.MipLevels = 1;
-			dsDesc.ArraySize = 1;
-			dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-			dsDesc.SampleDesc.Count = _msaaSamples;
-			dsDesc.SampleDesc.Quality = 0;
-			dsDesc.Usage = D3D11_USAGE_DEFAULT;
-			dsDesc.CPUAccessFlags = 0;
-			dsDesc.MiscFlags = 0;
-			dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
-
-			ID3D11Device* device = s_renderD3D11->m_device;
-			DX_CHECK(device->CreateTexture2D(&dsDesc, NULL, &m_msaaTexture));
-			DX_CHECK(device->CreateShaderResourceView(m_msaaTexture, NULL, &m_msaaSv));
-			DX_CHECK(device->CreateRenderTargetView(m_msaaTexture, NULL, &m_msaaRtv));
+		if (NULL == m_mirrorTexture)
+		{
+			m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+			m_mirrorTextureDesc.Width  = _mirrorWidth;
+			m_mirrorTextureDesc.Height = _mirrorHeight;
+			ovrResult result = ovr_CreateMirrorTextureDX(_session, s_renderD3D11->m_device, &m_mirrorTextureDesc, &m_mirrorTexture);
+			BX_WARN(OVR_SUCCESS(result), "Could not create D3D11 OVR mirror texture");
+			BX_UNUSED(result);
 		}
 		}
 	}
 	}
 
 
-	void OVRBufferD3D11::render(const ovrSession& _session)
+	void OVRRenderD3D11::startEyeRender(const ovrSession& _session, int _eyeIdx)
 	{
 	{
 		ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
 		ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
 		float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Important that alpha=0, if want pixels to be transparent, for manual layers
 		float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Important that alpha=0, if want pixels to be transparent, for manual layers
 
 
 		// render to MSAA target
 		// render to MSAA target
-		if (NULL != m_msaaTexture)
+		if (NULL != m_msaaTexture[_eyeIdx])
 		{
 		{
-			deviceCtx->OMSetRenderTargets(1, &m_msaaRtv, m_depthBuffer);
-			deviceCtx->ClearRenderTargetView(m_msaaRtv, black);
-			deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
+			deviceCtx->OMSetRenderTargets(1, &m_msaaRtv[_eyeIdx], m_depthBuffer[_eyeIdx]);
+			deviceCtx->ClearRenderTargetView(m_msaaRtv[_eyeIdx], black);
+			deviceCtx->ClearDepthStencilView(m_depthBuffer[_eyeIdx], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
 		}
 		}
 		else // MSAA disabled? render directly to eye buffer
 		else // MSAA disabled? render directly to eye buffer
 		{
 		{
 			int texIndex = 0;
 			int texIndex = 0;
-			ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex);
+			ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &texIndex);
 
 
-			deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
-			deviceCtx->ClearRenderTargetView(m_eyeRtv[texIndex], black);
-			deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
+			deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[_eyeIdx][texIndex], m_depthBuffer[_eyeIdx]);
+			deviceCtx->ClearRenderTargetView(m_eyeRtv[_eyeIdx][texIndex], black);
+			deviceCtx->ClearDepthStencilView(m_depthBuffer[_eyeIdx], D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
 
 
 			D3D11_VIEWPORT D3Dvp;
 			D3D11_VIEWPORT D3Dvp;
 			D3Dvp.TopLeftX = 0;
 			D3Dvp.TopLeftX = 0;
 			D3Dvp.TopLeftY = 0;
 			D3Dvp.TopLeftY = 0;
-			D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
-			D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
+			D3Dvp.Width = (FLOAT)m_eyeTextureSize[_eyeIdx].w;
+			D3Dvp.Height = (FLOAT)m_eyeTextureSize[_eyeIdx].h;
 			D3Dvp.MinDepth = 0;
 			D3Dvp.MinDepth = 0;
 			D3Dvp.MaxDepth = 1;
 			D3Dvp.MaxDepth = 1;
 			deviceCtx->RSSetViewports(1, &D3Dvp);
 			deviceCtx->RSSetViewports(1, &D3Dvp);
 		}
 		}
 	}
 	}
 
 
-	void OVRBufferD3D11::postRender(const ovrSession& _session)
+	void OVRRenderD3D11::postRender(const ovrSession& _session, int _eyeIdx)
 	{
 	{
-		if (NULL != m_msaaTexture)
+		if (NULL != m_msaaTexture[_eyeIdx])
 		{
 		{
 			ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
 			ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
 			int destIndex = 0;
 			int destIndex = 0;
-			ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &destIndex);
+			ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &destIndex);
 			ID3D11Resource* dstTex = NULL;
 			ID3D11Resource* dstTex = NULL;
-			ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, destIndex, IID_PPV_ARGS(&dstTex));
-			deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
+			ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain[_eyeIdx], destIndex, IID_PPV_ARGS(&dstTex));
+			deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture[_eyeIdx], 0, DXGI_FORMAT_R8G8B8A8_UNORM);
 			dstTex->Release();
 			dstTex->Release();
 		}
 		}
 	}
 	}
 
 
-	void OVRBufferD3D11::destroy(const ovrSession& _session)
+	void OVRRenderD3D11::destroy(const ovrSession& _session)
 	{
 	{
-		for (uint32_t ii = 0; ii < BX_COUNTOF(m_eyeRtv); ++ii)
+		for (int eye = 0; eye < 2; ++eye)
 		{
 		{
-			DX_RELEASE(m_eyeRtv[ii], 0);
-		}
+			for (uint32_t ii = 0; ii < BX_COUNTOF(m_eyeRtv); ++ii)
+			{
+				DX_RELEASE(m_eyeRtv[eye][ii], 0);
+			}
 
 
-		ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
-		m_depthBuffer->Release();
+			ovr_DestroyTextureSwapChain(_session, m_textureSwapChain[eye]);
+			m_textureSwapChain[eye] = NULL;
+			m_depthBuffer[eye]->Release();
 
 
-		if (NULL != m_msaaTexture)
-		{
-			m_msaaTexture->Release();
-			m_msaaTexture = NULL;
-		}
+			if (NULL != m_msaaTexture[eye])
+			{
+				m_msaaTexture[eye]->Release();
+				m_msaaTexture[eye] = NULL;
+			}
 
 
-		if (NULL != m_msaaSv)
-		{
-			m_msaaSv->Release();
-			m_msaaSv = NULL;
+			if (NULL != m_msaaSv[eye])
+			{
+				m_msaaSv[eye]->Release();
+				m_msaaSv[eye] = NULL;
+			}
+
+			if (NULL != m_msaaRtv[eye])
+			{
+				m_msaaRtv[eye]->Release();
+				m_msaaRtv[eye] = NULL;
+			}
 		}
 		}
 
 
-		if (NULL != m_msaaRtv)
+		if (NULL != m_mirrorTexture)
 		{
 		{
-			m_msaaRtv->Release();
-			m_msaaRtv = NULL;
+			ovr_DestroyMirrorTexture(_session, m_mirrorTexture);
+			m_mirrorTexture = NULL;
 		}
 		}
 	}
 	}
 
 
-	void OVRMirrorD3D11::create(const ovrSession& _session, int _width, int _height)
+	void OVRRenderD3D11::blitMirror(const ovrSession& _session)
 	{
 	{
-		m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
-		m_mirrorTextureDesc.Width  = _width;
-		m_mirrorTextureDesc.Height = _height;
-		ovrResult result = ovr_CreateMirrorTextureDX(_session, s_renderD3D11->m_device, &m_mirrorTextureDesc, &m_mirrorTexture);
-		BX_WARN(OVR_SUCCESS(result), "Could not create D3D11 OVR mirror texture");
-		BX_UNUSED(result);
-	}
-
-		void OVRMirrorD3D11::destroy(const ovrSession& session)
+		if (NULL != m_mirrorTexture)
 		{
 		{
-			if (NULL != m_mirrorTexture)
-			{
-				ovr_DestroyMirrorTexture(session, m_mirrorTexture);
-				m_mirrorTexture = NULL;
-			}
-		}
+			ID3D11Texture2D* tex = NULL;
+			ovr_GetMirrorTextureBufferDX(_session, m_mirrorTexture, IID_PPV_ARGS(&tex) );
+			ID3D11Texture2D* backBuffer;
+			DX_CHECK(s_renderD3D11->m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) );
 
 
-		void OVRMirrorD3D11::blit(const ovrSession& _session)
-		{
-			if (NULL != m_mirrorTexture)
-			{
-				ID3D11Texture2D* tex = NULL;
-				ovr_GetMirrorTextureBufferDX(_session, m_mirrorTexture, IID_PPV_ARGS(&tex) );
-				ID3D11Texture2D* backBuffer;
-				DX_CHECK(s_renderD3D11->m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) );
+			s_renderD3D11->m_deviceCtx->CopyResource(backBuffer, tex);
+			DX_CHECK(s_renderD3D11->m_swapChain->Present(0, 0) );
 
 
-				s_renderD3D11->m_deviceCtx->CopyResource(backBuffer, tex);
-				DX_CHECK(s_renderD3D11->m_swapChain->Present(0, 0) );
+			DX_RELEASE(tex, 1);
+			DX_RELEASE(backBuffer, 0);
+		}
+	}
 
 
-				DX_RELEASE(tex, 1);
-				DX_RELEASE(backBuffer, 0);
-			}
+	void OVRRenderD3D11::preReset(const ovrSession& _session)
+	{
+		if (NULL != m_mirrorTexture)
+		{
+			ovr_DestroyMirrorTexture(_session, m_mirrorTexture);
+			m_mirrorTexture = NULL;
 		}
 		}
+	}
+
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
 
 
 	struct UavFormat
 	struct UavFormat

+ 14 - 17
src/renderer_d3d11.h

@@ -61,26 +61,23 @@ BX_PRAGMA_DIAGNOSTIC_POP()
 namespace bgfx { namespace d3d11
 namespace bgfx { namespace d3d11
 {
 {
 #if BGFX_CONFIG_USE_OVR
 #if BGFX_CONFIG_USE_OVR
-	struct OVRBufferD3D11 : public OVRBufferI
+	struct OVRRenderD3D11 : public OVRRenderI
 	{
 	{
-		virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE;
-		virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
-		virtual void render(const ovrSession& _session) BX_OVERRIDE;
-		virtual void postRender(const ovrSession& _session) BX_OVERRIDE;
-
-		ID3D11RenderTargetView* m_eyeRtv[4];
-		ID3D11DepthStencilView* m_depthBuffer;
-		ID3D11Texture2D* m_msaaTexture;
-		ID3D11ShaderResourceView* m_msaaSv;
-		ID3D11RenderTargetView* m_msaaRtv;
+		OVRRenderD3D11();
+		virtual void create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight);
+		virtual void destroy(const ovrSession& _session);
+		virtual void preReset(const ovrSession& _session);
+		virtual void startEyeRender(const ovrSession& _session, int _eyeIdx);
+		virtual void postRender(const ovrSession& _session, int _eyeIdx);
+		virtual void blitMirror(const ovrSession& _session);
+
+		ID3D11RenderTargetView* m_eyeRtv[2][4];
+		ID3D11DepthStencilView* m_depthBuffer[2];
+		ID3D11Texture2D* m_msaaTexture[2];
+		ID3D11ShaderResourceView* m_msaaSv[2];
+		ID3D11RenderTargetView* m_msaaRtv[2];
 	};
 	};
 
 
-	struct OVRMirrorD3D11 : public OVRMirrorI
-	{
-		virtual void create(const ovrSession& _session, int _width, int _height) BX_OVERRIDE;
-		virtual void destroy(const ovrSession& session) BX_OVERRIDE;
-		virtual void blit(const ovrSession& session) BX_OVERRIDE;
-	};
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
 
 
 	struct BufferD3D11
 	struct BufferD3D11

+ 170 - 159
src/renderer_gl.cpp

@@ -2961,19 +2961,8 @@ namespace bgfx { namespace gl
 				{
 				{
 					const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
 					const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
 
 
-					for (uint32_t ii = 0; ii < 2; ++ii)
-					{
-						// eye buffers need to be initialized only once during application lifetime
-						if (NULL == m_ovr.m_eyeBuffers[ii])
-						{
-							m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii];
-							m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
-						}
-					}
-
-					// recreate mirror texture
-					m_ovr.m_mirror = &m_ovrMirror;
-					m_ovr.m_mirror->create(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height);
+					m_ovr.m_render = &m_ovrRender;
+					m_ovr.m_render->create(m_ovr.m_hmd, msaaSamples, m_resolution.m_width, m_resolution.m_height);
 				}
 				}
 			}
 			}
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
@@ -3407,8 +3396,7 @@ namespace bgfx { namespace gl
 
 
 		OVR m_ovr;
 		OVR m_ovr;
 #if BGFX_CONFIG_USE_OVR
 #if BGFX_CONFIG_USE_OVR
-		OVRMirrorGL m_ovrMirror;
-		OVRBufferGL m_ovrBuffers[2];
+		OVRRenderGL m_ovrRender;
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
 	};
 	};
 
 
@@ -3429,194 +3417,207 @@ namespace bgfx { namespace gl
 	}
 	}
 
 
 #if BGFX_CONFIG_USE_OVR
 #if BGFX_CONFIG_USE_OVR
-	void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
+	OVRRenderGL::OVRRenderGL()
 	{
 	{
-		m_eyeFbo = 0;
-		m_eyeTexId = 0;
-		m_depthBuffer = 0;
-		m_msaaEyeFbo = 0;
-		m_msaaEyeTexId = 0;
-		m_msaaDepthBuffer = 0;
-
-		ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
-		m_eyeTextureSize = ovr_GetFovTextureSize(_session, ovrEyeType(_eyeIdx), hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f);
-
-		ovrTextureSwapChainDesc desc = {};
-		desc.Type = ovrTexture_2D;
-		desc.ArraySize = 1;
-		desc.Width  = m_eyeTextureSize.w;
-		desc.Height = m_eyeTextureSize.h;
-		desc.MipLevels = 1;
-		desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
-		desc.SampleCount = 1;
-		desc.StaticImage = ovrFalse;
-
-		ovr_CreateTextureSwapChainGL(_session, &desc, &m_textureSwapChain);
-
-		int textureCount = 0;
-		ovr_GetTextureSwapChainLength(_session, m_textureSwapChain, &textureCount);
-
-		for (int j = 0; j < textureCount; ++j)
-		{
-			GLuint chainTexId;
-			ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, j, &chainTexId);
-			GL_CHECK(glBindTexture(GL_TEXTURE_2D, chainTexId) );
-
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
-		}
-
-		GL_CHECK(glGenFramebuffers(1, &m_eyeFbo) );
-
-		// create depth buffer
-		GL_CHECK(glGenTextures(1, &m_depthBuffer) );
-		GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer) );
-		GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
-		GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
-		GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
-		GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
-
-		GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) );
-
-		// create MSAA buffers
-		if (_msaaSamples > 1)
-		{
-			GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo) );
-
-			// create color MSAA texture
-			GL_CHECK(glGenTextures(1, &m_msaaEyeTexId) );
-			GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId) );
-
-			GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_RGBA, m_eyeTextureSize.w, m_eyeTextureSize.h, false) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
-
-			// create MSAA depth buffer
-			GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer) );
-			GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer) );
-
-			GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, m_eyeTextureSize.w, m_eyeTextureSize.h, false) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
-			GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
+		memset(&m_eyeFbo, 0, sizeof(m_eyeFbo));
+		m_mirrorFBO = 0;
+	}
+
+	void OVRRenderGL::create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight)
+	{
+		for (int eye = 0; eye < 2; ++eye)
+		{
+			if (NULL == m_textureSwapChain[eye])
+			{
+				m_eyeFbo[eye] = 0;
+				m_eyeTexId[eye] = 0;
+				m_depthBuffer[eye] = 0;
+				m_msaaEyeFbo[eye] = 0;
+				m_msaaEyeTexId[eye] = 0;
+				m_msaaDepthBuffer[eye] = 0;
+
+				ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
+				m_eyeTextureSize[eye] = ovr_GetFovTextureSize(_session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1.0f);
+
+				ovrTextureSwapChainDesc desc = {};
+				desc.Type = ovrTexture_2D;
+				desc.ArraySize = 1;
+				desc.Width  = m_eyeTextureSize[eye].w;
+				desc.Height = m_eyeTextureSize[eye].h;
+				desc.MipLevels = 1;
+				desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+				desc.SampleCount = 1;
+				desc.StaticImage = ovrFalse;
+
+				ovr_CreateTextureSwapChainGL(_session, &desc, &m_textureSwapChain[eye]);
+
+				int textureCount = 0;
+				ovr_GetTextureSwapChainLength(_session, m_textureSwapChain[eye], &textureCount);
+
+				for (int j = 0; j < textureCount; ++j)
+				{
+					GLuint chainTexId;
+					ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain[eye], j, &chainTexId);
+					GL_CHECK(glBindTexture(GL_TEXTURE_2D, chainTexId) );
+
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
+				}
+
+				GL_CHECK(glGenFramebuffers(1, &m_eyeFbo[eye]) );
+
+				// create depth buffer
+				GL_CHECK(glGenTextures(1, &m_depthBuffer[eye]) );
+				GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer[eye]) );
+				GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
+				GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
+				GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
+				GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
+
+				GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize[eye].w, m_eyeTextureSize[eye].h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) );
+
+				// create MSAA buffers
+				if (_msaaSamples > 1)
+				{
+					GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo[eye]) );
+
+					// create color MSAA texture
+					GL_CHECK(glGenTextures(1, &m_msaaEyeTexId[eye]) );
+					GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[eye]) );
+
+					GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_RGBA, m_eyeTextureSize[eye].w, m_eyeTextureSize[eye].h, false) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
+
+					// create MSAA depth buffer
+					GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer[eye]) );
+					GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer[eye]) );
+
+					GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, m_eyeTextureSize[eye].w, m_eyeTextureSize[eye].h, false) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
+					GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
+				}
+			}
+		}
+
+		if (NULL == m_mirrorTexture)
+		{
+			memset(&m_mirrorTextureDesc, 0, sizeof(m_mirrorTextureDesc) );
+			m_mirrorTextureDesc.Width  = _mirrorWidth;
+			m_mirrorTextureDesc.Height = _mirrorHeight;
+			m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
+
+			ovr_CreateMirrorTextureGL(_session, &m_mirrorTextureDesc, &m_mirrorTexture);
+
+			// Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes
+			if (!m_mirrorTexture)
+				return;
+
+			// Configure the mirror read buffer
+			GLuint texId;
+			ovr_GetMirrorTextureBufferGL(_session, m_mirrorTexture, &texId);
+			GL_CHECK(glGenFramebuffers(1, &m_mirrorFBO) );
+			GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO) );
+			GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0) );
+			GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
+			GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) );
+
+			if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+			{
+				GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) );
+				BX_CHECK(false, "Could not initialize VR buffers!");
+			}
 		}
 		}
 	}
 	}
 
 
-	void OVRBufferGL::render(const ovrSession& _session)
+	void OVRRenderGL::startEyeRender(const ovrSession& _session, int _eyeIdx)
 	{
 	{
 		// set the current eye texture in swap chain
 		// set the current eye texture in swap chain
 		int curIndex;
 		int curIndex;
-		ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex);
-		ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId);
+		ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain[_eyeIdx], &curIndex);
+		ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain[_eyeIdx], curIndex, &m_eyeTexId[_eyeIdx]);
 
 
 		if (0 != m_msaaEyeFbo)
 		if (0 != m_msaaEyeFbo)
 		{
 		{
-			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo) );
-			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) );
-			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer, 0) );
+			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo[_eyeIdx]) );
+			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[_eyeIdx], 0) );
+			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer[_eyeIdx], 0) );
 		}
 		}
 		else // MSAA disabled? render directly to eye buffer
 		else // MSAA disabled? render directly to eye buffer
 		{
 		{
-			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo) );
-			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
-			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0) );
+			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo[_eyeIdx]) );
+			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[_eyeIdx], 0) );
+			GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer[_eyeIdx], 0) );
 		}
 		}
-		GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h) );
+		GL_CHECK(glViewport(0, 0, m_eyeTextureSize[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h) );
 		GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );
 		GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );
 	}
 	}
 
 
-	void OVRBufferGL::postRender(const ovrSession& /*_sesion*/)
+	void OVRRenderGL::postRender(const ovrSession& /*_sesion*/, int _eyeIdx)
 	{
 	{
-		if (0 != m_msaaEyeFbo && 0 != m_eyeTexId)
+		if (0 != m_msaaEyeFbo[_eyeIdx] && 0 != m_eyeTexId[_eyeIdx])
 		{
 		{
 			// blit the contents of MSAA FBO to the regular eye buffer "connected" to the HMD
 			// blit the contents of MSAA FBO to the regular eye buffer "connected" to the HMD
-			GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo));
-			GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) );
+			GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo[_eyeIdx]));
+			GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[_eyeIdx], 0) );
 			GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
 			GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
 
 
 			BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)
 			BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)
 					 , "glCheckFramebufferStatus failed 0x%08x"
 					 , "glCheckFramebufferStatus failed 0x%08x"
 					 , glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) );
 					 , glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) );
 
 
-			GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo));
-			GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
+			GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo[_eyeIdx]));
+			GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[_eyeIdx], 0) );
 			GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
 			GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
 
 
 			BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
 			BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
 					 , "glCheckFramebufferStatus failed 0x%08x"
 					 , "glCheckFramebufferStatus failed 0x%08x"
 					 , glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) );
 					 , glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) );
 
 
-			GL_CHECK(glBlitFramebuffer(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h,
-					 0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h, GL_COLOR_BUFFER_BIT, GL_NEAREST) );
+			GL_CHECK(glBlitFramebuffer(0, 0, m_eyeTextureSize[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h,
+					 0, 0, m_eyeTextureSize[_eyeIdx].w, m_eyeTextureSize[_eyeIdx].h, GL_COLOR_BUFFER_BIT, GL_NEAREST) );
 
 
 			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
 			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
 		}
 		}
 	}
 	}
 
 
-	void OVRBufferGL::destroy(const ovrSession& _session)
+	void OVRRenderGL::destroy(const ovrSession& _session)
 	{
 	{
-		GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo) );
-		GL_CHECK(glDeleteTextures(1, &m_depthBuffer) );
-
-		ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
-
-		if (0 != m_msaaEyeFbo)
+		for (int eye = 0; eye < 2; ++eye)
 		{
 		{
-			GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) );
-			m_msaaEyeFbo = 0;
-		}
+			GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo[eye]) );
+			GL_CHECK(glDeleteTextures(1, &m_depthBuffer[eye]) );
 
 
-		if (0 != m_msaaEyeTexId)
-		{
-			GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId));
-			m_msaaEyeTexId = 0;
-		}
+			ovr_DestroyTextureSwapChain(_session, m_textureSwapChain[eye]);
+			m_textureSwapChain[eye] = NULL;
 
 
-		if (0 != m_msaaDepthBuffer)
-		{
-			GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer));
-			m_msaaDepthBuffer = 0;
-		}
-	}
-
-	void OVRMirrorGL::create(const ovrSession& _session, int _width, int _height)
-	{
-		memset(&m_mirrorTextureDesc, 0, sizeof(m_mirrorTextureDesc) );
-		m_mirrorTextureDesc.Width  = _width;
-		m_mirrorTextureDesc.Height = _height;
-		m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
-
-		ovr_CreateMirrorTextureGL(_session, &m_mirrorTextureDesc, &m_mirrorTexture);
-
-		// Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes
-		if (!m_mirrorTexture)
-			return;
+			if (0 != m_msaaEyeFbo[eye])
+			{
+				GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo[eye]) );
+				m_msaaEyeFbo[eye] = 0;
+			}
 
 
-		// Configure the mirror read buffer
-		GLuint texId;
-		ovr_GetMirrorTextureBufferGL(_session, m_mirrorTexture, &texId);
-		GL_CHECK(glGenFramebuffers(1, &m_mirrorFBO) );
-		GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO) );
-		GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0) );
-		GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
-		GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) );
+			if (0 != m_msaaEyeTexId[eye])
+			{
+				GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId[eye]));
+				m_msaaEyeTexId[eye] = 0;
+			}
 
 
-		if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
-		{
-			GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) );
-			BX_CHECK(false, "Could not initialize VR buffers!");
+			if (0 != m_msaaDepthBuffer[eye])
+			{
+				GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer[eye]));
+				m_msaaDepthBuffer[eye] = 0;
+			}
 		}
 		}
-	}
 
 
-	void OVRMirrorGL::destroy(const ovrSession& _session)
-	{
 		if (NULL != m_mirrorTexture)
 		if (NULL != m_mirrorTexture)
 		{
 		{
 			GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) );
 			GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) );
@@ -3625,7 +3626,7 @@ namespace bgfx { namespace gl
 		}
 		}
 	}
 	}
 
 
-	void OVRMirrorGL::blit(const ovrSession& /*_session*/)
+	void OVRRenderGL::blitMirror(const ovrSession& /*_session*/)
 	{
 	{
 		if (NULL != m_mirrorTexture)
 		if (NULL != m_mirrorTexture)
 		{
 		{
@@ -3638,6 +3639,16 @@ namespace bgfx { namespace gl
 			GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) );
 			GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) );
 		}
 		}
 	}
 	}
+
+	void OVRRenderGL::preReset(const ovrSession& _session)
+	{
+		if (NULL != m_mirrorTexture)
+		{
+			GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) );
+			ovr_DestroyMirrorTexture(_session, m_mirrorTexture);
+			m_mirrorTexture = NULL;
+		}
+	}
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
 
 
 	const char* glslTypeName(GLuint _type)
 	const char* glslTypeName(GLuint _type)

+ 16 - 20
src/renderer_gl.h

@@ -951,29 +951,25 @@ namespace bgfx
 namespace bgfx { namespace gl
 namespace bgfx { namespace gl
 {
 {
 #if BGFX_CONFIG_USE_OVR
 #if BGFX_CONFIG_USE_OVR
-	struct OVRBufferGL : public OVRBufferI
+	struct OVRRenderGL : public OVRRenderI
 	{
 	{
-		virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE;
-		virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
-		virtual void render(const ovrSession& _session) BX_OVERRIDE;
-		virtual void postRender(const ovrSession& _sesion) BX_OVERRIDE;
-
-		GLuint m_eyeFbo;
-		GLuint m_eyeTexId;
-		GLuint m_depthBuffer;
-		GLuint m_msaaEyeFbo;
-		GLuint m_msaaEyeTexId;
-		GLuint m_msaaDepthBuffer;
-	};
-
-	struct OVRMirrorGL : public OVRMirrorI
-	{
-		virtual void create(const ovrSession& _session, int _width, int _height) BX_OVERRIDE;
-		virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
-		virtual void blit(const ovrSession& _session) BX_OVERRIDE;
-
+		OVRRenderGL();
+		virtual void create(const ovrSession& _session, int _msaaSamples, int _mirrorWidth, int _mirrorHeight);
+		virtual void destroy(const ovrSession& _session);
+		virtual void preReset(const ovrSession& _session);
+		virtual void startEyeRender(const ovrSession& _session, int _eyeIdx);
+		virtual void postRender(const ovrSession& _session, int _eyeIdx);
+		virtual void blitMirror(const ovrSession& _session);
+
+		GLuint m_eyeFbo[2];
+		GLuint m_eyeTexId[2];
+		GLuint m_depthBuffer[2];
+		GLuint m_msaaEyeFbo[2];
+		GLuint m_msaaEyeTexId[2];
+		GLuint m_msaaDepthBuffer[2];
 		GLuint m_mirrorFBO;
 		GLuint m_mirrorFBO;
 	};
 	};
+
 #endif // BGFX_CONFIG_USE_OVR
 #endif // BGFX_CONFIG_USE_OVR
 
 
 	void dumpExtensions(const char* _extensions);
 	void dumpExtensions(const char* _extensions);