VulkanDelayedTextureDestroyer.cs 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright (c) 2024 Vuplex Inc. All rights reserved.
  2. //
  3. // Licensed under the Vuplex Commercial Software Library License, you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // https://vuplex.com/commercial-library-license
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. using System;
  15. using System.Collections;
  16. using System.Collections.Generic;
  17. using UnityEngine;
  18. namespace Vuplex.WebView.Internal {
  19. /// <summary>
  20. /// Helper classed used to wait a short delay before deleting Vulkan textures.
  21. /// </summary>
  22. /// <remarks>
  23. /// Due to the workaround for the Unity bug where Texture2D.UpdateExternalTexture() doesn't work
  24. /// (see the comments in IWithChangingTexture.cs for details of that), new Texture2D instances
  25. /// are frequently created and used to replace the existing web texture. To prevent this from
  26. /// causing flickering, this class waits a short delay before deleting old textures.
  27. /// </remarks>
  28. public class VulkanDelayedTextureDestroyer : MonoBehaviour {
  29. public static VulkanDelayedTextureDestroyer GetInstance(Action<IntPtr> destroyVulkanTextureFunction) {
  30. if (!_instance) {
  31. _instance = (VulkanDelayedTextureDestroyer)new GameObject("VulkanDelayedTextureDestroyer").AddComponent<VulkanDelayedTextureDestroyer>();
  32. _instance._destroyVulkanTextureFunction = destroyVulkanTextureFunction;
  33. DontDestroyOnLoad(_instance.gameObject);
  34. }
  35. return _instance;
  36. }
  37. public void DestroyTexture(IntPtr nativeTexture) {
  38. _textureLists[_indexOfTextureListActiveForDiscarding].Add(nativeTexture);
  39. }
  40. Action<IntPtr> _destroyVulkanTextureFunction;
  41. int _indexOfTextureListActiveForDiscarding = 0;
  42. static VulkanDelayedTextureDestroyer _instance;
  43. // To ensure a delay, toggle between two lists. Use one list for discarding
  44. // textures while the textures in the other list are being destroyed.
  45. List<IntPtr>[] _textureLists = new List<IntPtr>[] {
  46. new List<IntPtr>(),
  47. new List<IntPtr>()
  48. };
  49. WaitForSeconds _waitShortDelay = new WaitForSeconds(0.5f);
  50. void OnEnable() => StartCoroutine(_destroyTexturesPeriodically());
  51. IEnumerator _destroyTexturesPeriodically() {
  52. while (true) {
  53. yield return _waitShortDelay;
  54. var indexOfTextureListToDestroy = 1 - _indexOfTextureListActiveForDiscarding;
  55. var texturesToDestroy = _textureLists[indexOfTextureListToDestroy];
  56. foreach (var nativeTexture in texturesToDestroy) {
  57. _destroyVulkanTextureFunction(nativeTexture);
  58. }
  59. texturesToDestroy.Clear();
  60. _indexOfTextureListActiveForDiscarding = indexOfTextureListToDestroy;
  61. }
  62. }
  63. }
  64. }