diff options
Diffstat (limited to 'indra/llrender/llvertexbuffer.cpp')
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 150 |
1 files changed, 97 insertions, 53 deletions
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2d64292fe7..6a885d2a09 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -29,7 +29,6 @@ #include "llfasttimer.h" #include "llsys.h" #include "llvertexbuffer.h" -// #include "llrender.h" #include "llglheaders.h" #include "llrender.h" #include "llvector4a.h" @@ -263,7 +262,7 @@ static GLuint gen_buffer() LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; GLuint ret = 0; - constexpr U32 pool_size = 4096; + constexpr U32 pool_size = 32768; thread_local static GLuint sNamePool[pool_size]; thread_local static U32 sIndex = 0; @@ -278,13 +277,15 @@ static GLuint gen_buffer() glGenBuffers(pool_size, sNamePool); } else -#endif { // work around for AMD driver bug for (U32 i = 0; i < pool_size; ++i) { glGenBuffers(1, sNamePool + i); } } +#else + glGenBuffers(pool_size, sNamePool); +#endif } ret = sNamePool[--sIndex]; @@ -314,7 +315,27 @@ static void delete_buffers(S32 count, GLuint* buffers) if (!sFreeList[idx].empty()) { - glDeleteBuffers((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); + if (gGLManager.mIsApple) + { + // Unbind, then delete one name at a time. Do not glFinish(): + // that drains a queued glWaitSync and faults in + // GLDFenceRec::getStatus when Apple's fence record is null. + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + LLVertexBuffer::sGLRenderBuffer = 0; + LLVertexBuffer::sGLRenderIndices = 0; + for (GLuint name : sFreeList[idx]) + { + if (name) + { + glDeleteBuffers(1, &name); + } + } + } + else + { + glDeleteBuffers((GLsizei)sFreeList[idx].size(), sFreeList[idx].data()); + } sFreeList[idx].resize(0); } } @@ -358,10 +379,16 @@ public: { //allocate a new buffer LL_PROFILE_GPU_ZONE("vbo alloc"); - // ON OS X, we don't allocate a VBO until the last possible moment - // in unmapBuffer data = (U8*) ll_aligned_malloc_16(size); - STOP_GLERROR; + + if (type == GL_ARRAY_BUFFER) + { + LLVertexBuffer::sGLRenderBuffer = name; + } + else + { + LLVertexBuffer::sGLRenderIndices = name; + } } } @@ -377,12 +404,10 @@ public: } mAllocated -= size; - STOP_GLERROR; if (name) { delete_buffers(1, &name); } - STOP_GLERROR; } }; @@ -455,7 +480,7 @@ public: mMisses++; name = gen_buffer(); glBindBuffer(type, name); - glBufferData(type, size, nullptr, GL_DYNAMIC_DRAW); + glBufferData(type, size, nullptr, GL_STREAM_DRAW); if (type == GL_ELEMENT_ARRAY_BUFFER) { LLVertexBuffer::sGLRenderIndices = name; @@ -685,6 +710,15 @@ U32 LLVertexBuffer::sGLRenderIndices = 0; U32 LLVertexBuffer::sLastMask = 0; U32 LLVertexBuffer::sVertexCount = 0; +// The viewer keeps a single VAO bound. Attribute pointer calls store state in +// that VAO and capture the current array buffer. Track the formats configured +// for sGLRenderBuffer to avoid resubmitting identical state to OpenGL-on-Metal. +// If VAO switching is introduced, invalidate this cache when the VAO changes. +static U32 sVertexAttribsConfigured = 0; +static U32 sColorPointerSource = 0; +static constexpr U32 COLOR_POINTER_COLOR = 1; +static constexpr U32 COLOR_POINTER_EMISSIVE = 2; + //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = @@ -786,7 +820,6 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - STOP_GLERROR; gGL.syncMatrices(); @@ -906,10 +939,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType, (GLvoid*) (indices_offset * (size_t) mIndicesStride)); - STOP_GLERROR; } void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const @@ -932,9 +963,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - STOP_GLERROR; glDrawArrays(sGLMode[mode], first, count); - STOP_GLERROR; } //static @@ -942,14 +971,14 @@ void LLVertexBuffer::initClass(LLWindow* window) { llassert(sVBOPool == nullptr); -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (gGLManager.mIsApple) { LL_INFOS() << "VBO Pooling Disabled" << LL_ENDL; sVBOPool = new LLAppleVBOPool(); } else -#endif +//#endif { LL_INFOS() << "VBO Pooling Enabled" << LL_ENDL; sVBOPool = new LLDefaultVBOPool(); @@ -969,12 +998,12 @@ void LLVertexBuffer::initClass(LLWindow* window) //static void LLVertexBuffer::unbind() { - STOP_GLERROR; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - STOP_GLERROR; sGLRenderBuffer = 0; sGLRenderIndices = 0; + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; } //static @@ -1287,12 +1316,12 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde count = mNumVerts - index; } -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 // Region tracking not needed on apple silicon - it recreates entire buffer // While mIsApple can be encountered under windows, this is a // macOS OpenGL behavior workaround. LL_ARM64 check might be not needed if (!gGLManager.mIsApple) -#endif +//#endif { U32 start = mOffsets[type] + sTypeSize[type] * index; U32 end = start + sTypeSize[type] * count-1; @@ -1329,9 +1358,9 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) count = mNumIndices-index; } -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (!gGLManager.mIsApple) -#endif +//#endif { U32 start = sizeof(U16) * index; U32 end = start + sizeof(U16) * count-1; @@ -1366,7 +1395,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) // dst -- mMappedData or mMappedIndexData void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) { -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (gGLManager.mIsApple) { // on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call @@ -1378,7 +1407,7 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 memcpy(dst+start, data, end-start+1); } else -#endif +//#endif { llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices); @@ -1420,7 +1449,6 @@ void LLVertexBuffer::_mapBuffer() void LLVertexBuffer::_unmapBuffer() { - STOP_GLERROR; if (!mMapped) { return; @@ -1434,7 +1462,7 @@ void LLVertexBuffer::_unmapBuffer() } }; -#if LL_DARWIN || LL_ARM64 +//#if LL_DARWIN || LL_ARM64 if (gGLManager.mIsApple) { STOP_GLERROR; @@ -1447,12 +1475,16 @@ void LLVertexBuffer::_unmapBuffer() mGLBuffer = gen_buffer(); glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; - glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; + glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STREAM_DRAW ); } else if (mGLBuffer != sGLRenderBuffer) { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; } STOP_GLERROR; @@ -1467,7 +1499,7 @@ void LLVertexBuffer::_unmapBuffer() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); sGLRenderIndices = mGLIndices; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STREAM_DRAW ); } else if (mGLIndices != sGLRenderIndices) { @@ -1477,7 +1509,7 @@ void LLVertexBuffer::_unmapBuffer() STOP_GLERROR; } else -#endif // LL_DARWIN || LL_ARM64 +//#endif // LL_DARWIN || LL_ARM64 { if (!mMappedVertexRegions.empty()) { @@ -1692,10 +1724,12 @@ void LLVertexBuffer::setBuffer() { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; + sVertexAttribsConfigured = 0; + sColorPointerSource = 0; setupVertexBuffer(); } - else if (sLastMask != data_mask) + else if (gGLManager.mIsApple || sLastMask != data_mask) { setupVertexBuffer(); sLastMask = data_mask; @@ -1718,98 +1752,108 @@ void LLVertexBuffer::setupVertexBuffer() U8* base = nullptr; U32 data_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + U32 setup_mask = gGLManager.mIsApple ? + data_mask & ~sVertexAttribsConfigured : data_mask; - if (data_mask & MAP_NORMAL) + if (setup_mask & MAP_NORMAL) { AttributeType loc = TYPE_NORMAL; void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); } - if (data_mask & MAP_TEXCOORD3) + if (setup_mask & MAP_TEXCOORD3) { AttributeType loc = TYPE_TEXCOORD3; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); } - if (data_mask & MAP_TEXCOORD2) + if (setup_mask & MAP_TEXCOORD2) { AttributeType loc = TYPE_TEXCOORD2; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); } - if (data_mask & MAP_TEXCOORD1) + if (setup_mask & MAP_TEXCOORD1) { AttributeType loc = TYPE_TEXCOORD1; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); } - if (data_mask & MAP_TANGENT) + if (setup_mask & MAP_TANGENT) { AttributeType loc = TYPE_TANGENT; void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); } - if (data_mask & MAP_TEXCOORD0) + if (setup_mask & MAP_TEXCOORD0) { AttributeType loc = TYPE_TEXCOORD0; void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); } - if (data_mask & MAP_COLOR) + const U32 desired_color_source = (data_mask & MAP_EMISSIVE) ? + COLOR_POINTER_EMISSIVE : + ((data_mask & MAP_COLOR) ? COLOR_POINTER_COLOR : 0); + if (desired_color_source && + (!gGLManager.mIsApple || desired_color_source != sColorPointerSource)) { AttributeType loc = TYPE_COLOR; - //bind emissive instead of color pointer if emissive is present - void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); + void* ptr = desired_color_source == COLOR_POINTER_EMISSIVE ? + (void*)(base + mOffsets[TYPE_EMISSIVE]) : + (void*)(base + mOffsets[TYPE_COLOR]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + sColorPointerSource = desired_color_source; } - if (data_mask & MAP_EMISSIVE) + if (setup_mask & MAP_EMISSIVE) { AttributeType loc = TYPE_EMISSIVE; void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); - - if (!(data_mask & MAP_COLOR)) - { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps - loc = TYPE_COLOR; - glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); - } } - if (data_mask & MAP_WEIGHT) + if (setup_mask & MAP_WEIGHT) { AttributeType loc = TYPE_WEIGHT; void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); } - if (data_mask & MAP_WEIGHT4) + if (setup_mask & MAP_WEIGHT4) { AttributeType loc = TYPE_WEIGHT4; void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); } - if (data_mask & MAP_JOINT) + if (setup_mask & MAP_JOINT) { AttributeType loc = TYPE_JOINT; void* ptr = (void*)(base + mOffsets[TYPE_JOINT]); glVertexAttribIPointer(loc, 4, GL_UNSIGNED_SHORT, LLVertexBuffer::sTypeSize[TYPE_JOINT], ptr); } - if (data_mask & MAP_CLOTHWEIGHT) + if (setup_mask & MAP_CLOTHWEIGHT) { AttributeType loc = TYPE_CLOTHWEIGHT; void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); glVertexAttribPointer(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); } - if (data_mask & MAP_TEXTURE_INDEX) + if (setup_mask & MAP_TEXTURE_INDEX) { AttributeType loc = TYPE_TEXTURE_INDEX; void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12); glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); } - if (data_mask & MAP_VERTEX) + if (setup_mask & MAP_VERTEX) { AttributeType loc = TYPE_VERTEX; void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); } + if (gGLManager.mIsApple) + { + sVertexAttribsConfigured |= data_mask; + if (desired_color_source) + { + sVertexAttribsConfigured |= MAP_COLOR; + } + } STOP_GLERROR; } |
