From 9d684bc9241cca4aae79d93886d0f95dcee26d65 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 27 Sep 2024 05:38:39 -0400 Subject: Migrate ~LLPointer()'s peculiar warning case to llpointer.cpp. This allows removing #include "llerror.h" from llpointer.h. Also remove #include "llmutex.h" as a heavy way to get . That requires adding #include "llmutex.h" to llimage.h, llnotifications.h, llwatchdog.cpp and llvolumemgr.cpp, which were inheriting it from llpointer.h. --- indra/llmath/llvolumemgr.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index bb0c94d513..d8f649140f 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -25,6 +25,7 @@ #include "linden_common.h" +#include "llmutex.h" #include "llvolumemgr.h" #include "llvolume.h" -- cgit v1.3 From 852e31b6ff639489a199a54029fd10198d134cbd Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Sun, 4 Jan 2026 16:11:29 -0500 Subject: secondlife/viewer#2674 Optimize LLWorld::renderPropertyLines() - use vertexBatchPreTransformed() --- indra/llmath/v3math.h | 9 +++ indra/llrender/llrender.cpp | 63 +++++++++++++++---- indra/llrender/llrender.h | 13 +++- indra/newview/llviewerparceloverlay.cpp | 104 ++++++++++++++++++-------------- indra/newview/llviewerparceloverlay.h | 5 +- 5 files changed, 133 insertions(+), 61 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 196ecdcf7d..0e11dca876 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -155,6 +155,7 @@ class LLVector3 friend const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b); // Returns a * b; friend const LLVector3& operator*=(LLVector3 &a, F32 k); // Return a times scaler k friend const LLVector3& operator/=(LLVector3 &a, F32 k); // Return a divided by scaler k + friend const LLVector3& operator/=(LLVector3& a, const LLVector3& b); friend const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &b); // Returns a * b; friend LLVector3 operator-(const LLVector3 &a); // Return vector -a @@ -460,6 +461,14 @@ inline const LLVector3& operator/=(LLVector3& a, F32 k) return a; } +inline const LLVector3& operator/=(LLVector3& a, const LLVector3& b) +{ + a.mV[VX] /= b.mV[VX]; + a.mV[VY] /= b.mV[VY]; + a.mV[VZ] /= b.mV[VZ]; + return a; +} + inline LLVector3 operator-(const LLVector3& a) { return LLVector3(-a.mV[VX], -a.mV[VY], -a.mV[VZ]); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 57be8570af..1a3a499b20 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1774,25 +1774,64 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) return; } - if (mUIOffset.empty()) + LLVector4a vert(x, y, z); + transform(vert); + mVerticesp[mCount] = vert; + + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +} + +void LLRender::transform(LLVector3& vert) +{ + if (!mUIOffset.empty()) { - mVerticesp[mCount].set(x,y,z); + vert += LLVector3(mUIOffset.back().getF32ptr()); + vert *= LLVector3(mUIScale.back().getF32ptr()); } - else +} + +void LLRender::transform(LLVector4a& vert) +{ + if (!mUIOffset.empty()) { - LLVector4a vert(x, y, z); vert.add(mUIOffset.back()); vert.mul(mUIScale.back()); - mVerticesp[mCount] = vert; } +} - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +void LLRender::untransform(LLVector3& vert) +{ + if (!mUIOffset.empty()) + { + vert /= LLVector3(mUIScale.back().getF32ptr()); + vert -= LLVector3(mUIOffset.back().getF32ptr()); + } +} + +void LLRender::batchTransform(LLVector4a* verts, U32 vert_count) +{ + if (!mUIOffset.empty()) + { + const LLVector4a& offset = mUIOffset.back(); + const LLVector4a& scale = mUIScale.back(); + + for (U32 i = 0; i < vert_count; ++i) + { + verts[i].add(offset); + verts[i].mul(scale); + } + } +} + +void LLRender::vertexBatchPreTransformed(const std::vector& verts) +{ + vertexBatchPreTransformed(verts.data(), narrow(verts.size())); } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1813,7 +1852,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1837,7 +1876,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 } } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U* colors, S32 vert_count) { if (mCount + vert_count > 4094) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 0801c12fb4..be8539433c 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -450,9 +450,16 @@ public: void diffuseColor4ubv(const U8* c); void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); - void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); - void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); + void transform(LLVector3& vert); + void transform(LLVector4a& vert); + void untransform(LLVector3& vert); + + void batchTransform(LLVector4a* verts, U32 vert_count); + + void vertexBatchPreTransformed(const std::vector& verts); + void vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 6b4bcbe86e..63bcd82798 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -555,52 +555,52 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 inside_z = land.resolveHeightRegion(inside_x, inside_y); }; - auto split = [&](U32 lod, const LLVector3& start, F32 x, F32 y, F32 z, F32 part) + auto split = [&](U32 lod, const LLVector4a& start, F32 x, F32 y, F32 z, F32 part) { - F32 new_x = start.mV[VX] + (x - start.mV[VX]) * part; - F32 new_y = start.mV[VY] + (y - start.mV[VY]) * part; - F32 new_z = start.mV[VZ] + (z - start.mV[VZ]) * part; - edge.vertices[lod].emplace_back(new_x, new_y, new_z); + F32 new_x = start[VX] + (x - start[VX]) * part; + F32 new_y = start[VY] + (y - start[VY]) * part; + F32 new_z = start[VZ] + (z - start[VZ]) * part; + edge.pushVertex(lod, new_x, new_y, new_z, water_z); }; auto checkForSplit = [&](U32 lod) { - const std::vector& vertices = edge.vertices[lod]; - const LLVector3& last_outside = vertices.back(); - F32 z0 = last_outside.mV[VZ]; + const std::vector& vertices = edge.verticesUnderWater[lod]; + const LLVector4a& last_outside = vertices.back(); + F32 z0 = last_outside[VZ]; F32 z1 = outside_z; if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z)) return; F32 part = (water_z - z0) / (z1 - z0); - const LLVector3& last_inside = vertices[vertices.size() - 2]; + const LLVector4a& last_inside = vertices[vertices.size() - 2]; split(lod, last_inside, inside_x, inside_y, inside_z, part); split(lod, last_outside, outside_x, outside_y, outside_z, part); }; auto pushTwoVertices = [&](U32 lod) { + LLVector3 out(outside_x, outside_y, outside_z); + LLVector3 in(inside_x, inside_y, inside_z); if (fabs(inside_z - outside_z) < LINE_WIDTH / 5) { - edge.vertices[lod].emplace_back(inside_x, inside_y, inside_z); + edge.pushVertex(lod, inside_x, inside_y, inside_z, water_z); } else { // Make the line thinner if heights differ too much - LLVector3 out(outside_x, outside_y, outside_z); - LLVector3 in(inside_x, inside_y, inside_z); LLVector3 dist(in - out); F32 coef = dist.length() / LINE_WIDTH; LLVector3 new_in(out + dist / coef); - edge.vertices[lod].push_back(new_in); + edge.pushVertex(lod, new_in[VX], new_in[VY], new_in[VZ], water_z); } - edge.vertices[lod].emplace_back(outside_x, outside_y, outside_z); + edge.pushVertex(lod, outside_x, outside_y, outside_z, water_z); }; // Point A simplified (first two vertices) pushTwoVertices(1); // Point A detailized (only one vertex) - edge.vertices[0].emplace_back(outside_x, outside_y, outside_z); + edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); // Point B (two vertices) move(LINE_WIDTH); @@ -628,7 +628,23 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 pushTwoVertices(1); // Point G detailized (only one vertex) - edge.vertices[0].emplace_back(outside_x, outside_y, outside_z); + edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); +} + +void LLViewerParcelOverlay::Edge::pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z) +{ + verticesUnderWater[lod].emplace_back(x, y, z); + gGL.transform(verticesUnderWater[lod].back()); + + if (z >= water_z) + { + verticesAboveWater[lod].push_back(verticesUnderWater[lod].back()); + } + else + { + verticesAboveWater[lod].emplace_back(x, y, water_z); + gGL.transform(verticesAboveWater[lod].back()); + } } void LLViewerParcelOverlay::setDirty() @@ -673,6 +689,9 @@ void LLViewerParcelOverlay::renderPropertyLines() if (!show) return; + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_GPU_ZONE("Property Lines"); + LLSurface& land = mRegion->getLand(); bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); @@ -710,6 +729,8 @@ void LLViewerParcelOverlay::renderPropertyLines() // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgentCamera.getCameraPositionGlobal() ); + bool draw_underwater = camera_region.mV[VZ] < water_z || + !gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); // Set up a cull plane 2 * PARCEL_GRID_STEP_METERS behind // the camera. The cull plane normal is the camera's at axis. @@ -717,17 +738,22 @@ void LLViewerParcelOverlay::renderPropertyLines() cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS; cull_plane_point += camera_region; - bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); + bool render_hidden = !draw_underwater && + LLSelectMgr::sRenderHiddenSelections && + LLFloaterReg::instanceVisible("build"); constexpr F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; const F32 PROPERTY_LINE_LOD0_DIST_SQUARED = PROPERTY_LINE_CLIP_DIST_SQUARED / 25; for (const Edge& edge : mEdges) { - const std::vector& vertices0 = edge.vertices[0]; - LLVector3 center = (vertices0.front() + vertices0.back()) / 2; - F32 dist_squared = dist_vec_squared(center, camera_region); + const std::vector& vertices0 = edge.verticesAboveWater[0]; + const F32* first = vertices0.front().getF32ptr(); + const F32* last = vertices0.back().getF32ptr(); + LLVector3 center((first[VX] + last[VX]) / 2, (first[VY] + last[VY]) / 2, (first[VZ] + last[VZ]) / 2); + gGL.untransform(center); + F32 dist_squared = dist_vec_squared(center, camera_region); if (dist_squared > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; @@ -748,39 +774,27 @@ void LLViewerParcelOverlay::renderPropertyLines() gGL.color4ubv(edge.color.mV); - for (const LLVector3& vertex : edge.vertices[lod]) + if (draw_underwater) { - if (render_hidden || camera_z < water_z || vertex.mV[2] >= water_z) - { - gGL.vertex3fv(vertex.mV); - } - else - { - LLVector3 visible = vertex; - visible.mV[VZ] = water_z; - gGL.vertex3fv(visible.mV); - } + gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); } - - gGL.end(); - - if (render_hidden) + else { - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.vertexBatchPreTransformed(edge.verticesAboveWater[lod]); - gGL.begin(LLRender::TRIANGLE_STRIP); + if (render_hidden) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - LLColor4U color = edge.color; - color.mV[VALPHA] /= 4; - gGL.color4ubv(color.mV); + LLColor4U color = edge.color; + color.mV[VALPHA] /= 4; + gGL.color4ubv(color.mV); - for (const LLVector3& vertex : edge.vertices[lod]) - { - gGL.vertex3fv(vertex.mV); + gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); } - - gGL.end(); } + + gGL.end(); } gGL.popMatrix(); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 68900d16a6..7271c85701 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -116,7 +116,10 @@ private: struct Edge { - std::vector vertices[2]; // 0 - detailized, 1 - simplified + void pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z); + // LOD: 0 - detailized, 1 - simplified + std::vector verticesAboveWater[2]; + std::vector verticesUnderWater[2]; LLColor4U color; }; -- cgit v1.3 From 676cb60ee2cb9223c0b99403fba355a293888319 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Fri, 9 Jan 2026 00:28:48 +0200 Subject: #5238 Minor adjustments for LLVolumeFace crash handling --- indra/llkdu/llimagej2ckdu.cpp | 5 +++++ indra/llmath/llvolume.cpp | 27 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 7eba9494a6..e7ac6bdb31 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -615,6 +615,11 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco return false; } } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Bad memory allocation in J2C KDU" << LL_ENDL; + } catch (const KDUError& msg) { base.setLastError(msg.what()); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b3cb278d59..85172ddbf8 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4943,9 +4943,17 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mOctree(NULL), mOctreeTriangles(NULL) { - mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); - mCenter = mExtents+2; - *this = src; + try + { + mExtents = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * 3); + mCenter = mExtents + 2; + *this = src; + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLVolume") << "Bad memory allocation in LLVolumeFace" << LL_ENDL; + } } LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) @@ -5681,7 +5689,12 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) catch (std::bad_alloc&) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL; + LL_ERRS("LLVolume") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL; + } + catch (...) + { + LL_WARNS_ONCE("LLVolume") << "Mikktspace::genTangSpace() failed" << LL_ENDL; + return false; } @@ -5703,7 +5716,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) catch (std::bad_alloc&) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL; + LL_ERRS("LLVOLUME") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL; } U32 stream_count = data.w.empty() ? 4 : 5; @@ -5720,7 +5733,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) catch (std::bad_alloc&) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL; + LL_ERRS("LLVolume") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL; } } @@ -5732,7 +5745,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) if (mNumVertices == 0) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL; + LL_ERRS("LLVolume") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL; } if (!data.w.empty()) -- cgit v1.3 From d541eb9c300a5e362e059442e60ab83d97050d82 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Fri, 9 Jan 2026 23:03:50 +0200 Subject: #5249 Crash at LLVolumeFace::remap() Crash happens inside generateRemapMultiwith, no clear cause. Ideally we need the crashing model, but untill that, zero-initing remap. meshopt wants zero initialized paddings and since we are providing more space than nessesary, that might count as padding. --- indra/llmath/llvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 85172ddbf8..ecc5a7b0c5 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5171,7 +5171,7 @@ void LLVolumeFace::remap() // Documentation for meshopt_generateVertexRemapMulti claims that remap should use vertice count // but all examples use indice count. There are out of bounds crashes when using vertice count. // To be on the safe side use bigger of the two. - std::vector remap(llmax(mNumIndices, mNumVertices)); + std::vector remap(llmax(mNumIndices, mNumVertices), 0); S32 remap_vertices_count = static_cast(LLMeshOptimizer::generateRemapMultiU16(&remap[0], mIndices, mNumIndices, -- cgit v1.3 From 58ed702a7727983ea89f2210add453ffc8dac06a Mon Sep 17 00:00:00 2001 From: TJ Date: Mon, 19 Jan 2026 11:16:58 +1000 Subject: Fix hollowed prims not shading correctly and appearing not smooth (#3013, #5293) --- indra/llmath/llvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index ecc5a7b0c5..c74ea3e42b 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -912,7 +912,7 @@ bool LLProfile::generate(const LLProfileParams& params, bool path_open,F32 detai case LL_PCODE_HOLE_CIRCLE: case LL_PCODE_HOLE_SAME: default: - addHole(params, true, circle_detail, 0, hollow, 1.f); + addHole(params, false, circle_detail, 0, hollow, 1.f); break; } } -- cgit v1.3