Getting NullReferenceException When Building to Android and Using Immediate Mode Drawing

Avatar
  • updated
  • Under Review

Whenever I load a scene where I am doing Immediate Mode Drawing after building to Android, using

using (Draw.Command(cam))

I get the following runtime error (I have Compatibility Mode disabled.):

2024/12/11 21:31:22.985 24901 25004 Error Unity NullReferenceException: Object reference not set to an instance of an object.
2024/12/11 21:31:22.985 24901 25004 Error Unity at UnityEngine.Rendering.RenderGraphModule.RenderGraphResourceRegistry.GetRenderTargetInfo (UnityEngine.Rendering.RenderGraphModule.ResourceHandle& res, UnityEngine.Rendering.RenderGraphModule.RenderTargetInfo& outInfo) [0x00000] in <00000000000000000000000000000000>:0
2024/12/11 21:31:22.985 24901 25004 Error Unity at UnityEngine.Rendering.RenderGraphModule.RenderGraphBuilders.CheckUseFragment (UnityEngine.Rendering.RenderGraphModule.TextureHandle tex, System.Boolean isDepth) [0x00000] in <00000000000000000000000000000000>:0
2024/12/11 21:31:22.985 24901 25004 Error Unity at UnityEngine.Rendering.RenderGraphModule.RenderGraphBuilders.SetRenderAttachment (UnityEngine.Rendering.RenderGraphModule.TextureHandle tex, System.Int32 index, UnityEngine.Rendering.RenderGraphModule.AccessFlags flags, System.Int32 mipLevel, System.Int32 depthSlice) [0x00000] in <00000000000000000000000000000000>:0
2024/12/11 21:31:22.985 24901 25004 Error Unity at Shapes.ShapesRenderPass.RecordRenderGraph (UnityEngine.Rendering.RenderGraphModule.RenderGraph renderGraph, UnityEngine.Renderi


If I disable the script that is using immediate mode drawing, the errors disappear.

Reporting a bug? please specify Unity version:
6000.0.30
Reporting a bug? please specify Shapes version:
4.5.0
Reporting a bug? please specify Render Pipeline:
URP
Avatar
Justin Wasilenko
Quote from Freya Holmér

sorry for taking so long to get to this, I'm looking into it at the moment! thanks a ton for sharing your solutions it helps get fixes through much faster

Thanks Freya. Let me know if you need help testing. I really need this working on the Meta Quest platform.

Avatar
Freya Holmér creator
  • Under Review

sorry for taking so long to get to this, I'm looking into it at the moment! thanks a ton for sharing your solutions it helps get fixes through much faster

Avatar
Justin Wasilenko
Quote from Hendrik Schulte

I don't know how to help you with that problem. You might just have different URP / Unity versions or some different configuration. I tested this on 6.3.3f1 and URP 17.3.0 and Unity OpenXR Meta 2.2.1.

Just want to add that the fix only works for Android Builds on the Quest and doesn't for editor / webgl. This is what I ended up with in ShapesRenderPass.cs

       public override void RecordRenderGraph( RenderGraph renderGraph, ContextContainer frameData ) {
var resourceData = frameData.Get<UniversalResourceData>();
if (resourceData == null) {
Debug.LogWarning("ShapesRenderPass: resourceData is not valid, skipping render pass.");
return;
}
#if !UNITY_EDITOR && UNITY_ANDROID
var target = resourceData.backBufferColor;
#else
var target = resourceData.cameraColor;
#endif
if (!target.IsValid()) {
Debug.LogWarning("ShapesRenderPass: target is not valid, skipping render pass.");
return;
}
using var builder = renderGraph.AddRasterRenderPass<PassData>("Render Shapes", out var data);
data.drawCommand = drawCommand;
builder.AllowPassCulling(false);
builder.SetRenderAttachment(target, 0, AccessFlags.Write);
builder.SetRenderFunc((PassData dataParam, RasterGraphContext context)
=> dataParam.drawCommand.AppendToBuffer(context.cmd));
}

Hi Hendrik, No luck for me on my end. Running Unity 6.2.9. That got rid of the error message, but immediate drawing of Shapes no longer worked correctly + still the frame rate issue in my build.

Hopefully @Freya will take a look at this soon and make an update. Maybe next week I'll try on Unity 6.3 and see if that changes anything.

Avatar
Hendrik Schulte

I don't know how to help you with that problem. You might just have different URP / Unity versions or some different configuration. I tested this on 6.3.3f1 and URP 17.3.0 and Unity OpenXR Meta 2.2.1.

Just want to add that the fix only works for Android Builds on the Quest and doesn't for editor / webgl. This is what I ended up with in ShapesRenderPass.cs

       public override void RecordRenderGraph( RenderGraph renderGraph, ContextContainer frameData ) {
var resourceData = frameData.Get<UniversalResourceData>();
if (resourceData == null) {
Debug.LogWarning("ShapesRenderPass: resourceData is not valid, skipping render pass.");
return;
}
#if !UNITY_EDITOR && UNITY_ANDROID
var target = resourceData.backBufferColor;
#else
var target = resourceData.cameraColor;
#endif
if (!target.IsValid()) {
Debug.LogWarning("ShapesRenderPass: target is not valid, skipping render pass.");
return;
}
using var builder = renderGraph.AddRasterRenderPass<PassData>("Render Shapes", out var data);
data.drawCommand = drawCommand;
builder.AllowPassCulling(false);
builder.SetRenderAttachment(target, 0, AccessFlags.Write);
builder.SetRenderFunc((PassData dataParam, RasterGraphContext context)
=> dataParam.drawCommand.AppendToBuffer(context.cmd));
}
Avatar
Justin Wasilenko

That didn't work for me. By switching to 'resourceData.backBufferColor' I get this error:

[Exception] InvalidOperationException: Trying to use a texture (_MainLightShadowmapTexture) that was already released or not yet created. Make sure you declare it for reading in your pass or you don't read it before it's been written to at least once.
RenderGraphResourceRegistry.CheckTextureResource() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/RenderGraphResourceRegistry.cs:176
 174:  {
 175:      if (texResource.graphicsResource == null && !texResource.imported)
--> 176:          throw new InvalidOperationException($"Trying to use a texture ({texResource.GetName()}) that was already released or not yet created. Make sure you declare it for reading in your pass or you don't read it before it's been written to at least once.");
 177:  }

RenderGraphResourceRegistry.GetTexture() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/RenderGraphResourceRegistry.cs:185
 184:      var texResource = GetTextureResource(handle.handle);
--> 185:      CheckTextureResource(texResource);
 186:      return texResource.graphicsResource;
 187:  }

