Fixing RenderTextureDescriptor warning

Hi,

I’m having an issue using a temporary render texture as output of a camera.
It’s working fine, however it’s giving me this warning that I don’t know how to fix

In the render graph API, the output Render Texture must have a depth buffer. When you select a Render Texture in any camera’s Output Texture property, the Depth Stencil Format property of the texture must be set to a value other than None.
UnityEngine.Rendering.RenderPipelineManager:DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset,intptr,UnityEngine.Object,Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle)

The RenderTextureDescriptor looks like this:

        RenderTextureDescriptor texDesc = new RenderTextureDescriptor();
        texDesc.width = 1024;
        texDesc.height = 1024;
        texDesc.colorFormat = RenderTextureFormat.ARGBHalf;
        texDesc.dimension = TextureDimension.Tex2D;
        texDesc.autoGenerateMips = false;
        texDesc.depthBufferBits = 0;
        texDesc.msaaSamples = 1;
        texDesc.volumeDepth = 2;

I tried:

  • setting the depthBufferBits to 16
  • adding texDesc.graphicsFormat = GraphicsFormat.R16G16B16A16_SNorm ( or other formats )
  • adding texDesc.depthStencilFormat = GraphicsFormat.D16_UNorm (or other formats)

But all of this results in this error and the script stops working.

AssertionException: Assertion failure. Value was False
Expected: True
UnityEngine.Assertions.Assert.Fail (System.String message, System.String userMessage) (at :0)
UnityEngine.Assertions.Assert.IsTrue (System.Boolean condition, System.String message) (at :0)
UnityEngine.Assertions.Assert.IsTrue (System.Boolean condition) (at :0)
UnityEngine.Rendering.Universal.RenderingUtils.ReAllocateHandleIfNeeded (UnityEngine.Rendering.RTHandle& handle, UnityEngine.RenderTextureDescriptor& descriptor, UnityEngine.FilterMode filterMode, UnityEngine.TextureWrapMode wrapMode, System.Int32 anisoLevel, System.Single mipMapBias, System.String name) (at ./Library/PackageCache/com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs:824)
FluidSimulation.Simulate (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera camera) (at Assets/FluidSimulation/Scripts/FluidSimulation.cs:137)
FluidSimulation.OnBeginCameraRendering (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera camera) (at Assets/FluidSimulation/Scripts/FluidSimulation.cs:120)
UnityEngine.Rendering.RenderPipelineManager.BeginCameraRendering (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera camera) (at :0)
UnityEngine.Rendering.RenderPipeline.BeginCameraRendering (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera camera) (at :0)
UnityEngine.Rendering.Universal.UniversalRenderPipeline+CameraRenderingScope…ctor (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera camera) (at ./Library/PackageCache/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs:361)
UnityEngine.Rendering.Universal.UniversalRenderPipeline.Render (UnityEngine.Rendering.ScriptableRenderContext renderContext, System.Collections.Generic.List1[T] cameras) (at ./Library/PackageCache/com.unity.render-pipelines.universal/Runtime/UniversalRenderPipeline.cs:473) UnityEngine.Rendering.RenderPipeline.InternalRender (UnityEngine.Rendering.ScriptableRenderContext context, System.Collections.Generic.List1[T] cameras) (at :0)
UnityEngine.Rendering.RenderPipelineManager.DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset pipelineAsset, System.IntPtr loopPtr, UnityEngine.Object renderRequest, Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle safety) (at :0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

What am I supposed to do to fix that warning?

Thanks!

Also tried the “Render Requests” workflow, getting same issue

https://docs.unity3d.com/Packages/com.unity.render-pipelines.core@17.0/manual/User-Render-Requests.html

tex2d needs volumeDepth=1
what does the assert say exactly?
what exact Unity (patch) version are you using?

Hi,

yes, I actually set the volumeDepth to 1, was just trying things out.
the line that the asset refers in my code is just the function call where I to my things, but it happens simply as soon as I assign a temporary render target (with depthStencilFormat set) to a camera’s output.

basically that:

void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
...
RenderingUtils.ReAllocateHandleIfNeeded(ref _CaptureHandle, texDesc, FilterMode.Bilinear, name: "Capture");
_DynamicEffectsCamera.targetTexture = _CaptureHandle;
...
}

