diff options
author | 2016-10-29 09:11:50 +0200 | |
---|---|---|
committer | 2016-10-29 09:11:50 +0200 | |
commit | a3b4058bf7266f1291cf38c30425d9948250fcd9 (patch) | |
tree | 46116c48b60368ac9c782c1d5e6e8ae16e558987 /3rdparty/bgfx/src/renderer_gl.cpp | |
parent | b99be73f2db5d3f81edc96a92ac4839e7f1cc3ab (diff) |
Updated BGFX and BX and recompiled shaders (nw)
Diffstat (limited to '3rdparty/bgfx/src/renderer_gl.cpp')
-rw-r--r-- | 3rdparty/bgfx/src/renderer_gl.cpp | 643 |
1 files changed, 376 insertions, 267 deletions
diff --git a/3rdparty/bgfx/src/renderer_gl.cpp b/3rdparty/bgfx/src/renderer_gl.cpp index 75e3a4ef3a7..73122fe74ff 100644 --- a/3rdparty/bgfx/src/renderer_gl.cpp +++ b/3rdparty/bgfx/src/renderer_gl.cpp @@ -9,6 +9,7 @@ # include "renderer_gl.h" # include <bx/timer.h> # include <bx/uint32_t.h> +# include "hmd_ovr.h" #if BGFX_CONFIG_PROFILER_REMOTERY # define BGFX_GPU_PROFILER_BIND() rmt_BindOpenGL() @@ -1014,6 +1015,10 @@ namespace bgfx { namespace gl } } + static void GL_APIENTRY stubPolygonMode(GLenum /*_face*/, GLenum /*_mode*/) + { + } + typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height); static const char* getGLString(GLenum _name) @@ -1131,7 +1136,7 @@ namespace bgfx { namespace gl void flushGlError() { - for (GLenum err = glGetError(); err != 0; err = glGetError()); + for (GLenum err = glGetError(); err != 0; err = glGetError() ); } GLenum initTestTexture(TextureFormat::Enum _format, bool _srgb, bool _mipmaps) @@ -1352,6 +1357,47 @@ namespace bgfx { namespace gl BX_UNUSED(supported); } +#if BGFX_CONFIG_USE_OVR + class VRImplOVRGL : public VRImplOVR + { + public: + VRImplOVRGL(); + + virtual bool createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) BX_OVERRIDE; + virtual void destroySwapChain() BX_OVERRIDE; + virtual void destroyMirror() BX_OVERRIDE; + virtual void renderEyeStart(const VRDesc& _desc, uint8_t _eye) BX_OVERRIDE; + virtual bool submitSwapChain(const VRDesc& _desc) BX_OVERRIDE; + + private: + GLuint m_eyeFbo[2]; + GLuint m_eyeTexId[2][4]; + GLuint m_depthBuffer[2]; + GLuint m_msaaEyeFbo[2]; + GLuint m_msaaEyeTexId[2]; + GLuint m_msaaDepthBuffer[2]; + GLuint m_mirrorFbo; + GLint m_mirrorWidth; + GLint m_mirrorHeight; + + ovrTextureSwapChain m_textureSwapChain[2]; + ovrMirrorTexture m_mirrorTexture; + }; +#endif // BGFX_CONFIG_USE_OVR + + struct VendorId + { + const char* name; + uint16_t id; + }; + + static const VendorId s_vendorIds[] = + { + { "NVIDIA Corporation", BGFX_PCI_ID_NVIDIA }, + { "Advanced Micro Devices, Inc.", BGFX_PCI_ID_AMD }, + { "Intel", BGFX_PCI_ID_INTEL }, + }; + struct RendererContextGL : public RendererContextI { RendererContextGL() @@ -1401,13 +1447,27 @@ namespace bgfx { namespace gl setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); // Must be after context is initialized?! - m_ovr.init(); + VRImplI* vrImpl = NULL; +#if BGFX_CONFIG_USE_OVR + vrImpl = &m_ovrRender; +#endif + m_ovr.init(vrImpl); m_vendor = getGLString(GL_VENDOR); m_renderer = getGLString(GL_RENDERER); m_version = getGLString(GL_VERSION); m_glslVersion = getGLString(GL_SHADING_LANGUAGE_VERSION); + for (uint32_t ii = 0; ii < BX_COUNTOF(s_vendorIds); ++ii) + { + const VendorId& vendorId = s_vendorIds[ii]; + if (0 == strncmp(vendorId.name, m_vendor, strlen(vendorId.name) ) ) + { + g_caps.vendorId = vendorId.id; + break; + } + } + GLint numCmpFormats = 0; GL_CHECK(glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCmpFormats) ); BX_TRACE("GL_NUM_COMPRESSED_TEXTURE_FORMATS %d", numCmpFormats); @@ -1872,6 +1932,11 @@ namespace bgfx { namespace gl : 0 ; + if (NULL == glPolygonMode) + { + glPolygonMode = stubPolygonMode; + } + if (s_extension[Extension::ARB_copy_image].m_supported || s_extension[Extension::EXT_copy_image].m_supported || s_extension[Extension:: NV_copy_image].m_supported @@ -1904,14 +1969,14 @@ namespace bgfx { namespace gl : 0 ; - g_caps.maxTextureSize = uint16_t(glGet(GL_MAX_TEXTURE_SIZE) ); + g_caps.limits.maxTextureSize = uint16_t(glGet(GL_MAX_TEXTURE_SIZE) ); if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) || BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 30) || s_extension[Extension::EXT_draw_buffers ].m_supported || s_extension[Extension::WEBGL_draw_buffers].m_supported) { - g_caps.maxFBAttachments = uint8_t(bx::uint32_min(glGet(GL_MAX_DRAW_BUFFERS) + g_caps.limits.maxFBAttachments = uint8_t(bx::uint32_min(glGet(GL_MAX_DRAW_BUFFERS) , BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) ); } @@ -2205,15 +2270,8 @@ namespace bgfx { namespace gl m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain); } - switch (m_ovr.swap(_hmd, true) ) - { - case OVR::DeviceLost: - ovrPreReset(); - break; - - default: - break; - } + m_ovr.flip(); + m_ovr.swap(_hmd); // TODO - move this out of end-of-frame // need to swap GL render context even if OVR is enabled to get the mirror texture in the output m_glctx.swap(); @@ -2321,7 +2379,7 @@ namespace bgfx { namespace gl { } - void readTexture(TextureHandle _handle, void* _data) BX_OVERRIDE + void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) BX_OVERRIDE { if (m_readBackSupported) { @@ -2333,14 +2391,14 @@ namespace bgfx { namespace gl if (compressed) { GL_CHECK(glGetCompressedTexImage(texture.m_target - , 0 + , _mip , _data ) ); } else { GL_CHECK(glGetTexImage(texture.m_target - , 0 + , _mip , texture.m_fmt , texture.m_type , _data @@ -2439,6 +2497,7 @@ namespace bgfx { namespace gl { BX_FREE(g_allocator, m_uniforms[_handle.idx]); m_uniforms[_handle.idx] = NULL; + m_uniformReg.remove(_handle); } void saveScreenShot(const char* _filePath) BX_OVERRIDE @@ -2956,24 +3015,8 @@ namespace bgfx { namespace gl #if BGFX_CONFIG_USE_OVR if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) ) { - 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, 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); - } + const uint32_t msaaSamples = 1 << ( (m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT); + m_ovr.postReset(msaaSamples, m_resolution.m_width, m_resolution.m_height); } #endif // BGFX_CONFIG_USE_OVR } @@ -3404,10 +3447,9 @@ namespace bgfx { namespace gl const char* m_version; const char* m_glslVersion; - OVR m_ovr; + VR m_ovr; #if BGFX_CONFIG_USE_OVR - OVRMirrorGL m_ovrMirror; - OVRBufferGL m_ovrBuffers[2]; + VRImplOVRGL m_ovrRender; #endif // BGFX_CONFIG_USE_OVR }; @@ -3428,215 +3470,247 @@ namespace bgfx { namespace gl } #if BGFX_CONFIG_USE_OVR - void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) + + VRImplOVRGL::VRImplOVRGL() + : m_mirrorTexture(NULL) + { + memset(&m_textureSwapChain, 0, sizeof(m_textureSwapChain) ); + } + + static void setDefaultSamplerState() { - m_eyeFbo = 0; - m_eyeTexId = 0; - m_depthBuffer = 0; - m_msaaEyeFbo = 0; - m_msaaEyeTexId = 0; - m_msaaDepthBuffer = 0; + 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) ); + } - ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session); - m_eyeTextureSize = ovr_GetFovTextureSize(_session, ovrEyeType(_eyeIdx), hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f); + bool VRImplOVRGL::createSwapChain(const VRDesc& _desc, int _msaaSamples, int _mirrorWidth, int _mirrorHeight) + { + for (int eye = 0; eye < 2; ++eye) + { + if (NULL == m_textureSwapChain[eye]) + { + m_eyeFbo[eye] = 0; + m_depthBuffer[eye] = 0; + m_msaaEyeFbo[eye] = 0; + m_msaaEyeTexId[eye] = 0; + m_msaaDepthBuffer[eye] = 0; + memset(&m_eyeTexId[eye], 0, sizeof(m_eyeTexId[eye]) ); + + ovrTextureSwapChainDesc swapchainDesc = {}; + swapchainDesc.Type = ovrTexture_2D; + swapchainDesc.ArraySize = 1; + swapchainDesc.Width = _desc.m_eyeSize[eye].m_w; + swapchainDesc.Height = _desc.m_eyeSize[eye].m_h; + swapchainDesc.MipLevels = 1; + swapchainDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + swapchainDesc.SampleCount = 1; + swapchainDesc.StaticImage = ovrFalse; + + ovrResult result = ovr_CreateTextureSwapChainGL(m_session, &swapchainDesc, &m_textureSwapChain[eye]); + if (!OVR_SUCCESS(result) ) + { + destroySwapChain(); + return false; + } - 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; + int textureCount = 0; + ovr_GetTextureSwapChainLength(m_session, m_textureSwapChain[eye], &textureCount); + for (int ii = 0; ii < textureCount; ++ii) + { + ovr_GetTextureSwapChainBufferGL(m_session, m_textureSwapChain[eye], ii, &m_eyeTexId[eye][ii]); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_eyeTexId[eye][ii]) ); + setDefaultSamplerState(); + } - ovr_CreateTextureSwapChainGL(_session, &desc, &m_textureSwapChain); + GL_CHECK(glGenFramebuffers(1, &m_eyeFbo[eye]) ); - int textureCount = 0; - ovr_GetTextureSwapChainLength(_session, m_textureSwapChain, &textureCount); + // create depth buffer + GL_CHECK(glGenTextures(1, &m_depthBuffer[eye]) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer[eye]) ); + setDefaultSamplerState(); - 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(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) ); - 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(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_eyeFbo[eye]) ); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer[eye], 0) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ); - GL_CHECK(glGenFramebuffers(1, &m_eyeFbo) ); + // create MSAA targets if needed + 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, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, false) ); + setDefaultSamplerState(); + + // create MSAA depth buffer + GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer[eye]) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_depthBuffer[eye]) ); + GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, false) ); + setDefaultSamplerState(); + + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo[eye]) ); + GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId[eye], 0) ); + GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ); + } - // 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) ); + m_renderLayer.ColorTexture[eye] = m_textureSwapChain[eye]; + } + } - GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) ); + m_renderLayer.Header.Flags |= ovrLayerFlag_TextureOriginAtBottomLeft; - // create MSAA buffers - if (_msaaSamples > 1) + if (NULL == m_mirrorTexture) { - GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo) ); + m_mirrorFbo = 0; - // create color MSAA texture - GL_CHECK(glGenTextures(1, &m_msaaEyeTexId) ); - GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId) ); + ovrMirrorTextureDesc mirrorDesc = {}; + mirrorDesc.Width = _mirrorWidth; + mirrorDesc.Height = _mirrorHeight; + mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; - 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) ); + // Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes + ovr_CreateMirrorTextureGL(m_session, &mirrorDesc, &m_mirrorTexture); + if (m_mirrorTexture) + { + m_mirrorWidth = _mirrorWidth; + m_mirrorHeight = _mirrorHeight; - // create MSAA depth buffer - GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer) ); - GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer) ); + // Configure the mirror read buffer + GLuint texId; + ovr_GetMirrorTextureBufferGL(m_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) ); - 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) ); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFbo) ); + ovr_DestroyMirrorTexture(m_session, m_mirrorTexture); + m_mirrorTexture = NULL; + BX_CHECK(false, "Could not initialize VR mirror buffers!"); + } + } } - } - - void OVRBufferGL::render(const ovrSession& _session) - { - // set the current eye texture in swap chain - int curIndex; - ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex); - ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId); - 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) ); + return true; } - void OVRBufferGL::postRender(const ovrSession& /*_sesion*/) + void VRImplOVRGL::destroySwapChain() { - if (0 != m_msaaEyeFbo && 0 != m_eyeTexId) + for (int eye = 0; eye < 2; ++eye) { - // 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) ); + if (NULL != m_textureSwapChain[eye]) + { + GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo[eye]) ); + GL_CHECK(glDeleteTextures(1, &m_depthBuffer[eye]) ); - 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) ); + ovr_DestroyTextureSwapChain(m_session, m_textureSwapChain[eye]); + m_textureSwapChain[eye] = NULL; - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + if (0 != m_msaaEyeFbo[eye]) + { + GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo[eye]) ); + GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId[eye]) ); + GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer[eye]) ); + m_msaaEyeFbo[eye] = 0; + } + } } + + destroyMirror(); } - void OVRBufferGL::destroy(const ovrSession& _session) + void VRImplOVRGL::destroyMirror() { - GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo) ); - GL_CHECK(glDeleteTextures(1, &m_depthBuffer) ); - - ovr_DestroyTextureSwapChain(_session, m_textureSwapChain); - - if (0 != m_msaaEyeFbo) + if (NULL != m_mirrorTexture) { - GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) ); - m_msaaEyeFbo = 0; + GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFbo) ); + ovr_DestroyMirrorTexture(m_session, m_mirrorTexture); + m_mirrorTexture = NULL; } + } - if (0 != m_msaaEyeTexId) + void VRImplOVRGL::renderEyeStart(const VRDesc& _desc, uint8_t _eye) + { + // set the current eye texture in the swap chain + if (0 != m_msaaEyeFbo[_eye]) { - GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId)); - m_msaaEyeTexId = 0; + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo[_eye]) ); } - - if (0 != m_msaaDepthBuffer) + else { - GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer)); - m_msaaDepthBuffer = 0; + int texIndex; + ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureSwapChain[_eye], &texIndex); + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo[_eye]) ); + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[_eye][texIndex], 0) ); } + + GL_CHECK(glViewport(0, 0, _desc.m_eyeSize[_eye].m_w, _desc.m_eyeSize[_eye].m_h) ); + GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ); } - void OVRMirrorGL::create(const ovrSession& _session, int _width, int _height) + bool VRImplOVRGL::submitSwapChain(const VRDesc& _desc) { - memset(&m_mirrorTextureDesc, 0, sizeof(m_mirrorTextureDesc) ); - m_mirrorTextureDesc.Width = _width; - m_mirrorTextureDesc.Height = _height; - m_mirrorTextureDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; + for (int eye = 0; eye < 2; ++eye) + { + if (0 != m_msaaEyeFbo[eye]) + { + // blit the contents of MSAA FBO to the regulare eye buffer "connected" to the HMD + int destIndex; + ovr_GetTextureSwapChainCurrentIndex(m_session, m_textureSwapChain[eye], &destIndex); - ovr_CreateMirrorTextureGL(_session, &m_mirrorTextureDesc, &m_mirrorTexture); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo[eye]) ); + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) + ); - // Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes - if (!m_mirrorTexture) - return; + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo[eye]) ); + GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId[eye][destIndex], 0) ); + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) + ); - // 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) ); + GL_CHECK(glBlitFramebuffer(0, 0, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, 0, 0, _desc.m_eyeSize[eye].m_w, _desc.m_eyeSize[eye].m_h, GL_COLOR_BUFFER_BIT, GL_NEAREST) ); + 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!"); + ovrResult result = ovr_CommitTextureSwapChain(m_session, m_textureSwapChain[eye]); + if (!OVR_SUCCESS(result) ) + { + return false; + } } - } - void OVRMirrorGL::destroy(const ovrSession& _session) - { - if (NULL != m_mirrorTexture) + ovrLayerHeader* layerList = &m_renderLayer.Header; + ovrResult result = ovr_SubmitFrame(m_session, 0, &m_viewScale, &layerList, 1); + if (!OVR_SUCCESS(result) ) { - GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO) ); - ovr_DestroyMirrorTexture(_session, m_mirrorTexture); - m_mirrorTexture = NULL; + return false; } - } - void OVRMirrorGL::blit(const ovrSession& /*_session*/) - { - if (NULL != m_mirrorTexture) + if (result != ovrSuccess_NotVisible && NULL != m_mirrorTexture) { - // Blit mirror texture to back buffer - GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFbo) ); GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ); - GLint width = m_mirrorTextureDesc.Width; - GLint height = m_mirrorTextureDesc.Height; - GL_CHECK(glBlitFramebuffer(0, height, width, 0, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST) ); + GL_CHECK(glBlitFramebuffer(0, m_mirrorHeight, m_mirrorWidth, 0, 0, 0, m_mirrorWidth, m_mirrorHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST) ); GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ); } + + return true; } + #endif // BGFX_CONFIG_USE_OVR const char* glslTypeName(GLuint _type) @@ -3689,6 +3763,7 @@ namespace bgfx { namespace gl GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_1D); GLSL_TYPE(GL_IMAGE_2D); + GLSL_TYPE(GL_IMAGE_2D_ARRAY); GLSL_TYPE(GL_INT_IMAGE_2D); GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_2D); @@ -3786,6 +3861,7 @@ namespace bgfx { namespace gl case GL_UNSIGNED_INT_IMAGE_1D: case GL_IMAGE_2D: + case GL_IMAGE_2D_ARRAY: case GL_INT_IMAGE_2D: case GL_UNSIGNED_INT_IMAGE_2D: @@ -4285,6 +4361,11 @@ namespace bgfx { namespace gl , const GLvoid* _data ) { + if (NULL == _data) + { + return; + } + if (_target == GL_TEXTURE_3D || _target == GL_TEXTURE_2D_ARRAY || _target == GL_TEXTURE_CUBE_MAP_ARRAY) @@ -4355,7 +4436,19 @@ namespace bgfx { namespace gl else if (_target == GL_TEXTURE_2D_ARRAY || _target == GL_TEXTURE_CUBE_MAP_ARRAY) { - texSubImage(_target, _level, 0, 0, _depth, _width, _height, 1, _format, _type, _data); + texSubImage( + _target + , _level + , 0 + , 0 + , _depth + , _width + , _height + , 1 + , _format + , _type + , _data + ); } else if (_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { @@ -5456,7 +5549,7 @@ namespace bgfx { namespace gl if (!!bx::findIdentifierMatch(code, "gl_FragData") ) { - for (uint32_t ii = 0, num = g_caps.maxFBAttachments; ii < num; ++ii) + for (uint32_t ii = 0, num = g_caps.limits.maxFBAttachments; ii < num; ++ii) { char tmpFragData[16]; bx::snprintf(tmpFragData, BX_COUNTOF(tmpFragData), "gl_FragData[%d]", ii); @@ -5546,7 +5639,7 @@ namespace bgfx { namespace gl if (!!bx::findIdentifierMatch(code, "gl_FragData") ) { - for (uint32_t ii = 0, num = g_caps.maxFBAttachments; ii < num; ++ii) + for (uint32_t ii = 0, num = g_caps.limits.maxFBAttachments; ii < num; ++ii) { char tmpFragData[16]; bx::snprintf(tmpFragData, BX_COUNTOF(tmpFragData), "gl_FragData[%d]", ii); @@ -5568,7 +5661,7 @@ namespace bgfx { namespace gl } } - if (!!bx::findIdentifierMatch(code, s_ARB_texture_multisample)) + if (!!bx::findIdentifierMatch(code, s_ARB_texture_multisample) ) { writeString(&writer, "#extension GL_ARB_texture_multisample : enable\n"); } @@ -5898,7 +5991,8 @@ namespace bgfx { namespace gl uint32_t dsFlags = _flags & (BGFX_CLEAR_DISCARD_DEPTH|BGFX_CLEAR_DISCARD_STENCIL); if (BGFX_CLEAR_NONE != dsFlags) { - if ( (BGFX_CLEAR_DISCARD_DEPTH|BGFX_CLEAR_DISCARD_STENCIL) == dsFlags) + if (!BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES) + && (BGFX_CLEAR_DISCARD_DEPTH|BGFX_CLEAR_DISCARD_STENCIL) == dsFlags) { buffers[idx++] = GL_DEPTH_STENCIL_ATTACHMENT; } @@ -6035,7 +6129,8 @@ namespace bgfx { namespace gl _render->m_hmdInitialized = m_ovr.isInitialized(); const bool hmdEnabled = m_ovr.isEnabled(); - ViewState viewState(_render, hmdEnabled); + static ViewState viewState; + viewState.reset(_render, hmdEnabled); uint16_t programIdx = invalidHandle; SortKey key; @@ -6055,11 +6150,17 @@ namespace bgfx { namespace gl uint8_t primIndex; { - const uint64_t pt = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0; + const uint64_t pt = 0; primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT); } PrimInfo prim = s_primInfo[primIndex]; + GL_CHECK(glPolygonMode(GL_FRONT_AND_BACK + , _render->m_debug&BGFX_DEBUG_WIREFRAME + ? GL_LINE + : GL_FILL + ) ); + uint32_t baseVertex = 0; GLuint currentVao = 0; bool wasCompute = false; @@ -6171,8 +6272,7 @@ namespace bgfx { namespace gl if (m_ovr.isEnabled() ) { - m_ovr.getViewport(eye, &viewState.m_rect); - m_ovr.renderEyeStart(eye); + m_ovr.renderEyeStart(eye, &viewState.m_rect); } else { @@ -6291,7 +6391,7 @@ namespace bgfx { namespace gl GL_CHECK(glBindImageTexture(ii , texture.m_id , bind.m_un.m_compute.m_mip - , GL_FALSE + , texture.isCubeMap()?GL_TRUE:GL_FALSE , 0 , s_access[bind.m_un.m_compute.m_access] , s_imageFormat[bind.m_un.m_compute.m_format]) @@ -6349,7 +6449,7 @@ namespace bgfx { namespace gl uintptr_t args = compute.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE; for (uint32_t ii = 0; ii < numDrawIndirect; ++ii) { - GL_CHECK(glDispatchComputeIndirect((GLintptr)args) ); + GL_CHECK(glDispatchComputeIndirect( (GLintptr)args) ); args += BGFX_CONFIG_DRAW_INDIRECT_STRIDE; } } @@ -6560,38 +6660,39 @@ namespace bgfx { namespace gl viewState.m_alphaRef = ref/255.0f; } -#if BGFX_CONFIG_RENDERER_OPENGL - if ( (BGFX_STATE_PT_POINTS|BGFX_STATE_POINT_SIZE_MASK) & changedFlags) + if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) ) { - float pointSize = (float)(bx::uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) ); - GL_CHECK(glPointSize(pointSize) ); - } + if ( (BGFX_STATE_PT_POINTS|BGFX_STATE_POINT_SIZE_MASK) & changedFlags) + { + float pointSize = (float)(bx::uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) ); + GL_CHECK(glPointSize(pointSize) ); + } - if (BGFX_STATE_MSAA & changedFlags) - { - GL_CHECK(BGFX_STATE_MSAA & newFlags - ? glEnable(GL_MULTISAMPLE) - : glDisable(GL_MULTISAMPLE) - ); - } + if (BGFX_STATE_MSAA & changedFlags) + { + GL_CHECK(BGFX_STATE_MSAA & newFlags + ? glEnable(GL_MULTISAMPLE) + : glDisable(GL_MULTISAMPLE) + ); + } - if (BGFX_STATE_LINEAA & changedFlags) - { - GL_CHECK(BGFX_STATE_LINEAA & newFlags - ? glEnable(GL_LINE_SMOOTH) - : glDisable(GL_LINE_SMOOTH) - ); - } + if (BGFX_STATE_LINEAA & changedFlags) + { + GL_CHECK(BGFX_STATE_LINEAA & newFlags + ? glEnable(GL_LINE_SMOOTH) + : glDisable(GL_LINE_SMOOTH) + ); + } - if (m_conservativeRasterSupport - && BGFX_STATE_CONSERVATIVE_RASTER & changedFlags) - { - GL_CHECK(BGFX_STATE_CONSERVATIVE_RASTER & newFlags - ? glEnable(GL_CONSERVATIVE_RASTERIZATION_NV) - : glDisable(GL_CONSERVATIVE_RASTERIZATION_NV) - ); + if (m_conservativeRasterSupport + && BGFX_STATE_CONSERVATIVE_RASTER & changedFlags) + { + GL_CHECK(BGFX_STATE_CONSERVATIVE_RASTER & newFlags + ? glEnable(GL_CONSERVATIVE_RASTERIZATION_NV) + : glDisable(GL_CONSERVATIVE_RASTERIZATION_NV) + ); + } } -#endif // BGFX_CONFIG_RENDERER_OPENGL if ( (BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags) { @@ -6721,7 +6822,7 @@ namespace bgfx { namespace gl blendFactor = draw.m_rgba; } - const uint64_t pt = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : newFlags&BGFX_STATE_PT_MASK; + const uint64_t pt = newFlags&BGFX_STATE_PT_MASK; primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT); prim = s_primInfo[primIndex]; } @@ -6778,25 +6879,28 @@ namespace bgfx { namespace gl } if (0 != defaultVao - && 0 == draw.m_startVertex + && 0 == draw.m_stream[0].m_startVertex && 0 == draw.m_instanceDataOffset) { if (programChanged - || baseVertex != draw.m_startVertex - || currentState.m_vertexBuffer.idx != draw.m_vertexBuffer.idx - || currentState.m_indexBuffer.idx != draw.m_indexBuffer.idx - || currentState.m_instanceDataOffset != draw.m_instanceDataOffset - || currentState.m_instanceDataStride != draw.m_instanceDataStride + || baseVertex != draw.m_stream[0].m_startVertex + || currentState.m_streamMask != draw.m_streamMask + || currentState.m_stream[0].m_handle.idx != draw.m_stream[0].m_handle.idx + || currentState.m_indexBuffer.idx != draw.m_indexBuffer.idx + || currentState.m_instanceDataOffset != draw.m_instanceDataOffset + || currentState.m_instanceDataStride != draw.m_instanceDataStride || currentState.m_instanceDataBuffer.idx != draw.m_instanceDataBuffer.idx) { bx::HashMurmur2A murmur; murmur.begin(); - murmur.add(draw.m_vertexBuffer.idx); - if (isValid(draw.m_vertexBuffer) ) + const Stream& stream = draw.m_stream[0]; + murmur.add(stream.m_handle.idx); + + if (isValid(stream.m_handle) ) { - const VertexBufferGL& vb = m_vertexBuffers[draw.m_vertexBuffer.idx]; - uint16_t decl = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx; + const VertexBufferGL& vb = m_vertexBuffers[stream.m_handle.idx]; + uint16_t decl = !isValid(vb.m_decl) ? stream.m_decl.idx : vb.m_decl.idx; murmur.add(decl); } @@ -6807,11 +6911,13 @@ namespace bgfx { namespace gl murmur.add(programIdx); uint32_t hash = murmur.end(); - currentState.m_vertexBuffer = draw.m_vertexBuffer; + currentState.m_streamMask = draw.m_streamMask; + currentState.m_stream[0].m_handle = stream.m_handle; + baseVertex = stream.m_startVertex; + currentState.m_indexBuffer = draw.m_indexBuffer; currentState.m_instanceDataOffset = draw.m_instanceDataOffset; currentState.m_instanceDataStride = draw.m_instanceDataStride; - baseVertex = draw.m_startVertex; GLuint id = m_vaoStateCache.find(hash); if (UINT32_MAX != id) @@ -6827,14 +6933,14 @@ namespace bgfx { namespace gl program.add(hash); - if (isValid(draw.m_vertexBuffer) ) + if (isValid(stream.m_handle) ) { - VertexBufferGL& vb = m_vertexBuffers[draw.m_vertexBuffer.idx]; + VertexBufferGL& vb = m_vertexBuffers[stream.m_handle.idx]; vb.add(hash); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); - uint16_t decl = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx; - program.bindAttributes(m_vertexDecls[decl], draw.m_startVertex); + uint16_t decl = !isValid(vb.m_decl) ? stream.m_decl.idx : vb.m_decl.idx; + program.bindAttributes(m_vertexDecls[decl], stream.m_startVertex); if (isValid(draw.m_instanceDataBuffer) ) { @@ -6868,24 +6974,27 @@ namespace bgfx { namespace gl && 0 != currentVao) { GL_CHECK(glBindVertexArray(defaultVao) ); - currentState.m_vertexBuffer.idx = invalidHandle; - currentState.m_indexBuffer.idx = invalidHandle; + currentState.m_streamMask = 0; + currentState.m_stream[0].m_handle.idx = invalidHandle; + currentState.m_indexBuffer.idx = invalidHandle; bindAttribs = true; currentVao = 0; } if (programChanged - || currentState.m_vertexBuffer.idx != draw.m_vertexBuffer.idx + || currentState.m_streamMask != draw.m_streamMask + || currentState.m_stream[0].m_handle.idx != draw.m_stream[0].m_handle.idx || currentState.m_instanceDataBuffer.idx != draw.m_instanceDataBuffer.idx - || currentState.m_instanceDataOffset != draw.m_instanceDataOffset - || currentState.m_instanceDataStride != draw.m_instanceDataStride) + || currentState.m_instanceDataOffset != draw.m_instanceDataOffset + || currentState.m_instanceDataStride != draw.m_instanceDataStride) { - currentState.m_vertexBuffer = draw.m_vertexBuffer; + currentState.m_streamMask = draw.m_streamMask; + currentState.m_stream[0].m_handle = draw.m_stream[0].m_handle; currentState.m_instanceDataBuffer.idx = draw.m_instanceDataBuffer.idx; - currentState.m_instanceDataOffset = draw.m_instanceDataOffset; - currentState.m_instanceDataStride = draw.m_instanceDataStride; + currentState.m_instanceDataOffset = draw.m_instanceDataOffset; + currentState.m_instanceDataStride = draw.m_instanceDataStride; - uint16_t handle = draw.m_vertexBuffer.idx; + uint16_t handle = draw.m_stream[0].m_handle.idx; if (invalidHandle != handle) { VertexBufferGL& vb = m_vertexBuffers[handle]; @@ -6914,15 +7023,15 @@ namespace bgfx { namespace gl } } - if (isValid(currentState.m_vertexBuffer) ) + if (0 != currentState.m_streamMask) { - if (baseVertex != draw.m_startVertex + if (baseVertex != draw.m_stream[0].m_startVertex || bindAttribs) { - baseVertex = draw.m_startVertex; - const VertexBufferGL& vb = m_vertexBuffers[draw.m_vertexBuffer.idx]; - uint16_t decl = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx; - program.bindAttributes(m_vertexDecls[decl], draw.m_startVertex); + baseVertex = draw.m_stream[0].m_startVertex; + const VertexBufferGL& vb = m_vertexBuffers[draw.m_stream[0].m_handle.idx]; + uint16_t decl = !isValid(vb.m_decl) ? draw.m_stream[0].m_decl.idx : vb.m_decl.idx; + program.bindAttributes(m_vertexDecls[decl], draw.m_stream[0].m_startVertex); if (isValid(draw.m_instanceDataBuffer) ) { @@ -6933,13 +7042,13 @@ namespace bgfx { namespace gl } } - if (isValid(currentState.m_vertexBuffer) ) + if (0 != currentState.m_streamMask) { uint32_t numVertices = draw.m_numVertices; if (UINT32_MAX == numVertices) { - const VertexBufferGL& vb = m_vertexBuffers[currentState.m_vertexBuffer.idx]; - uint16_t decl = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx; + const VertexBufferGL& vb = m_vertexBuffers[currentState.m_stream[0].m_handle.idx]; + uint16_t decl = !isValid(vb.m_decl) ? draw.m_stream[0].m_decl.idx : vb.m_decl.idx; const VertexDecl& vertexDecl = m_vertexDecls[decl]; numVertices = vb.m_size/vertexDecl.m_stride; } |