TextureHandle.op_Implicit() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/RenderGraphResourceTexture.cs:89
  87:  /// <param name="texture">Input TextureHandle.
  88:  /// <returns>Resource as a RenderTargetIdentifier.</returns>
-->  89:  public static implicit operator RenderTargetIdentifier(TextureHandle texture) => texture.IsValid() ? RenderGraphResourceRegistry.current.GetTexture(texture) : default(RenderTargetIdentifier);
  91:  /// <summary>

NativePassCompiler.ExecuteGraphNode() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/Compiler/NativePassCompiler.cs:1412
1410:      foreach (var tex in pass.setGlobalsList)
1411:      {
-->1412:          rgContext.cmd.SetGlobalTexture(tex.Item2, tex.Item1);
1413:      }
1414:  }

NativePassCompiler.ExecuteGraph() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/Compiler/NativePassCompiler.cs:1511
1509:  #endif
-->1511:                  ExecuteGraphNode(ref rgContext, resources, passes[pass.passId]);
1513:                  // If we set any uavs clear them again so they are local to the pass

RenderGraph.ExecuteNativeRenderGraph() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/RenderGraph.Compiler.cs:42
  40:  using (new ProfilingScope(m_RenderGraphContext.cmd, ProfilingSampler.Get(RenderGraphProfileId.ExecuteRenderGraph)))
  41:  {
-->  42:      nativeCompiler.ExecuteGraph(m_RenderGraphContext, m_Resources, m_RenderPasses);
  44:      if (m_RenderGraphContext.contextlessTesting == false)

RenderGraph.Execute() at ./Library/PackageCache/com.unity.render-pipelines.core@04755ad51d99/Runtime/RenderGraph/RenderGraph.cs:1575
1573:  #endif
1574:                      if (nativeRenderPassesEnabled)
-->1575:                          ExecuteNativeRenderGraph();
1576:                      else
1577:                          ExecuteRenderGraph();

GUIUtility.ProcessEvent()
</summary>
Avatar
Hendrik Schulte

I managed to fix it without forcing the intermediate texture. 


In ShapesRenderPass.RecordRenderGraph, use resourceData.backBufferColor instead of resourceData.cameraColor

Avatar
Hendrik Schulte

Hey Justin,
good catch! That performance drop is unacceptable of course.
To elaborate a bit further: 

I found out that in ShapesRenderPass.RecordRenderGraph, resourceData.cameraColor is invalid when not ensuring that there is an intermediate texture which is causing the error in the first place. 

So if Shapes does not need the texture as you said, I tried removing the references to resourceData.cameraColor, but that does not work either with this error:

InvalidOperationException: Render Shapes: Using raster commands from a pass with no active render target is not allowed as it will use an undefined render target state. Please set up pass render targets using SetRenderAttachments.

I'll fiddle around a bit more

Avatar
Justin Wasilenko

Hi Hendrik,

I gave it a try and while it does allow Quest to turn off compatibility mode, it completely tanked my frame rate. 
Right now I have Shapes running with compatibility mode, rock solid 72 fps. 

Tried fix number 2, and frame rate is cut in half. Probably because it's forcing the intermediate texture which causes another Blit? But I don't think Shapes needs that Intermediate Texture to function correctly.

Avatar
Hendrik Schulte

I managed to fix the problem! 


It seems that in Android / Quest builds, Unity does not create an intermediate texture for Shapes to render to. Therefore, in ShapesRenderPass.csresourceData.cameraColor is null.

There are two ways to fix it:

  1. In the Universal Renderer asset, set Intermediate Texture to Always. This has the upside that you don't have to update the Shapes source, but "Using this option might have a significant performance impact on some platforms".
  2. In ShapesRenderFeature.cs, properly configure the inputs of the RenderPass, so that Unity can automatically create the intermediate textures for Shapes' RenderPasses:
public override void AddRenderPasses( ScriptableRenderer renderer, ref RenderingData renderingData ) { // on pre render, called once per render
Camera cam = renderingData.cameraData.camera;
if( DrawCommand.cBuffersRendering.TryGetValue( cam, out List<DrawCommand> cmds ) ) {
foreach( DrawCommand cmd in cmds )
{
var pass = ObjectPool<ShapesRenderPass>.Alloc();
pass.ConfigureInput(ScriptableRenderPassInput.Color);
    renderer.EnqueuePass( pass.Init( cmd ) );
}
}
}

The problem probably also applies to HDRP, but I did not test that.

Would be nice to see a fixed version of Shapes, soon.

Avatar
Hendrik Schulte

This is still a breaking issue for me in 6.2 where the app simply crashes at startup when compatibility mode is disabled. Unity will also remove the Compatibility mode in 6.4. So I want to draw some attention to this.

Avatar
hendrik schulte

I have the same problem as airoll described above on Quest 3 using Shapes 4.5.1 and Unity 6000.0.46f1. When enabling compatibility mode, it works.

Avatar
Justin Wasilenko

I keep trying to find out what has gone wrong with Shapes as it's necessary for my game. Today I was at least able to get an error from the adb logs on Quest:

AndroidPlayer "Oculus_Quest 3@ADB:2G0YC6LF6000D1:0" A non-multisampled texture being bound to a multisampled sampler. Disabling in order to avoid undefined behavior. Please enable the bindMS flag on the texture. UnityEngine.Rendering.Universal.UniversalRenderPipeline:RenderSingleCamera(ScriptableRenderContext, UniversalCameraData) UnityEngine.Rendering.Universal.UniversalRenderPipeline:RenderCameraStack(ScriptableRenderContext, Camera) UnityEngine.Rendering.Universal.UniversalRenderPipeline:Render(ScriptableRenderContext, List`1) UnityEngine.Rendering.RenderPipelineManager:DoRenderLoop_Internal(RenderPipelineAsset, IntPtr, Object) [./Runtime/Shaders/ShaderImpl/ShaderTextureProperty.cpp line 496775000]

This error repeats itself every frame.

Avatar
Justin Wasilenko

Also wanted to add, I had no problems on Unity 2022 and the previous version of Shapes with Immediate drawing on Quest.

Avatar
Justin Wasilenko

While I am not getting that error, I get this message instead:

12-12 16:22:26.214 5757 5879 W Unity : VULKAN: GENERAL WARNING: The following warning was triggered: VKDBGUTILWARN003. Please refer to the Adreno Game Developer Guide for more information: https://developer.qualcomm.com/sites/default/files/docs/adreno-gpu/snapdragon-game-toolkit/learn_guides.html
12-12 16:22:26.214 5757 5879 W Unity : Objects:
12-12 16:22:26.214 5757 5879 W Unity : #0: { name = ExecuteRenderGraph (C0:C/XR, DS:C/X), type = VK_OBJECT_TYPE_RENDER_PASS, handle = 0xb40000722220dd00 }
12-12 16:22:26.214 5757 5879 W Unity :


Same Unity, Shapes, and URP version as the above. Using Quest 3 and Vulkan.


In my case, adding some Shape game objects to the scene they render just fine. However if I override DrawShapes(Camera cam) for Immediate mode (which I use extensively in my project) nothing gets rendered at all, just a black screen, and the above Vulkan warning being spammed in ADB. Even just doing a simple override like this will cause the black screen and nothing being rendered:


public override void DrawShapes(Camera cam) { using (Draw.Command(cam)) { // Nothing here } }