summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/src/renderer_gl.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/src/renderer_gl.cpp')
-rw-r--r--3rdparty/bgfx/src/renderer_gl.cpp399
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;