// Copyright (c) 2024 Vuplex Inc. All rights reserved. // // Licensed under the Vuplex Commercial Software Library License, you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // https://vuplex.com/commercial-library-license // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Vuplex.WebView.Internal { /// /// Helper classed used to wait a short delay before deleting Vulkan textures. /// /// /// Due to the workaround for the Unity bug where Texture2D.UpdateExternalTexture() doesn't work /// (see the comments in IWithChangingTexture.cs for details of that), new Texture2D instances /// are frequently created and used to replace the existing web texture. To prevent this from /// causing flickering, this class waits a short delay before deleting old textures. /// public class VulkanDelayedTextureDestroyer : MonoBehaviour { public static VulkanDelayedTextureDestroyer GetInstance(Action destroyVulkanTextureFunction) { if (!_instance) { _instance = (VulkanDelayedTextureDestroyer)new GameObject("VulkanDelayedTextureDestroyer").AddComponent(); _instance._destroyVulkanTextureFunction = destroyVulkanTextureFunction; DontDestroyOnLoad(_instance.gameObject); } return _instance; } public void DestroyTexture(IntPtr nativeTexture) { _textureLists[_indexOfTextureListActiveForDiscarding].Add(nativeTexture); } Action _destroyVulkanTextureFunction; int _indexOfTextureListActiveForDiscarding = 0; static VulkanDelayedTextureDestroyer _instance; // To ensure a delay, toggle between two lists. Use one list for discarding // textures while the textures in the other list are being destroyed. List[] _textureLists = new List[] { new List(), new List() }; WaitForSeconds _waitShortDelay = new WaitForSeconds(0.5f); void OnEnable() => StartCoroutine(_destroyTexturesPeriodically()); IEnumerator _destroyTexturesPeriodically() { while (true) { yield return _waitShortDelay; var indexOfTextureListToDestroy = 1 - _indexOfTextureListActiveForDiscarding; var texturesToDestroy = _textureLists[indexOfTextureListToDestroy]; foreach (var nativeTexture in texturesToDestroy) { _destroyVulkanTextureFunction(nativeTexture); } texturesToDestroy.Clear(); _indexOfTextureListActiveForDiscarding = indexOfTextureListToDestroy; } } } }