diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index a33bf88f9d..bfeb055599 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5664,29 +5664,29 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) mWeights[dst_idx].loadua(data.w[src_idx].mV); } } + + // put back in normalized coordinate frame + LLVector4a inv_scale(1.f/mNormalizedScale.mV[0], 1.f / mNormalizedScale.mV[1], 1.f / mNormalizedScale.mV[2]); + LLVector4a scale; + scale.load3(mNormalizedScale.mV); + scale.getF32ptr()[3] = 1.f; + + for (int i = 0; i < mNumVertices; ++i) + { + mPositions[i].mul(inv_scale); + mNormals[i].mul(scale); + mNormals[i].normalize3(); + F32 w = mTangents[i].getF32ptr()[3]; + mTangents[i].mul(scale); + mTangents[i].normalize3(); + mTangents[i].getF32ptr()[3] = w; + } } else { // blew past the max vertex size limit, use legacy tangent generation which never adds verts createTangents(); } - - // put back in normalized coordinate frame - LLVector4a inv_scale(1.f/mNormalizedScale.mV[0], 1.f / mNormalizedScale.mV[1], 1.f / mNormalizedScale.mV[2]); - LLVector4a scale; - scale.load3(mNormalizedScale.mV); - scale.getF32ptr()[3] = 1.f; - - for (int i = 0; i < mNumVertices; ++i) - { - mPositions[i].mul(inv_scale); - mNormals[i].mul(scale); - mNormals[i].normalize3(); - F32 w = mTangents[i].getF32ptr()[3]; - mTangents[i].mul(scale); - mTangents[i].normalize3(); - mTangents[i].getF32ptr()[3] = w; - } } // cache optimize index buffer diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 5eb8d246bc..be9c722913 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -355,6 +355,11 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool void run() override; void close() override; // [FIRE-32453][BUG-232971] Improve shutdown behaviour. + void glReady() + { + mGLReady = true; + } + // initialzie DXGI adapter (for querying available VRAM) void initDX(); @@ -413,6 +418,9 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool HWND mWindowHandle = NULL; HDC mhDC = 0; + // *HACK: Attempt to prevent startup crashes by deferring memory accounting + // until after some graphics setup. See SL-20177. -Cosmic,2023-09-18 + bool mGLReady = false; // best guess at available video memory in MB std::atomic mAvailableVRAM; @@ -1734,6 +1742,13 @@ const S32 max_format = (S32)num_formats - 1; // ok to post quit messages now mPostQuit = TRUE; + // *HACK: Attempt to prevent startup crashes by deferring memory accounting + // until after some graphics setup. See SL-20177. -Cosmic,2023-09-18 + mWindowThread->post([=]() + { + mWindowThread->glReady(); + }); + if (auto_show) { show(); @@ -4826,6 +4841,8 @@ void debugEnumerateGraphicsAdapters() void LLWindowWin32::LLWindowWin32Thread::initDX() { + if (!mGLReady) { return; } + if (mDXGIAdapter == NULL) { debugEnumerateGraphicsAdapters(); @@ -4860,6 +4877,8 @@ void LLWindowWin32::LLWindowWin32Thread::initDX() void LLWindowWin32::LLWindowWin32Thread::initD3D() { + if (!mGLReady) { return; } + if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandle != 0) { mD3D = Direct3DCreate9(D3D_SDK_VERSION); @@ -4886,6 +4905,8 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D() void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() { LL_PROFILE_ZONE_SCOPED; + if (!mGLReady) { return; } + if (mDXGIAdapter != nullptr) { // NOTE: what lies below is hand wavy math based on compatibility testing and observation against a variety of hardware @@ -4993,8 +5014,6 @@ void LLWindowWin32::LLWindowWin32Thread::run() try { // - initDX(); - //as good a place as any to up the MM timer resolution (see ms_sleep) //attempt to set timer resolution to 1ms TIMECAPS tc; @@ -5007,9 +5026,12 @@ void LLWindowWin32::LLWindowWin32Thread::run() { LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; + // lazily call initD3D inside this loop to catch when mGLReady has been set to true + initDX(); + if (mWindowHandle != 0) { - // lazily call initD3D inside this loop to catch when mWindowHandle has been set + // lazily call initD3D inside this loop to catch when mWindowHandle has been set, and mGLReady has been set to true // *TODO: Shutdown if this fails when mWindowHandle exists initD3D(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 56d48adfdc..a1d0b920d7 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1192,22 +1192,32 @@ void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) } BOOL LLFace::getGeometryVolume(const LLVolume& volume, - const S32 &f, - const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in, - const U16 &index_offset, - bool force_rebuild) + S32 face_index, + const LLMatrix4& mat_vert_in, + const LLMatrix3& mat_norm_in, + U16 index_offset, + bool force_rebuild, + bool no_debug_assert) { LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE; llassert(verify()); - if (volume.getNumVolumeFaces() <= f) { - LL_WARNS() << "Attempt get volume face out of range! Total Faces: " << volume.getNumVolumeFaces() << " Attempt get access to: " << f << LL_ENDL; - return FALSE; - } + if (face_index < 0 || face_index >= volume.getNumVolumeFaces()) + { + if (gDebugGL) + { + LL_WARNS() << "Face index is out of bounds!" << LL_ENDL; + LL_WARNS() << "Attempt get volume face out of range!" + " Total Faces: " << volume.getNumVolumeFaces() << + " Attempt get access to: " << face_index << LL_ENDL; + llassert(no_debug_assert); + } + return FALSE; + } bool rigged = isState(RIGGED); - const LLVolumeFace &vf = volume.getVolumeFace(f); + const LLVolumeFace &vf = volume.getVolumeFace(face_index); S32 num_vertices = (S32)vf.mNumVertices; S32 num_indices = (S32) vf.mNumIndices; @@ -1236,14 +1246,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (gDebugGL) { - LL_WARNS() << "Index buffer overflow!" << LL_ENDL; + LL_WARNS() << "Index buffer overflow!" << LL_ENDL; LL_WARNS() << "Indices Count: " << mIndicesCount << " VF Num Indices: " << num_indices << " Indices Index: " << mIndicesIndex << " VB Num Indices: " << mVertexBuffer->getNumIndices() << LL_ENDL; - LL_WARNS() << " Face Index: " << f + LL_WARNS() << " Face Index: " << face_index << " Pool Type: " << mPoolType << LL_ENDL; - llassert(false); + llassert(no_debug_assert); } return FALSE; } @@ -1253,7 +1263,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (gDebugGL) { LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL; - llassert(false); + llassert(no_debug_assert); } return FALSE; } @@ -1292,7 +1302,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, bool rebuild_tangent = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TANGENT); bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); - const LLTextureEntry *tep = mVObjp->getTE(f); + const LLTextureEntry *tep = mVObjp->getTE(face_index); const U8 bump_code = tep ? tep->getBumpmap() : 0; BOOL is_static = mDrawablep->isStatic(); @@ -1513,7 +1523,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (bump_code) { - mVObjp->getVolume()->genTangents(f); + mVObjp->getVolume()->genTangents(face_index); F32 offset_multiple; switch( bump_code ) { @@ -1566,7 +1576,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) { //planar texgen needs binormals - mVObjp->getVolume()->genTangents(f); + mVObjp->getVolume()->genTangents(face_index); } U8 tex_mode = 0; @@ -1856,7 +1866,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount); - mVObjp->getVolume()->genTangents(f); + mVObjp->getVolume()->genTangents(face_index); for (S32 i = 0; i < num_vertices; i++) { @@ -1997,7 +2007,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount); F32* tangents = (F32*) tangent.get(); - mVObjp->getVolume()->genTangents(f); + mVObjp->getVolume()->genTangents(face_index); LLVector4Logical mask; mask.clear(); diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 12663799c9..b76bfd7e86 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -157,10 +157,12 @@ public: void updateRebuildFlags(); bool canRenderAsMask(); // logic helper BOOL getGeometryVolume(const LLVolume& volume, - const S32 &f, - const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, - const U16 &index_offset, - bool force_rebuild = false); + S32 face_index, + const LLMatrix4& mat_vert, + const LLMatrix3& mat_normal, + U16 index_offset, + bool force_rebuild = false, + bool no_debug_assert = false); // For avatar U16 getGeometryAvatar( diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 786bb93ca1..3ce5201628 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -125,7 +125,7 @@ const std::string LLFloaterPermsDefault::sCategoryNames[CAT_LAST] = "Notecards", "Gestures", "Wearables", - "Settings" + "Settings", "Materials" }; diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h index b3912d2e79..6fb2878cbc 100644 --- a/indra/newview/llfloaterperms.h +++ b/indra/newview/llfloaterperms.h @@ -77,6 +77,7 @@ enum Categories CAT_GESTURES, CAT_WEARABLES, CAT_SETTINGS, + CAT_MATERIALS, CAT_LAST }; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 137f589616..93fe60e5eb 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1130,6 +1130,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) && objectp->permModify()) { BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced(); + BOOL attachment = objectp->isAttachment(); bool has_pbr_material; bool has_faces_without_pbr; @@ -1429,6 +1430,18 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mTextureCtrl->setBakeTextureEnabled(TRUE); } + + if (attachment) + { + // attachments are in world and in inventory, + // server doesn't support changing permissions + // in such case + mTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + } } if (mShinyTextureCtrl) @@ -1436,6 +1449,15 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mShinyTextureCtrl->setTentative( !identical_spec ); mShinyTextureCtrl->setEnabled( editable && !has_pbr_material ); mShinyTextureCtrl->setImageAssetID( specmap_id ); + + if (attachment) + { + mShinyTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + mShinyTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + } } if (mBumpyTextureCtrl) @@ -1443,6 +1465,15 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mBumpyTextureCtrl->setTentative( !identical_norm ); mBumpyTextureCtrl->setEnabled( editable && !has_pbr_material ); mBumpyTextureCtrl->setImageAssetID( normmap_id ); + + if (attachment) + { + mBumpyTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + mBumpyTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + } } } @@ -2068,6 +2099,15 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, pbr_ctrl->setTentative(identical_pbr ? FALSE : TRUE); pbr_ctrl->setEnabled(settable); pbr_ctrl->setImageAssetID(pbr_id); + + if (objectp->isAttachment()) + { + pbr_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER | PERM_MODIFY); + } + else + { + pbr_ctrl->setImmediateFilterPermMask(PERM_NONE); + } } getChildView("pbr_from_inventory")->setEnabled(settable); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 8f929c6b17..f6c369cd6d 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -369,6 +369,15 @@ void LLPanelVolume::getState( ) { LightTextureCtrl->setEnabled(FALSE); LightTextureCtrl->setValid(FALSE); + + if (objectp->isAttachment()) + { + LightTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + LightTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + } } getChildView("Light Intensity")->setEnabled(false); @@ -1441,6 +1450,19 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item if (volobjp) { LLViewerInventoryItem* item = gInventory.getItem(item_id); + + if (item && volobjp->isAttachment()) + { + const LLPermissions& perm = item->getPermissions(); + BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; + if (!unrestricted) + { + // Attachments are in world and in inventory simultaneously, + // at the moment server doesn't support such a situation. + return; + } + } + if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) { LLToolDragAndDrop::handleDropMaterialProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 51e26b8ba6..ea8ac1cd9f 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1938,10 +1938,24 @@ bool LLSelectMgr::selectionSetImage(const LLUUID& imageid) f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} bool apply(LLViewerObject* objectp, S32 te) { - if(objectp && !objectp->permModify()) + if(!objectp || !objectp->permModify()) { return false; } + + // Might be better to run willObjectAcceptInventory + if (mItem && objectp->isAttachment()) + { + const LLPermissions& perm = mItem->getPermissions(); + BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; + if (!unrestricted) + { + // Attachments are in world and in inventory simultaneously, + // at the moment server doesn't support such a situation. + return false; + } + } + if (mItem) { LLToolDragAndDrop::dropTextureOneFace(objectp, @@ -2024,10 +2038,21 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mMatId(id) {} bool apply(LLViewerObject* objectp, S32 te) { - if (objectp && !objectp->permModify()) + if (!objectp || !objectp->permModify()) { return false; } + if (mItem && objectp->isAttachment()) + { + const LLPermissions& perm = mItem->getPermissions(); + BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; + if (!unrestricted) + { + // Attachments are in world and in inventory simultaneously, + // at the moment server doesn't support such a situation. + return false; + } + } LLUUID asset_id = mMatId; if (mItem) { @@ -2342,7 +2367,19 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id) if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) { LLViewerObject *object = mSelectedObjects->getFirstRootObject(); - if (!object) return; + if (!object) + { + return; + } + const LLPermissions& perm = item->getPermissions(); + BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; + BOOL attached = object->isAttachment(); + if (attached && !unrestricted) + { + // Attachments are in world and in inventory simultaneously, + // at the moment server doesn't support such a situation. + return; + } LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); } getSelection()->applyToTEs(&setfunc); @@ -2402,7 +2439,19 @@ void LLSelectMgr::selectionSetShiny(U8 shiny, const LLUUID &image_id) if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) { LLViewerObject *object = mSelectedObjects->getFirstRootObject(); - if (!object) return; + if (!object) + { + return; + } + const LLPermissions& perm = item->getPermissions(); + BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; + BOOL attached = object->isAttachment(); + if (attached && !unrestricted) + { + // Attachments are in world and in inventory simultaneously, + // at the moment server doesn't support such a situation. + return; + } LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); } getSelection()->applyToTEs(&setfunc); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 391bb0cd67..888f1d5a72 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1481,6 +1481,12 @@ void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryT } } +void LLFloaterTexturePicker::setImmediateFilterPermMask(PermissionMask mask) +{ + mImmediateFilterPermMask = mask; + mInventoryPanel->setFilterPermMask(mask); +} + void LLFloaterTexturePicker::onPickerCallback(const std::vector& filenames, LLHandle handle) { std::vector::const_iterator iter = filenames.begin(); @@ -1684,6 +1690,17 @@ void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) } } +void LLTextureCtrl::setImmediateFilterPermMask(PermissionMask mask) +{ + mImmediateFilterPermMask = mask; + + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if (floaterp) + { + floaterp->setImmediateFilterPermMask(mask); + } +} + void LLTextureCtrl::setVisible( BOOL visible ) { if( !visible ) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 05209137be..56db8fae24 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -187,8 +187,7 @@ public: void setCanApply(bool can_preview, bool can_apply); - void setImmediateFilterPermMask(PermissionMask mask) - { mImmediateFilterPermMask = mask; } + void setImmediateFilterPermMask(PermissionMask mask); void setDnDFilterPermMask(PermissionMask mask) { mDnDFilterPermMask = mask; } PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; } @@ -367,6 +366,7 @@ public: void setBakeTextureEnabled(BOOL enabled); void setInventoryPickType(LLTextureCtrl::EPickInventoryType type); + void setImmediateFilterPermMask(PermissionMask mask); static void onPickerCallback(const std::vector& filenames, LLHandle handle); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 4291174a6b..f8360146eb 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1688,6 +1688,8 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL if(attached && !unrestricted) { + // Attachments are in world and in inventory simultaneously, + // at the moment server doesn't support such a situation. return ACCEPT_NO_LOCKED; } else if(modify && transfer && volume && !worn) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 88b416f2b4..0d41bcfc7f 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2185,7 +2185,8 @@ bool LLViewerFetchedTexture::updateFetch() } } - llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid)); + llassert_always(mRawImage.notNull() || !mIsRawImageValid); + llassert_always(mRawImage.notNull() || !mNeedsCreateTexture); return mIsFetching ? true : false; } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 51897f5aaf..ecb7685451 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -6406,12 +6406,18 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { - if (!face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) - { //something's gone wrong with the vertex buffer accounting, rebuild this group - group->dirtyGeom(); - gPipeline.markRebuild(group); - } + if (!face->getGeometryVolume(*volume, // volume + face->getTEOffset(), // face_index + vobj->getRelativeXform(), // mat_vert_in + vobj->getRelativeXformInvTrans(), // mat_norm_in + face->getGeomIndex(), // index_offset + false, // force_rebuild + true)) // no_debug_assert + { // Something's gone wrong with the vertex buffer accounting, + // rebuild this group with no debug assert because MESH_DIRTY + group->dirtyGeom(); + gPipeline.markRebuild(group); + } buff->unmapBuffer(); }