From 7a69b2b353e195574fff57a2c0c8e09495ce8959 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 29 Jan 2018 14:54:41 +0100 Subject: [PATCH] Proposed fix for mesh physics view crashes on OpenSim with physic shapes exceeding 65536 vertices --- indra/llrender/llvertexbuffer.cpp | 100 ++++++++++++++++-------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index ed71ecd368..1ae61177bb 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -611,63 +611,73 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos, con //LLGLSLShader::startProfile(); //glDrawArrays(sGLMode[mode], 0, count); //LLGLSLShader::stopProfile(count, mode); - bool has_buffer = true; - if (!sUtilityBuffer) - { - sUtilityBuffer = new LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0, GL_STREAM_DRAW); - has_buffer = sUtilityBuffer->allocateBuffer(count, count, true); - } - if (sUtilityBuffer->getNumVerts() < (S32) count) - { - has_buffer = sUtilityBuffer->resizeBuffer(count, count); - } + U32 start_pos = 0; + U32 remaining = pos.size(); - if (has_buffer) + while (remaining > 0) { - LLStrider vertex_strider; - LLStrider normal_strider; - sUtilityBuffer->getVertexStrider(vertex_strider); - sUtilityBuffer->getNormalStrider(normal_strider); - for (U32 i = 0; i < count; ++i) + count = llmin(remaining, 65536u); + start_pos = pos.size() - remaining; + remaining -= count; + + bool has_buffer = true; + if (!sUtilityBuffer) { - *(vertex_strider++) = pos[i]; - *(normal_strider++) = norm[i]; + sUtilityBuffer = new LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0, GL_STREAM_DRAW); + has_buffer = sUtilityBuffer->allocateBuffer(count, count, true); + } + if (sUtilityBuffer->getNumVerts() < (S32)count) + { + has_buffer = sUtilityBuffer->resizeBuffer(count, count); } - sUtilityBuffer->setBuffer(MAP_VERTEX | MAP_NORMAL); - LLGLSLShader::startProfile(); - sUtilityBuffer->drawArrays(mode, 0, pos.size()); - LLGLSLShader::stopProfile(count, mode); - } - else - { - unbind(); - - setupClientArrays(MAP_VERTEX | MAP_NORMAL); - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - if (shader) + if (has_buffer) { - S32 loc = LLVertexBuffer::TYPE_VERTEX; - if (loc > -1) + LLStrider vertex_strider; + LLStrider normal_strider; + sUtilityBuffer->getVertexStrider(vertex_strider); + sUtilityBuffer->getNormalStrider(normal_strider); + for (U32 i = 0; i < count; ++i) { - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV); - } - loc = LLVertexBuffer::TYPE_NORMAL; - if (loc > -1) - { - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV); + *(vertex_strider++) = pos[start_pos + i]; + *(normal_strider++) = norm[start_pos + i]; } + + sUtilityBuffer->setBuffer(MAP_VERTEX | MAP_NORMAL); + LLGLSLShader::startProfile(); + sUtilityBuffer->drawArrays(mode, 0, count); + LLGLSLShader::stopProfile(count, mode); } else { - glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); - glNormalPointer(GL_FLOAT, 0, norm[0].mV); + unbind(); + + setupClientArrays(MAP_VERTEX | MAP_NORMAL); + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + if (shader) + { + S32 loc = LLVertexBuffer::TYPE_VERTEX; + if (loc > -1) + { + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[start_pos].mV); + } + loc = LLVertexBuffer::TYPE_NORMAL; + if (loc > -1) + { + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[start_pos].mV); + } + } + else + { + glVertexPointer(3, GL_FLOAT, 0, pos[start_pos].mV); + glNormalPointer(GL_FLOAT, 0, norm[start_pos].mV); + } + LLGLSLShader::startProfile(); + glDrawArrays(sGLMode[mode], 0, count); + LLGLSLShader::stopProfile(count, mode); } - LLGLSLShader::startProfile(); - glDrawArrays(sGLMode[mode], 0, count); - LLGLSLShader::stopProfile(count, mode); } // }