Setting the temp render texture on the camera’s output without setting the depthStencilFormat works but create a warning every frame.

I’m using Unity 6.0.29

Thanks!

So… still have not figured this one out.

Basically I’ve got my render texture descriptor that looks like this:

RenderTextureDescriptor CreateRTDescriptor(bool depth = false)
{
	RenderTextureDescriptor texDesc = new RenderTextureDescriptor();

	texDesc.width = 1024;
	texDesc.height = 1024;
	texDesc.colorFormat = RenderTextureFormat.ARGBHalf;
	texDesc.dimension = TextureDimension.Tex2D;
	texDesc.autoGenerateMips = false;
	texDesc.depthBufferBits = 0;
	texDesc.msaaSamples = 1;
	texDesc.volumeDepth = 1;

	if (depth)
	{
		texDesc.depthStencilFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.D16_UNorm;
		texDesc.depthBufferBits = 16;
	}

	return texDesc;

}

Then trying to assign a temporary render texture to a camera…

void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
	CommandBuffer cmd = CommandBufferPool.Get();
  ...

	// Error ===========================
	RenderingUtils.ReAllocateHandleIfNeeded(ref _CaptureHandle, CreateRTDescriptor(true), FilterMode.Bilinear, name: "Capture");
	_DynamicEffectsCamera.targetTexture = _CaptureHandle;

  ...

	context.ExecuteCommandBuffer(cmd);
	CommandBufferPool.Release(cmd);
}

if I use CreateRTDescriptor(true) it creates the assert mentioned above and nothing works.
if I use CreateRTDescriptor(false) it creates a render texture with no depth. No assert and it works like intended, but I get the warning about the render texture assigned to a camera must have a depth buffer.

Hey, i dunno if you’re still having that issue but just wanted to drop in here and share what worked for me (i got this when using SubmitRenderRequest).

Took me a fewweek to fix this stupid thing so don’t mind the frustration…
From what i see there are two things that i think are worth mentioning/knowing and led me to the solution :

1- ill be blunt here : for what it’s supposed to be , RenderTextureDescriptor is one of the worst “descriptor” structs i’ve ever seen , the properties are not default get/set fields , for example here’s the content of colorFormat :

Implementation of colorFormat
    public RenderTextureFormat colorFormat
    {
        get
        {
            if (graphicsFormat != 0)
            {
                return GraphicsFormatUtility.GetRenderTextureFormat(graphicsFormat);
            }

            return (shadowSamplingMode == ShadowSamplingMode.None) ? RenderTextureFormat.Depth : RenderTextureFormat.Shadowmap;
        }
        set
        {
            shadowSamplingMode = RenderTexture.GetShadowSamplingModeForFormat(value);
            GraphicsFormat format = GraphicsFormatUtility.GetGraphicsFormat(value, sRGB);
            graphicsFormat = SystemInfo.GetCompatibleFormat(format, GraphicsFormatUsage.Render);
            depthStencilFormat = RenderTexture.GetDepthStencilFormatLegacy(depthBufferBits, shadowSamplingMode);
        }
    }

here’s depthBufferBits

Implementation of depthBufferBits
    public int depthBufferBits
    {
        get
        {
            return GraphicsFormatUtility.GetDepthBits(depthStencilFormat);
        }
        set
        {
            depthStencilFormat = RenderTexture.GetDepthStencilFormatLegacy(value, shadowSamplingMode);
        }
    }

Do you see the issue ? setting these properties can “override” whatever property you previously set so be careful and just use a constructor (this specific one below) directly to avoid unnecessary headache

public RenderTextureDescriptor(int width, int height, GraphicsFormat colorFormat, GraphicsFormatdepthStencilFormat, int mipCount)

2- SRP still has a lot of sloppy features (3 billion ways to blit , to Allocate textures , to record into command buffers …) , each one getting reworked and deprecated by each update …
With that said … Since the docs recommend the use of RTHandles to alloc/release texture that’s what did, but what go rid of the warning was using the good ol’ RenderTexture constructor to create the texture and THAT did it for me.

