using NativeEngine; namespace Sandbox; public partial class RenderAttributes { // Keep a list of textures we've used, CRenderAttributes doesn't use strong handles. // This is mainly here to keep textures alive when stored in long lived attributes like SceneObject.Attributes // Otherwise the GC may collect them while still in use by native code. // It could be done on CRenderAttributes natively, but we tried that before and fucked it, it's complicated. private Dictionary usedTextures; // lazy allocated private void SetUsedTexture( StringToken k, Texture texture ) { usedTextures ??= []; var native = texture?.native ?? default; // Is this key already holding a texture if ( usedTextures.TryGetValue( k, out var old ) ) { // Does the existing data point to the same as the new data? // If so, nothing to do! if ( native.IsValid && old.GetBindingPtr() == native.GetBindingPtr() ) return; // Otherwise, kill our old handle, we're replacing it old.DestroyStrongHandle(); } // If our new handle is null, don't write it, just remove any possible entry if ( native.IsNull ) { usedTextures.Remove( k ); return; } // Finally COPY a strong handle, otherwise we're at the mercy of Texture.Dispose() usedTextures[k] = native.CopyStrongHandle(); } /// /// Clear used textures, destroying any strong handles we've created. /// These handles are mainly used for storage RenderAttributes like SceneObject.Attributes /// private void ClearUsedTextures() { if ( usedTextures is null ) return; // Clean up any strong handles foreach ( var tex in usedTextures.Values ) { if ( !tex.IsValid ) continue; tex.DestroyStrongHandle(); } usedTextures.Clear(); } }