Search Unity

Question How do I get Universal RP>Textures out of memory?

Discussion in 'Universal Render Pipeline' started by chrismarch, Oct 8, 2020.

  1. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    On our iOS build, all the textures included in Universal RP are in memory, but our project doesn't reference them, even indirectly. They are all referenced by (only) PostProcessData included in URP, but all of our ForwardRendererData scriptable objects do not reference PostProcessData, and we aren't using the ForwardRendererData scriptable object that is in the URP package.

    We are using Unity 2019.4.10f1, URP 7.5.1 and Addressables 1.16.1, building to iOS 13.

    It even seems we have two copies of all these textures in memory, although we are packing all our addressable groups separately, and ran the deduplication rule... and pack that group separately... and don't use post processing at all.

    Xcode attached to the device build (GPU Capture memory view)
    upload_2020-10-8_14-18-57.png

    Here you can see I confirmed that a sample of these textures are only referenced in the project by the scriptable objects included in URP seen here, and not by any assets we use:
    upload_2020-10-8_14-21-40.png

    Here is the code to walk the references, as output in the console:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. public class FindReferencesInProject
    7. {
    8.     private const string MenuItemText = "Assets/Find References In Project";
    9.  
    10.     [MenuItem(MenuItemText, false, 25)]
    11.     public static void Find()
    12.     {
    13.         var sw = new System.Diagnostics.Stopwatch();
    14.         sw.Start();
    15.  
    16.         var referenceCache = new Dictionary<string, List<string>>();
    17.  
    18.         string[] guids = AssetDatabase.FindAssets("");
    19.         foreach (string guid in guids)
    20.         {
    21.             string assetPath = AssetDatabase.GUIDToAssetPath(guid);
    22.             string[] dependencies = AssetDatabase.GetDependencies(assetPath, false);
    23.  
    24.             foreach (var dependency in dependencies)
    25.             {
    26.                 if (referenceCache.ContainsKey(dependency))
    27.                 {
    28.                     if (!referenceCache[dependency].Contains(assetPath))
    29.                     {
    30.                         referenceCache[dependency].Add(assetPath);
    31.                     }
    32.                 }
    33.                 else
    34.                 {
    35.                     referenceCache[dependency] = new List<string>(){ assetPath };
    36.                 }
    37.             }
    38.         }
    39.  
    40.         Debug.Log("Build index takes " + sw.ElapsedMilliseconds + " milliseconds");
    41.  
    42.         string path = AssetDatabase.GetAssetPath(Selection.activeObject);
    43.         Debug.Log("Find: " + path, Selection.activeObject);
    44.         if (referenceCache.ContainsKey(path))
    45.         {
    46.             foreach (var reference in referenceCache[path])
    47.             {
    48.                 Debug.Log(reference, AssetDatabase.LoadMainAssetAtPath(reference));
    49.             }
    50.         }
    51.         else
    52.         {
    53.             Debug.LogWarning("No references");
    54.         }
    55.  
    56.         referenceCache.Clear();
    57.     }
    58.  
    59.     [MenuItem(MenuItemText, true)]
    60.     public static bool Validate()
    61.     {
    62.         if (Selection.activeObject)
    63.         {
    64.             string path = AssetDatabase.GetAssetPath(Selection.activeObject);
    65.             return !AssetDatabase.IsValidFolder(path);
    66.         }
    67.  
    68.         return false;
    69.     }
    70. }
    From https://github.com/networm/FindReferencesInProject
     
  2. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    I blame the code in ForwardRendererData.cs, which seems to make it impossible for me to set the PostProcessData to None without maybe inheriting from ForwardRendererData and overriding the methods that reload, and undo my inspector changes

    [Reload("Runtime/Data/PostProcessData.asset")]
    public PostProcessData postProcessData = null;


    We don't use dithering, we don't use SMAA, we don't use film grain... we shouldn't need all these MB of textures taking up memory.
     
    Last edited: Oct 8, 2020
  3. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    ugh, spent way to much time figuring this out, and my fix probably won't last a point release. What we really need is the ability to strip all the PostProcessing textures and shaders from a build. URP and Unity are typically for mobile and most mobile titles are going to benefit from avoiding all post...

    EDIT: Unity has a fix in progress to allow stripping post shaders and textures, but it isn't in a 2019 release yet

    (if you point all your forward renderers to a custom PostProcessing asset and go into debug and clear out the textures, then this script will prevent them from reloading... for now)
    Code (CSharp):
    1. #if UNITY_EDITOR
    2. using UnityEditor;
    3. using UnityEditor.ProjectWindowCallback;
    4. #endif
    5. using System;
    6. using UnityEngine.Rendering.Universal;
    7. using UnityEngine;
    8. using UnityEngine.Rendering;
    9.  
    10. namespace UnityEngine.Rendering.Universal
    11. {
    12.     //[CreateAssetMenu(fileName = "ForwardRenderingDataNoPost.asset", menuName = "ScriptableObjects/ForwardRenderingDataNoPost", order = 3)]
    13.     [Serializable, ReloadGroup, ExcludeFromPreset]
    14.     public class ForwardRendererDataNoPost : ForwardRendererData
    15.     {
    16. #if UNITY_EDITOR
    17.         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812")]
    18.         internal class CreateForwardRendererNoPostAsset : EndNameEditAction
    19.         {
    20.             public override void Action(int instanceId, string pathName, string resourceFile)
    21.             {
    22.                 var instance = CreateInstance<ForwardRendererDataNoPost>();
    23.                 AssetDatabase.CreateAsset(instance, pathName);
    24.                 ResourceReloader.ReloadAllNullIn(instance, UniversalRenderPipelineAsset.packagePath);
    25.                 Selection.activeObject = instance;
    26.             }
    27.         }
    28.  
    29.         [MenuItem("Assets/Create/ScriptableObjects/ForwardRenderingDataNoPost", priority = 0)]
    30.         static void CreateForwardRendererData()
    31.         {
    32.             ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, CreateInstance<CreateForwardRendererNoPostAsset>(), "CustomForwardRendererNoPostData.asset", null, null);
    33.         }
    34. #endif
    35.  
    36.         protected override ScriptableRenderer Create()
    37.         {
    38.          
    39. #if UNITY_EDITOR
    40.             if (!Application.isPlaying)
    41.             {
    42.                 ResourceReloader.TryReloadAllNullIn(this, UniversalRenderPipelineAsset.packagePath);
    43.             }
    44. #endif
    45.             return new ForwardRenderer(this);
    46.         }
    47.  
    48.         //#if UNDEFINED
    49.         protected override void OnEnable()
    50.         {
    51.          
    52.             SetDirty();
    53.  
    54.             // Upon asset creation, OnEnable is called and `shaders` reference is not yet initialized
    55.             // We need to call the OnEnable for data migration when updating from old versions of UniversalRP that
    56.             // serialized resources in a different format. Early returning here when OnEnable is called
    57.             // upon asset creation is fine because we guarantee new assets get created with all resources initialized.
    58.             if (shaders == null)
    59.                 return;
    60.  
    61. #if UNITY_EDITOR
    62.             ResourceReloader.TryReloadAllNullIn(this, UniversalRenderPipelineAsset.packagePath);
    63. #endif
    64.  
    65.             /*
    66.             base.OnEnable();
    67. #if UNITY_EDITOR
    68.             postProcessData.textures = null;
    69. #endif
    70. */
    71.         }
    72.     //#endif
    73.     }
    74. }
    75.  
     
    Last edited: Oct 13, 2020
    FardinHaque likes this.
  4. bigbrainz

    bigbrainz

    Joined:
    Jul 21, 2015
    Posts:
    177
    @chrismarch, did you happen to have a current solution for this in 2020.3? We had a workaround script that seemed to be working in 2019.4, but this year Unity seems to be overwriting our changes and forcing unneeded post-processing textures back into the build.

    Note: We'd rather not disable Post-Processing completely, but we certainly don't need all these big, uncompressed, FilmGrain textures. So silly that they're automatically included in a way you can't disable, resize or at least crunch.