So to summarize here’s how i create the texture i used for SubmitRenderRequest

                RenderTextureDescriptor descriptor = new RenderTextureDescriptor(w, h)
                {
                    graphicsFormat = GraphicsFormat.R8G8B8A8_UNorm,
                    depthStencilFormat = GraphicsFormat.D24_UNorm_S8_UInt, // This will ACTUALLY add the depth to the texture get rid of the warning now
                    msaaSamples = 1,
                    sRGB = true,
                    useMipMap = false
                };

                RenderTexture rt = new RenderTexture(descriptor);
                rt.Create();

                /// DO the SubmitRenderRequest

                rt.Release();

Hope this helps any future seekers.

Thank you so much for sharing your findings, some of these info are quite valuable.

I’m now doing something similar that you with a regular render texture to use for the camera target, but I keep using the RTHandle for the rest of the blits as it is better in memory and only the camera target seems to cause issue with the RTHandle for my case.

It’s a mess indeed. The problem is mostly these “magic” properties.

The problem is that in the early days, Unity did a lot of magic behind the scenes to try to simplify things. The RenderTextureFormat sets the color format, depthstencil format and shadow sampling mode. Luckley, you can actually inspect this in C# now.

We have been converging towards a more explict API using GraphicsFormat, with which you have more explicit control. The constructor you mention uses these explict low level (non magic) properties. You can also set them directly.

That’s a good approach.

Another magic bit in core Unity is the allocation of up to two GPU resources in a RenderTexture, color and/or depth stencil. That makes sense to a certain degree but also complicates things and can lead to user errors.

In Unity 6, as part of the adoption of RenderGraph, we are converging towards using TextureDesc that as only a single format since it describes a single resource. It still has color and depth properties to easily set the single format, for backwards compatibility, which is unfortunate but needed. Some thoughts on that here.

In practice, RTHandles were almost exclusively used to describe a single resource so we settled on adopting that convention. It was already inforced to a certain degree in the code. The only exception is indeed importing a RenderTexture, that by convention can have these two resources.

Thanks for sharing !

I know that me saying this here might be a bit of “screaming into the void” that wont make a difference but ill just say it hoping that it joins other voices that share my view :
“Please don’t be afraid of deprecating old stuff and hard-cutting old parts of the graphics ecosystem”

I understand that unity wants to always have an abstraction layer between the user and the underlying tech, but i think (unlike scripting , animation , editor tools , etc …) graphics is a place that needs to be as close to the metal as possible , and with things as they are now and the introduction of RG i think cutting away with the old would be a great step, this will help everyone envolved (the people making their own pipelines , the asset creators/maintainers , the users by proxy , and propably also the unity team).

I understand the need for a “transition phase” where things go from “supported-unrecommended-deprecated-obselete” for compatibity purposes , but was wondering if deleting the redundant things and unifying to a flat and clean API is ever in the plans ? -as opposed to adding more workarounds and utils classes and helper (see : blitting and textures for example)-

Fully agree. This ofc needs to be done with great care for our users and ecosystem, and on a reasonable timeline for everyone to adapt. With the URP RenderGraph adoption, which is essentially a new render pipeline, we set out to remove the old URP (Compatibility Mode) as soon as possible. You can read more on that and the complexity of balancing all those requirements here . We have now started to add a compiler define to strip out all that old code. We’ll share more on that soon.

The docs say to pass TextureDesc to ReAllocateHandleIfNeeded - however - on 6.3, the function only accepts RenderTextureDescriptor - and is resulting in quite a bit of frustration ( im getting error spam also, trying to use a shared target to be set as targets in 3 passes )

What patch version are you on? There should be a TextureDesc overload in the latest 6.3.x.

Hello AljoshaD !

On patch 6000.0.64f1, ReAllocateHandleIfNeeded only accept RenderTextureDescriptor.

The example shown in this link doesn’t compile due to this error.

I tried to replace the TextureDesc by this RenderTextureDescriptor (which I think is equivalent?):

RenderTextureDescriptor textureDesc = new RenderTextureDescriptor()
{
    height = 256,
    width = 256,
    graphicsFormat = GraphicsFormat.R8G8B8A8_UNorm,
    depthStencilFormat = GraphicsFormat.D24_UNorm_S8_UInt,
    useMipMap = false
};

But it give this assertion error and then I get spam by an exception :confused:

Assertion

