OculusVR: added MSAA support

This commit is contained in:
Krzysztof Kondrak 2016-04-09 18:39:08 +02:00
parent 3363d8f5cd
commit c5acc53c6b
6 changed files with 203 additions and 34 deletions

View File

@ -152,6 +152,7 @@ namespace bgfx
for (uint32_t ii = 0; ii < 2; ++ii)
{
m_eyeBuffers[ii]->postRender(m_hmd);
result = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[ii]->m_textureSwapChain);
if (!OVR_SUCCESS(result) )
{

View File

@ -31,10 +31,10 @@ namespace bgfx
struct OVRBufferI
{
virtual ~OVRBufferI() {};
virtual void create(const ovrSession& _session, int _eyeIdx) = 0;
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) = 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;
};

View File

@ -2156,7 +2156,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ovrPostReset();
// If OVR doesn't create separate depth stencil view, create default one.
if (NULL == m_backBufferDepthStencil)
if (!m_ovr.isEnabled() && NULL == m_backBufferDepthStencil)
{
D3D11_TEXTURE2D_DESC dsd;
dsd.Width = getBufferWidth();
@ -3120,13 +3120,15 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{
if (m_ovr.postReset() )
{
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);
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
}
}
@ -3590,10 +3592,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
#if BGFX_CONFIG_USE_OVR
void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx)
void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
{
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;
@ -3641,7 +3646,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
dbDesc.MipLevels = 1;
dbDesc.ArraySize = 1;
dbDesc.Format = DXGI_FORMAT_D32_FLOAT;
dbDesc.SampleDesc.Count = 1;
dbDesc.SampleDesc.Count = _msaaSamples;
dbDesc.SampleDesc.Quality = 0;
dbDesc.Usage = D3D11_USAGE_DEFAULT;
dbDesc.CPUAccessFlags = 0;
@ -3651,29 +3656,74 @@ BX_PRAGMA_DIAGNOSTIC_POP();
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));
}
}
void OVRBufferD3D11::render(const ovrSession& _session)
{
// Clear and set up rendertarget
int texIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex);
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
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);
D3D11_VIEWPORT D3Dvp;
D3Dvp.TopLeftX = 0;
D3Dvp.TopLeftY = 0;
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
deviceCtx->RSSetViewports(1, &D3Dvp);
// render to MSAA target
if (NULL != m_msaaTexture)
{
deviceCtx->OMSetRenderTargets(1, &m_msaaRtv, m_depthBuffer);
deviceCtx->ClearRenderTargetView(m_msaaRtv, black);
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
}
else // MSAA disabled? render directly to eye buffer
{
int texIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &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);
D3D11_VIEWPORT D3Dvp;
D3Dvp.TopLeftX = 0;
D3Dvp.TopLeftY = 0;
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
deviceCtx->RSSetViewports(1, &D3Dvp);
}
}
void OVRBufferD3D11::postRender(const ovrSession& _session)
{
if (NULL != m_msaaTexture)
{
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
int destIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &destIndex);
ID3D11Resource* dstTex = NULL;
ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, destIndex, IID_PPV_ARGS(&dstTex));
deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
dstTex->Release();
}
}
void OVRBufferD3D11::destroy(const ovrSession& _session)
@ -3685,6 +3735,24 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
m_depthBuffer->Release();
if (NULL != m_msaaTexture)
{
m_msaaTexture->Release();
m_msaaTexture = NULL;
}
if (NULL != m_msaaSv)
{
m_msaaSv->Release();
m_msaaSv = NULL;
}
if (NULL != m_msaaRtv)
{
m_msaaRtv->Release();
m_msaaRtv = NULL;
}
}
void OVRMirrorD3D11::create(const ovrSession& _session, int _width, int _height)

View File

@ -63,12 +63,16 @@ namespace bgfx { namespace d3d11
#if BGFX_CONFIG_USE_OVR
struct OVRBufferD3D11 : public OVRBufferI
{
virtual void create(const ovrSession& _session, int _eyeIdx) BX_OVERRIDE;
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;
};
struct OVRMirrorD3D11 : public OVRMirrorI

View File

@ -2864,13 +2864,15 @@ namespace bgfx { namespace gl
{
if (m_ovr.postReset() )
{
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);
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
}
}
@ -3332,8 +3334,15 @@ namespace bgfx { namespace gl
}
#if BGFX_CONFIG_USE_OVR
void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx)
void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
{
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);
@ -3375,6 +3384,35 @@ namespace bgfx { namespace gl
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) );
}
}
void OVRBufferGL::render(const ovrSession& _session)
@ -3384,20 +3422,74 @@ namespace bgfx { namespace gl
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex);
ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId);
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) );
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) );
}
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(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h) );
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );
}
void OVRBufferGL::postRender(const ovrSession& /*_sesion*/)
{
if (0 != m_msaaEyeFbo && 0 != m_eyeTexId)
{
// 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(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)
, "glCheckFramebufferStatus failed 0x%08x"
, 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(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
, "glCheckFramebufferStatus failed 0x%08x"
, 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(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}
}
void OVRBufferGL::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)
{
GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) );
m_msaaEyeFbo = 0;
}
if (0 != m_msaaEyeTexId)
{
GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId));
m_msaaEyeTexId = 0;
}
if (0 != m_msaaDepthBuffer)
{
GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer));
m_msaaDepthBuffer = 0;
}
}
void OVRMirrorGL::create(const ovrSession& _session, int _width, int _height)

View File

@ -905,13 +905,17 @@ namespace bgfx { namespace gl
#if BGFX_CONFIG_USE_OVR
struct OVRBufferGL : public OVRBufferI
{
virtual void create(const ovrSession& _session, int _eyeIdx) BX_OVERRIDE;
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
@ -1285,8 +1289,8 @@ namespace bgfx { namespace gl
void create(const ShaderGL& _vsh, const ShaderGL& _fsh);
void destroy();
void init();
void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const;
void init();
void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const;
void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const;
void add(uint32_t _hash)
@ -1300,8 +1304,8 @@ namespace bgfx { namespace gl
GLint m_attributes[Attrib::Count]; // sparse
GLint m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT+1];
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint8_t m_numSamplers;
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint8_t m_numSamplers;
UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];