diff options
Diffstat (limited to '3rdparty/bgfx/src/renderer_gl.cpp')
-rw-r--r-- | 3rdparty/bgfx/src/renderer_gl.cpp | 399 |
1 files changed, 276 insertions, 123 deletions
diff --git a/3rdparty/bgfx/src/renderer_gl.cpp b/3rdparty/bgfx/src/renderer_gl.cpp index 93a714ea194..8f4903a2cb1 100644 --- a/3rdparty/bgfx/src/renderer_gl.cpp +++ b/3rdparty/bgfx/src/renderer_gl.cpp @@ -851,10 +851,16 @@ namespace bgfx { namespace gl static const char* s_ARB_shader_texture_lod[] = { "texture2DLod", + "texture2DArrayLod", // BK - interacts with ARB_texture_array. "texture2DProjLod", + "texture2DGrad", + "texture2DProjGrad", "texture3DLod", "texture3DProjLod", + "texture3DGrad", + "texture3DProjGrad", "textureCubeLod", + "textureCubeGrad", "shadow2DLod", "shadow2DProjLod", NULL @@ -869,10 +875,10 @@ namespace bgfx { namespace gl "texture2DLod", "texture2DProjLod", "textureCubeLod", + "texture2DGrad", + "texture2DProjGrad", + "textureCubeGrad", NULL - // "texture2DGrad", - // "texture2DProjGrad", - // "textureCubeGrad", }; static const char* s_EXT_shadow_samplers[] = @@ -1055,7 +1061,7 @@ namespace bgfx { namespace gl while (pos < end) { uint32_t len; - const char* space = strchr(pos, ' '); + const char* space = bx::strnchr(pos, ' '); if (NULL != space) { len = bx::uint32_min(sizeof(name), (uint32_t)(space - pos) ); @@ -1065,7 +1071,7 @@ namespace bgfx { namespace gl len = bx::uint32_min(sizeof(name), (uint32_t)bx::strnlen(pos) ); } - strncpy(name, pos, len); + bx::strlncpy(name, BX_COUNTOF(name), pos, len); name[len] = '\0'; BX_TRACE("\t%s", name); @@ -1349,12 +1355,12 @@ namespace bgfx { namespace gl && extension.m_initialize) { const char* ext = _name; - if (0 == strncmp(ext, "GL_", 3) ) // skip GL_ + if (0 == bx::strncmp(ext, "GL_", 3) ) // skip GL_ { ext += 3; } - if (0 == strcmp(ext, extension.m_name) ) + if (0 == bx::strncmp(ext, extension.m_name) ) { extension.m_supported = true; supported = true; @@ -1437,7 +1443,7 @@ namespace bgfx { namespace gl , m_backBufferFbo(0) , m_msaaBackBufferFbo(0) { - memset(m_msaaBackBufferRbos, 0, sizeof(m_msaaBackBufferRbos) ); + bx::memSet(m_msaaBackBufferRbos, 0, sizeof(m_msaaBackBufferRbos) ); } ~RendererContextGL() @@ -1449,8 +1455,8 @@ namespace bgfx { namespace gl m_renderdocdll = loadRenderDoc(); m_fbh.idx = invalidHandle; - memset(m_uniforms, 0, sizeof(m_uniforms) ); - memset(&m_resolution, 0, sizeof(m_resolution) ); + bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); + bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); @@ -1469,7 +1475,7 @@ namespace bgfx { namespace gl for (uint32_t ii = 0; ii < BX_COUNTOF(s_vendorIds); ++ii) { const VendorId& vendorId = s_vendorIds[ii]; - if (0 == strncmp(vendorId.name, m_vendor, bx::strnlen(vendorId.name) ) ) + if (0 == bx::strncmp(vendorId.name, m_vendor, bx::strnlen(vendorId.name) ) ) { g_caps.vendorId = vendorId.id; break; @@ -1543,8 +1549,8 @@ namespace bgfx { namespace gl ; if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 31) - && 0 == strcmp(m_vendor, "Imagination Technologies") - && NULL != strstr(m_version, "(SDK 3.5@3510720)") ) + && 0 == bx::strncmp(m_vendor, "Imagination Technologies") + && NULL != bx::strnstr(m_version, "(SDK 3.5@3510720)") ) { // Skip initializing extensions that are broken in emulator. s_extension[Extension::ARB_program_interface_query ].m_initialize = @@ -1564,7 +1570,7 @@ namespace bgfx { namespace gl while (pos < end) { uint32_t len; - const char* space = strchr(pos, ' '); + const char* space = bx::strnchr(pos, ' '); if (NULL != space) { len = bx::uint32_min(sizeof(name), (uint32_t)(space - pos) ); @@ -1574,7 +1580,7 @@ namespace bgfx { namespace gl len = bx::uint32_min(sizeof(name), (uint32_t)bx::strnlen(pos) ); } - strncpy(name, pos, len); + bx::strlncpy(name, BX_COUNTOF(name), pos, len); name[len] = '\0'; updateExtension(name); @@ -1607,7 +1613,7 @@ namespace bgfx { namespace gl } // Allow all texture filters. - memset(s_textureFilter, true, BX_COUNTOF(s_textureFilter) ); + bx::memSet(s_textureFilter, true, BX_COUNTOF(s_textureFilter) ); bool bc123Supported = 0 || s_extension[Extension::EXT_texture_compression_s3tc ].m_supported @@ -2290,6 +2296,9 @@ namespace bgfx { namespace gl m_ovr.flip(); m_ovr.swap(_hmd); + // Ensure the back buffer is bound as the source of the flip + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo)); + // need to swap GL render context even if OVR is enabled to get // the mirror texture in the output m_glctx.swap(); @@ -2311,7 +2320,7 @@ namespace bgfx { namespace gl void createVertexDecl(VertexDeclHandle _handle, const VertexDecl& _decl) BX_OVERRIDE { VertexDecl& decl = m_vertexDecls[_handle.idx]; - memcpy(&decl, &_decl, sizeof(VertexDecl) ); + bx::memCopy(&decl, &_decl, sizeof(VertexDecl) ); dump(decl); } @@ -2508,7 +2517,7 @@ namespace bgfx { namespace gl uint32_t size = g_uniformTypeSize[_type]*_num; void* data = BX_ALLOC(g_allocator, size); - memset(data, 0, size); + bx::memSet(data, 0, size); m_uniforms[_handle.idx] = data; m_uniformReg.add(_handle, _name, m_uniforms[_handle.idx]); } @@ -2520,14 +2529,24 @@ namespace bgfx { namespace gl m_uniformReg.remove(_handle); } - void saveScreenShot(const char* _filePath) BX_OVERRIDE + void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) BX_OVERRIDE { - uint32_t length = m_resolution.m_width*m_resolution.m_height*4; - uint8_t* data = (uint8_t*)BX_ALLOC(g_allocator, length); - + SwapChainGL* swapChain = NULL; uint32_t width = m_resolution.m_width; uint32_t height = m_resolution.m_height; + if (isValid(_handle) ) + { + const FrameBufferGL& frameBuffer = m_frameBuffers[_handle.idx]; + swapChain = frameBuffer.m_swapChain; + width = frameBuffer.m_width; + height = frameBuffer.m_height; + } + m_glctx.makeCurrent(swapChain); + + uint32_t length = width*height*4; + uint8_t* data = (uint8_t*)BX_ALLOC(g_allocator, length); + GL_CHECK(glReadPixels(0 , 0 , width @@ -2563,7 +2582,7 @@ namespace bgfx { namespace gl void updateUniform(uint16_t _loc, const void* _data, uint32_t _size) BX_OVERRIDE { - memcpy(m_uniforms[_loc], _data, _size); + bx::memCopy(m_uniforms[_loc], _data, _size); } void setMarker(const char* _marker, uint32_t _size) BX_OVERRIDE @@ -2571,6 +2590,11 @@ namespace bgfx { namespace gl GL_CHECK(glInsertEventMarker(_size, _marker) ); } + void invalidateOcclusionQuery(OcclusionQueryHandle _handle) BX_OVERRIDE + { + m_occlusionQuery.invalidate(_handle); + } + void submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) BX_OVERRIDE; void blitSetup(TextVideoMemBlitter& _blitter) BX_OVERRIDE @@ -2638,7 +2662,9 @@ namespace bgfx { namespace gl GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) ); ProgramGL& program = m_program[_blitter.m_program.idx]; + program.bindAttributesBegin(); program.bindAttributes(_blitter.m_decl, 0); + program.bindAttributesEnd(); GL_CHECK(glDrawElements(GL_TRIANGLES , _numIndices @@ -3205,7 +3231,7 @@ namespace bgfx { namespace gl else { UniformHandle handle; - memcpy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) ); + bx::memCopy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) ); data = (const char*)m_uniforms[handle.idx]; } @@ -3391,7 +3417,9 @@ namespace bgfx { namespace gl ProgramGL& program = m_program[_clearQuad.m_program[numMrt-1].idx]; GL_CHECK(glUseProgram(program.m_id) ); + program.bindAttributesBegin(); program.bindAttributes(vertexDecl, 0); + program.bindAttributesEnd(); float mrtClear[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS][4]; @@ -3400,7 +3428,7 @@ namespace bgfx { namespace gl for (uint32_t ii = 0; ii < numMrt; ++ii) { uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[ii]); - memcpy(mrtClear[ii], _palette[index], 16); + bx::memCopy(mrtClear[ii], _palette[index], 16); } } else @@ -3415,7 +3443,7 @@ namespace bgfx { namespace gl for (uint32_t ii = 0; ii < numMrt; ++ii) { - memcpy(mrtClear[ii], rgba, 16); + bx::memCopy(mrtClear[ii], rgba, 16); } } @@ -3536,7 +3564,7 @@ namespace bgfx { namespace gl , m_textureSwapChain(NULL) , m_mirrorTexture(NULL) { - memset(&m_eyeTarget, 0, sizeof(m_eyeTarget) ); + bx::memSet(&m_eyeTarget, 0, sizeof(m_eyeTarget) ); } static void setDefaultSamplerState() @@ -3980,7 +4008,7 @@ namespace bgfx { namespace gl { BX_WARN(0 != _vsh.m_id, "Invalid vertex/compute shader."); GL_CHECK(glDeleteProgram(m_id) ); - m_used[0] = Attrib::Count; + m_usedCount = 0; m_id = 0; return; } @@ -4105,7 +4133,7 @@ namespace bgfx { namespace gl GLint num; }; VariableInfo vi; - GLenum props[] ={ GL_TYPE, GL_LOCATION, GL_ARRAY_SIZE }; + GLenum props[] = { GL_TYPE, GL_LOCATION, GL_ARRAY_SIZE }; GLenum gltype; GLint num; @@ -4144,13 +4172,13 @@ namespace bgfx { namespace gl num = bx::uint32_max(num, 1); int offset = 0; - char* array = strchr(name, '['); + char* array = const_cast<char*>(bx::strnchr(name, '[') ); if (NULL != array) { BX_TRACE("--- %s", name); *array = '\0'; array++; - char* end = strchr(array, ']'); + char* end = const_cast<char*>(bx::strnchr(array, ']') ); if (NULL != end) { // Some devices (Amazon Fire) might not return terminating brace. *end = '\0'; @@ -4298,7 +4326,7 @@ namespace bgfx { namespace gl } } - memset(m_attributes, 0xff, sizeof(m_attributes) ); + bx::memSet(m_attributes, 0xff, sizeof(m_attributes) ); uint32_t used = 0; for (uint8_t ii = 0; ii < Attrib::Count; ++ii) { @@ -4310,11 +4338,8 @@ namespace bgfx { namespace gl m_used[used++] = ii; } } - BX_CHECK(used < BX_COUNTOF(m_used), "Out of bounds %d > array size %d." - , used - , BX_COUNTOF(m_used) - ); - m_used[used] = Attrib::Count; + BX_CHECK(used < BX_COUNTOF(m_used), "Out of bounds %d > array size %d.", used, Attrib::Count); + m_usedCount = (uint8_t)used; used = 0; for (uint32_t ii = 0; ii < BX_COUNTOF(s_instanceDataName); ++ii) @@ -4333,9 +4358,9 @@ namespace bgfx { namespace gl m_instanceData[used] = 0xffff; } - void ProgramGL::bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex) const + void ProgramGL::bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex) { - for (uint32_t ii = 0; Attrib::Count != m_used[ii]; ++ii) + for (uint32_t ii = 0, iiEnd = m_usedCount; ii < iiEnd; ++ii) { Attrib::Enum attr = Attrib::Enum(m_used[ii]); GLint loc = m_attributes[attr]; @@ -4375,10 +4400,8 @@ namespace bgfx { namespace gl , (void*)(uintptr_t)baseVertex) ); } - } - else - { - GL_CHECK(glDisableVertexAttribArray(loc) ); + + m_unboundUsedAttrib[ii] = Attrib::Count; } } } @@ -4667,6 +4690,7 @@ namespace bgfx { namespace gl GL_CHECK(glGenTextures(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate texture id."); GL_CHECK(glBindTexture(_target, m_id) ); + GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) ); const TextureFormatInfo& tfi = s_textureFormat[m_textureFormat]; m_fmt = tfi.m_fmt; @@ -5312,8 +5336,8 @@ namespace bgfx { namespace gl void strins(char* _str, const char* _insert) { size_t len = bx::strnlen(_insert); - memmove(&_str[len], _str, bx::strnlen(_str)+1); - memcpy(_str, _insert, len); + bx::memMove(&_str[len], _str, bx::strnlen(_str)+1); + bx::memCopy(_str, _insert, len); } void ShaderGL::create(Memory* _mem) @@ -5481,15 +5505,20 @@ namespace bgfx { namespace gl if (usesTextureLod) { - BX_WARN(s_extension[Extension::EXT_shader_texture_lod].m_supported, "EXT_shader_texture_lod is used but not supported by GLES2 driver."); - if (s_extension[Extension::EXT_shader_texture_lod].m_supported - /*&& GL_VERTEX_SHADER == m_type*/) + BX_WARN(s_extension[Extension::ARB_shader_texture_lod].m_supported + , "ARB_shader_texture_lod is used but not supported by GLES2 driver." + ); + + if (s_extension[Extension::ARB_shader_texture_lod].m_supported) { writeString(&writer - , "#extension GL_EXT_shader_texture_lod : enable\n" - "#define texture2DLod texture2DLodEXT\n" - "#define texture2DProjLod texture2DProjLodEXT\n" - "#define textureCubeLod textureCubeLodEXT\n" + , "#extension GL_ARB_shader_texture_lod : enable\n" + "#define texture2DLod texture2DLodARB\n" + "#define texture2DProjLod texture2DProjLodARB\n" + "#define textureCubeLod textureCubeLodARB\n" + "#define texture2DGrad texture2DGradARB\n" + "#define texture2DProjGrad texture2DProjGradARB\n" + "#define textureCubeGrad textureCubeGradARB\n" ); } else @@ -5523,10 +5552,10 @@ namespace bgfx { namespace gl if (insertFragDepth) { - char* entry = strstr(temp, "void main ()"); + const char* entry = bx::strnstr(temp, "void main ()"); if (NULL != entry) { - char* brace = strstr(entry, "{"); + char* brace = const_cast<char*>(bx::strnstr(entry, "{") ); if (NULL != brace) { const char* end = bx::strmb(brace, '{', '}'); @@ -5543,7 +5572,7 @@ namespace bgfx { namespace gl { char* insert = const_cast<char*>(fragDepth); strins(insert, "bg"); - memcpy(insert + 2, "fx", 2); + bx::memCopy(insert + 2, "fx", 2); } } else if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) @@ -5561,7 +5590,7 @@ namespace bgfx { namespace gl const bool usesPacking = !!bx::findIdentifierMatch(code, s_ARB_shading_language_packing); uint32_t version = - usesIUsamplers || usesTexelFetch ? 130 + usesIUsamplers || usesTexelFetch || usesGpuShader5 ? 130 : usesTextureLod ? 120 : 120 ; @@ -5575,7 +5604,12 @@ namespace bgfx { namespace gl { if (m_type == GL_FRAGMENT_SHADER) { - writeString(&writer, "#extension GL_ARB_shader_texture_lod : enable\n"); + writeString(&writer + , "#extension GL_ARB_shader_texture_lod : enable\n" + "#define texture2DGrad texture2DGradARB\n" + "#define texture2DProjGrad texture2DProjGradARB\n" + "#define textureCubeGrad textureCubeGradARB\n" + ); } } @@ -5619,7 +5653,7 @@ namespace bgfx { namespace gl { char tmpFragData[16]; bx::snprintf(tmpFragData, BX_COUNTOF(tmpFragData), "gl_FragData[%d]", ii); - fragData = bx::uint32_max(fragData, NULL == strstr(code, tmpFragData) ? 0 : ii+1); + fragData = bx::uint32_max(fragData, NULL == bx::strnstr(code, tmpFragData) ? 0 : ii+1); } BGFX_FATAL(0 != fragData, Fatal::InvalidShader, "Unable to find and patch gl_FragData!"); @@ -5677,9 +5711,12 @@ namespace bgfx { namespace gl writeString(&writer, "#version 140\n"); } - writeString(&writer, "#define texture2DLod textureLod\n"); - writeString(&writer, "#define texture3DLod textureLod\n"); - writeString(&writer, "#define textureCubeLod textureLod\n"); + writeString(&writer, "#define texture2DLod textureLod\n"); + writeString(&writer, "#define texture3DLod textureLod\n"); + writeString(&writer, "#define textureCubeLod textureLod\n"); + writeString(&writer, "#define texture2DGrad textureGrad\n"); + writeString(&writer, "#define texture3DGrad textureGrad\n"); + writeString(&writer, "#define textureCubeGrad textureGrad\n"); if (m_type == GL_FRAGMENT_SHADER) { @@ -5709,7 +5746,7 @@ namespace bgfx { namespace gl { char tmpFragData[16]; bx::snprintf(tmpFragData, BX_COUNTOF(tmpFragData), "gl_FragData[%d]", ii); - fragData = bx::uint32_max(fragData, NULL == strstr(code, tmpFragData) ? 0 : ii+1); + fragData = bx::uint32_max(fragData, NULL == bx::strnstr(code, tmpFragData) ? 0 : ii+1); } BGFX_FATAL(0 != fragData, Fatal::InvalidShader, "Unable to find and patch gl_FragData!"); @@ -5814,7 +5851,7 @@ namespace bgfx { namespace gl m_denseIdx = UINT16_MAX; m_numTh = _num; - memcpy(m_attachment, _attachment, _num*sizeof(Attachment) ); + bx::memCopy(m_attachment, _attachment, _num*sizeof(Attachment) ); m_needPresent = false; @@ -5988,7 +6025,7 @@ namespace bgfx { namespace gl m_swapChain = NULL; } - memset(m_fbo, 0, sizeof(m_fbo) ); + bx::memSet(m_fbo, 0, sizeof(m_fbo) ); uint16_t denseIdx = m_denseIdx; m_denseIdx = UINT16_MAX; m_needPresent = false; @@ -6112,24 +6149,43 @@ namespace bgfx { namespace gl while (0 != m_control.available() ) { Query& query = m_query[m_control.m_read]; - int32_t result; - if (!_wait) + if (isValid(query.m_handle) ) { - GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT_AVAILABLE, &result) ); + int32_t result; - if (!result) + if (!_wait) { - break; + GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT_AVAILABLE, &result) ); + + if (!result) + { + break; + } } + + GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT, &result) ); + _render->m_occlusion[query.m_handle.idx] = int32_t(result); } - GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT, &result) ); - _render->m_occlusion[query.m_handle.idx] = 0 < result; m_control.consume(1); } } + void OcclusionQueryGL::invalidate(OcclusionQueryHandle _handle) + { + const uint32_t size = m_control.m_size; + + for (uint32_t ii = 0, num = m_control.available(); ii < num; ++ii) + { + Query& query = m_query[(m_control.m_read + ii) % size]; + if (query.m_handle.idx == _handle.idx) + { + query.m_handle.idx = bgfx::invalidHandle; + } + } + } + void RendererContextGL::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) { BGFX_GPU_PROFILER_BEGIN_DYNAMIC("rendererSubmit"); @@ -6223,7 +6279,6 @@ namespace bgfx { namespace gl : GL_FILL ) ); - uint32_t baseVertex = 0; GLuint currentVao = 0; bool wasCompute = false; bool viewHasScissor = false; @@ -6601,7 +6656,7 @@ namespace bgfx { namespace gl else { Rect scissorRect; - scissorRect.intersect(viewScissorRect, _render->m_rectCache.m_cache[scissor]); + scissorRect.setIntersect(viewScissorRect, _render->m_rectCache.m_cache[scissor]); if (scissorRect.isZeroArea() ) { continue; @@ -6951,27 +7006,63 @@ namespace bgfx { namespace gl && 0 == draw.m_stream[0].m_startVertex && 0 == draw.m_instanceDataOffset) { + bool diffStartVertex = false; + bool diffStreamHandles = false; + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) + { + streamMask >>= ntz; + idx += ntz; + + if (currentState.m_stream[idx].m_handle.idx != draw.m_stream[idx].m_handle.idx) + { + diffStreamHandles = true; + break; + } + + if (currentState.m_stream[idx].m_startVertex != draw.m_stream[idx].m_startVertex) + { + diffStartVertex = true; + break; + } + } + if (programChanged - || 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) + || currentState.m_instanceDataBuffer.idx != draw.m_instanceDataBuffer.idx + || diffStartVertex + || diffStreamHandles) { bx::HashMurmur2A murmur; murmur.begin(); - const Stream& stream = draw.m_stream[0]; - murmur.add(stream.m_handle.idx); - - if (isValid(stream.m_handle) ) + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) { - 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); + streamMask >>= ntz; + idx += ntz; + + const Stream& stream = draw.m_stream[idx]; + murmur.add(stream.m_handle.idx); + + if (isValid(stream.m_handle) ) + { + 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); + } + + currentState.m_stream[idx].m_handle = stream.m_handle; + currentState.m_stream[idx].m_startVertex = stream.m_startVertex; } + currentState.m_streamMask = draw.m_streamMask; murmur.add(draw.m_indexBuffer.idx); murmur.add(draw.m_instanceDataBuffer.idx); @@ -6980,11 +7071,7 @@ namespace bgfx { namespace gl murmur.add(programIdx); uint32_t hash = murmur.end(); - 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_indexBuffer = draw.m_indexBuffer; currentState.m_instanceDataOffset = draw.m_instanceDataOffset; currentState.m_instanceDataStride = draw.m_instanceDataStride; @@ -7002,14 +7089,26 @@ namespace bgfx { namespace gl program.add(hash); - if (isValid(stream.m_handle) ) + program.bindAttributesBegin(); + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) { - VertexBufferGL& vb = m_vertexBuffers[stream.m_handle.idx]; - vb.add(hash); - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); + streamMask >>= ntz; + idx += ntz; - uint16_t decl = !isValid(vb.m_decl) ? stream.m_decl.idx : vb.m_decl.idx; - program.bindAttributes(m_vertexDecls[decl], stream.m_startVertex); + const Stream& stream = draw.m_stream[idx]; + + if (isValid(stream.m_handle) ) + { + VertexBufferGL& vb = m_vertexBuffers[stream.m_handle.idx]; + vb.add(hash); + + uint16_t decl = !isValid(vb.m_decl) ? stream.m_decl.idx : vb.m_decl.idx; + GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); + program.bindAttributes(m_vertexDecls[decl], stream.m_startVertex); + } if (isValid(draw.m_instanceDataBuffer) ) { @@ -7019,10 +7118,7 @@ namespace bgfx { namespace gl program.bindInstanceData(draw.m_instanceDataStride, draw.m_instanceDataOffset); } } - else - { - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); - } + program.bindAttributesEnd(); if (isValid(draw.m_indexBuffer) ) { @@ -7043,37 +7139,56 @@ namespace bgfx { namespace gl && 0 != currentVao) { GL_CHECK(glBindVertexArray(defaultVao) ); - currentState.m_streamMask = 0; - currentState.m_stream[0].m_handle.idx = invalidHandle; - currentState.m_indexBuffer.idx = invalidHandle; + currentState.m_streamMask = 0; + for (size_t ii = 0; ii < BGFX_CONFIG_MAX_VERTEX_STREAMS; ++ii) + { + currentState.m_stream[ii].m_handle.idx = invalidHandle; + } + currentState.m_indexBuffer.idx = invalidHandle; bindAttribs = true; currentVao = 0; } + bool diffStreamHandles = false; + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) + { + streamMask >>= ntz; + idx += ntz; + + if (currentState.m_stream[idx].m_handle.idx != draw.m_stream[idx].m_handle.idx) + { + diffStreamHandles = true; + break; + } + } + if (programChanged || 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_instanceDataStride != draw.m_instanceDataStride + || diffStreamHandles) { 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; - uint16_t handle = draw.m_stream[0].m_handle.idx; - if (invalidHandle != handle) - { - VertexBufferGL& vb = m_vertexBuffers[handle]; - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); - bindAttribs = true; - } - else + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) { - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); + streamMask >>= ntz; + idx += ntz; + + currentState.m_stream[idx].m_handle = draw.m_stream[idx].m_handle; } + + bindAttribs = true; } if (currentState.m_indexBuffer.idx != draw.m_indexBuffer.idx) @@ -7094,13 +7209,41 @@ namespace bgfx { namespace gl if (0 != currentState.m_streamMask) { - if (baseVertex != draw.m_stream[0].m_startVertex - || bindAttribs) + bool diffStartVertex = false; + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) + { + streamMask >>= ntz; + idx += ntz; + + if (currentState.m_stream[idx].m_startVertex != draw.m_stream[idx].m_startVertex) + { + diffStartVertex = true; + break; + } + } + + if (bindAttribs || diffStartVertex) { - 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); + program.bindAttributesBegin(); + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) + { + streamMask >>= ntz; + idx += ntz; + + currentState.m_stream[idx].m_startVertex = draw.m_stream[idx].m_startVertex; + + const VertexBufferGL& vb = m_vertexBuffers[draw.m_stream[idx].m_handle.idx]; + uint16_t decl = !isValid(vb.m_decl) ? draw.m_stream[idx].m_decl.idx : vb.m_decl.idx; + GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); + program.bindAttributes(m_vertexDecls[decl], draw.m_stream[idx].m_startVertex); + } + program.bindAttributesEnd(); if (isValid(draw.m_instanceDataBuffer) ) { @@ -7116,10 +7259,20 @@ namespace bgfx { namespace gl uint32_t numVertices = draw.m_numVertices; if (UINT32_MAX == numVertices) { - 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; + for (uint32_t idx = 0, streamMask = draw.m_streamMask, ntz = bx::uint32_cnttz(streamMask) + ; 0 != streamMask + ; streamMask >>= 1, idx += 1, ntz = bx::uint32_cnttz(streamMask) + ) + { + streamMask >>= ntz; + idx += ntz; + + const VertexBufferGL& vb = m_vertexBuffers[draw.m_stream[idx].m_handle.idx]; + uint16_t decl = !isValid(vb.m_decl) ? draw.m_stream[idx].m_decl.idx : vb.m_decl.idx; + const VertexDecl& vertexDecl = m_vertexDecls[decl]; + + numVertices = bx::uint32_min(numVertices, vb.m_size/vertexDecl.m_stride); + } } uint32_t numIndices = 0; |