AssertionException: Assertion failure. Value was False
Expected: True
UnityEngine.Assertions.Assert.Fail (System.String message, System.String userMessage) (at <03bc89244eae41faa3400ee906fec7bf>:0)
UnityEngine.Assertions.Assert.IsTrue (System.Boolean condition, System.String message) (at <03bc89244eae41faa3400ee906fec7bf>:0)
UnityEngine.Assertions.Assert.IsTrue (System.Boolean condition) (at <03bc89244eae41faa3400ee906fec7bf>:0)
UnityEngine.Rendering.Universal.RenderingUtils.ReAllocateHandleIfNeeded (UnityEngine.Rendering.RTHandle& handle, UnityEngine.RenderTextureDescriptor& descriptor, UnityEngine.FilterMode filterMode, UnityEngine.TextureWrapMode wrapMode, System.Int32 anisoLevel, System.Single mipMapBias, System.String name) (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/RenderingUtils.cs:834)
RandomTriangles.Create () (at Assets/Content/Scripts/Graphics/Landscape/S_RandomTriangles.cs:84)
UnityEngine.Rendering.Universal.ScriptableRenderer..ctor (UnityEngine.Rendering.Universal.ScriptableRendererData data) (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/ScriptableRenderer.cs:711)
UnityEngine.Rendering.Universal.UniversalRenderer..ctor (UnityEngine.Rendering.Universal.UniversalRendererData data) (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/UniversalRenderer.cs:193)
UnityEngine.Rendering.Universal.UniversalRendererData.Create () (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/UniversalRendererData.cs:159)
UnityEngine.Rendering.Universal.ScriptableRendererData.InternalCreateRenderer () (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/ScriptableRendererData.cs:68)
UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.CreateRenderers () (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/Data/UniversalRenderPipelineAsset.cs:847)
UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.CreatePipeline () (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/Data/UniversalRenderPipelineAsset.cs:794)
UnityEngine.Rendering.RenderPipelineAsset.InternalCreatePipeline () (at <03bc89244eae41faa3400ee906fec7bf>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

Exception

Exception: Blitter is already initialized. Please only initialize the blitter once or you will leak engine resources. If you need to re-initialize the blitter with different shaders destroy & recreate it.
UnityEngine.Rendering.Blitter.Initialize (UnityEngine.Shader blitPS, UnityEngine.Shader blitColorAndDepthPS) (at ./Library/PackageCache/com.unity.render-pipelines.core@e0ee7b7230ea/Runtime/Utilities/Blitter.cs:96)
UnityEngine.Rendering.Universal.UniversalRenderPipeline..ctor (UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset asset) (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/UniversalRenderPipeline.cs:216)
UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.CreatePipeline () (at ./Library/PackageCache/com.unity.render-pipelines.universal@26412651eee9/Runtime/Data/UniversalRenderPipelineAsset.cs:793)
UnityEngine.Rendering.RenderPipelineAsset.InternalCreatePipeline () (at <03bc89244eae41faa3400ee906fec7bf>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

Tested on a brand new project. Any tips to share ? Meanwhile, I will try to use the old RenderTexture constructor as PixelEyesDev said.

ah looks like the docs were backported to 6.0 by mistake. While the ReAllocateHandleIfNeeded overload for TextureDesc is only available from 6.2. You can notify the doc team by giving feedback below the page.

RenderTextureDescriptor is similar to TextureDesc indeed. However, we are trying to get rid of it for a few reasons. The properties are more expense to call, and its error prone due to having two resources (color and depth) with each their own format.

In a RenderGraph native world, using TextureDesc, a TextureHandle only represents a single resource, color OR depth. The TextureDesc only has a single format (although the properties are still there for backward compatibility). Most RTHandle APIs assume only a single resource as well. If you set both formats, it will try to create two resources under the hood and some APIs fail/assert on that.

Thank you for the explanation! I notified the doc team :slight_smile:

I tested on 6000.3.1f1, the overload does work !

I am on 6.3.0b5 atm. ( i am unable to get reallocatetextureifneeded to EVER work on this version of unity and I am constantly being spammed with Current Render Graph Resource Registry is not set errors despite the creation not throwing an exception - and importing the texture in my pass.

I am also trying this with a shared RTHandle - but cannot find a solution to my ResourceRegistry errors.