What does BloomOptimized and 4x anti-aliasing product such huge RenderTexture ram cost?

This is my BloomOpimized script,which is based on Unity’s embedded one:

using System;
using UnityEngine;

namespace UnityStandardAssets.ImageEffects
{
    [ExecuteInEditMode]
    [RequireComponent (typeof(Camera))]
    [AddComponentMenu ("Image Effects/Bloom and Glow/Bloom (Optimized)")]
    public class BloomOptimized : PostEffectsBase
    {

        public enum Resolution
        {
            Low = 0,
            High = 1,
        }

        public enum BlurType
        {
            Standard = 0,
            Sgx = 1,
        }

        [Range(0.0f, 1.5f)]
        public float threshold = 0.25f;
        [Range(0.0f, 2.5f)]
        public float intensity = 0.75f;

        [Range(0.25f, 5.5f)]
        public float blurSize = 1.0f;

        Resolution resolution = Resolution.Low;
        [Range(1, 4)]
        public int blurIterations = 1;

        public BlurType blurType= BlurType.Standard;

        public Shader fastBloomShader = null;
        private Material fastBloomMaterial = null;

  
        public override bool CheckResources ()
        {
            CheckSupport (false);

            fastBloomMaterial = CheckShaderAndCreateMaterial (fastBloomShader, fastBloomMaterial);

            if (!isSupported)
                ReportAutoDisable ();
            return isSupported;
        }

        void OnDisable ()
        {
            if (fastBloomMaterial)
                DestroyImmediate (fastBloomMaterial);
        }

        void OnRenderImage (RenderTexture source, RenderTexture destination)
        {
            if (CheckResources() == false)
            {
                Graphics.Blit (source, destination);
                return;
            }
            source.name = "BloomOptimized";

            int divider = 4;
            float widthMod = 0.5f;

            fastBloomMaterial.SetVector ("_Parameter", new Vector4 (blurSize * widthMod, 0.0f, threshold, intensity));
            source.filterMode = FilterMode.Bilinear;

            var rtW= source.width/divider;
            var rtH= source.height/divider;

            // downsample
            RenderTexture rt = RenderTexture.GetTemporary (rtW /2, rtH / 2, 0, source.format);
        rt.name="BloomOptimized rt";
            rt.filterMode = FilterMode.Bilinear;
            Graphics.Blit (source, rt, fastBloomMaterial, 1);

            //var passOffs= blurType == BlurType.Standard ? 0 : 2;
            var passOffs = 0;

            for(int i = 0; i < blurIterations; i++)
            {
                fastBloomMaterial.SetVector ("_Parameter", new Vector4 (blurSize * widthMod + (i*1.0f), 0.0f, threshold, intensity));

                // vertical blur
                RenderTexture rt2 = RenderTexture.GetTemporary (rtW /2, rtH/2, 0, source.format);
                rt2.name="BloomOptimized rt2";
                rt2.filterMode = FilterMode.Bilinear;
                Graphics.Blit (rt, rt2, fastBloomMaterial, 2 + passOffs);
                RenderTexture.ReleaseTemporary (rt);
                rt = rt2;

                // horizontal blur
                rt2 = RenderTexture.GetTemporary (rtW/2, rtH/2, 0, source.format);
                rt2.name="BloomOptimized rt22";
                rt2.filterMode = FilterMode.Bilinear;
                Graphics.Blit (rt, rt2, fastBloomMaterial, 3 + passOffs);
                RenderTexture.ReleaseTemporary (rt);
                rt = rt2;
            }

            fastBloomMaterial.SetTexture ("_Bloom", rt);

            Graphics.Blit (source, destination, fastBloomMaterial, 0);


            RenderTexture.ReleaseTemporary (rt);
        }
    }
}

And this is the RenderTexture’s RAM profile:
4755941--451625--upload_2019-7-17_19-9-32.png

As it shows,the “source” RT named “BloomOptimized” has a very big 71.2MB size.As the resolution is 21591080,hereby a standard 2048 * 1024 resolution RT will occupy 64MB RAM,which means 1024 * 1024 equals 32MB.And it seems the anti-aliasing index will times the RT producing times,so 32MB / 4 equals 8MB if no anti-aliasing is used.That is still confusing,because RGBA has 4 channels so the maximum RAM it costs would be 4MB for a 10241024 RT.Why it is doubled?

How to reduce this RT ram size considerably?

I find there is a RenderTextureMemoryless.MSAA argument when using RenderTexture.GetTemporary method which seems to be relevant.Maybe it can reduce the RT’s memory size,but as the biggest RT is the “source”,which is retrieved directly from the Engine,not controlled by my script,then I don’t know how to reduce the size of the “source” RT.

And still,no idea why the size is doubled.

As I understand it, it’s because it needs enough space to save all the samples (so whatever the resolution is, times the AA samples).

Memoryless would have helped but AFAIK it only works on iOS/tvOS.

But the profiling result shows that it doubles the memory after resolution timing the AA samples.

My screen resolution is about 2.2K.So the memory of resolution timing AA samples should be about 36MB.But now it is 72MB.

I don’t know where does that final double come from.

What format are your rendertextures?

RGBA32.I think It is not customizable.It is Unity’s default “source” RenderTexture in OnRenderImage() method.

You can see the detail in the codes and profile table.Hightlighted ones in green are those.
4762898--452723--Untitled-2.jpg

Unity’s defaults went out of whack recently, so I doubt it’s ARGB32. If the camera has HDR enabled, it may very well be
ARGBHalf, which uses 16bit per channel instead of 8bit, and that would explain the size.

1 Like

We don’t enable hdr.And the shadow map and depth map’s RT sizes are correct,as shows in the table.Only the image effects(OptmizedBloom)'s RT size is twice as big as what it should be.Really strange.

Do
Debug.Log("Source rt format is : " + source.format);
Debug.Log("Destination rt format is : " + destination.format);

inside OnRenderImage

1 Like

It’s ARGB32.

And the table above is from a low level profiler provider,which is even more accurate than scripting level.