Search Unity

Question How to extend the SRP Rendering Debugger?

Discussion in 'Editor & General Support' started by fleity, Aug 11, 2022.

  1. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    345
    hey everyone,

    I have the need for a texture validation tool which I can implement as a material override. I would like to integrate it with the Rendering Debugger in a new panel. I can not find any information on the the entire internet on how to do it though.

    upload_2022-8-11_10-43-28.png

    kind regards, thanks for your help.
     
  2. arttu_p

    arttu_p

    Unity Technologies

    Joined:
    Jan 15, 2021
    Posts:
    24
    Hi! Embedding custom debug options into Rendering Debugger is not a officially supported use case right now. However the APIs to do this should be public for the most part, so you are welcome to try and let us know if there are any pain points.

    Something like this should work:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. [ExecuteInEditMode]
    7. public class CustomDebugPanel : MonoBehaviour
    8. {
    9.     const string k_PanelName = "MyCustomPanel";
    10.  
    11.     public bool myBoolean = true;
    12.  
    13.     void OnEnable()
    14.     {
    15.         var panel = DebugManager.instance.GetPanel(k_PanelName, true);
    16.  
    17.         var widgetList = new List<DebugUI.Widget>();
    18.         widgetList.AddRange(new DebugUI.Widget[]
    19.         {
    20.             new DebugUI.BoolField
    21.             {
    22.                 displayName = "My checkbox",
    23.                 tooltip = "Custom tooltip",
    24.                 getter = () => myBoolean,
    25.                 setter = value => myBoolean = value
    26.             },
    27.         });
    28.  
    29.         panel.children.Add(widgetList.ToArray());
    30.     }
    31.  
    32.     void OnDisable()
    33.     {
    34.         DebugManager.instance.RemovePanel(k_PanelName);
    35.     }
    36. }
    37.  
    Other than that, you can also look at URP/HDRP package code and modify that directly, if you are comfortable editing package source code.
     
    LooperVFX, sabojako and fleity like this.
  3. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    345
    That is sooo much easier than what I copied together from the existing panels, thank you so much.
    I tried to avoid importing the entire URP package to the project and hoped I could just create another instance of a class panel which would be appended to the window just by inheriting from .But this solution is much nicer (and works at all).

    How can this NOT be an expected use case though :D? Can I please file this as a useful feature? Having the option to add custom validation tools to a Debugging tool like this seems like a no brainer for any at least medium scale production, because every production probably has needs to check one or another feature in isolation and having a clean way to add basically a way to render everything with a certain shader goes a long way for this.
    My very specific case is: I want to check if the resolution of the textures used is in a healthy range by displaying the used mip map level (based on an old post about how this was implemented for the built-in renderer on Aras's blog: https://aras-p.info/blog/2011/05/03/a-way-to-visualize-mip-levels/) because this feature dissappeared in SRP as far as I can see.

    I would argue any tool that can theoretically be extended will be customized by someone.
    I will report back as soon as I am finished, thanks again.
     
  4. arttu_p

    arttu_p

    Unity Technologies

    Joined:
    Jan 15, 2021
    Posts:
    24
    Happy to hear it was useful. I 100% agree with you, customizing debug modes is definitely something that we want to support (hence the public API), it's more that there's a lot of work to do so we haven't been able to prioritize verifying these workflows yet. I'll pass on the feedback that this is useful to you, hopefully we can have this more officially supported with docs & examples down the line.

    The mipmap debugmode that you're describing is not supported right now because of some technical issues in making that work for shadergraph shaders. If you're not using SG and/or are able to make your SG shaders output the necessary info in this debug mode, you should be able to make such a mode yourself.
     
    LooperVFX likes this.
  5. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    345
    hey @arttu_p
    so it took a bit for the feature to be voted into a sprint on my side as well :D
    Yes my shader is not using SG, but I don't see why it should not work with SG in the end all it is doing is ddx, ddy of the uvs.


    So major pain points..
    I don't really know where to start to be honest. Maybe first of all the way of getting additional widgets and panels into the rendering debugger works great and from there one can pretty much attach any kind of functionality which is great.
    However I had major troubles hooking into the rendering pipeline from there. Especially since I wanted to organize everything as closely as possible the same way that it is done in URP.
    Ideally I would have been able to skip the regular rendering of objects and gain access to the renderers Setup function somehow too but that did not work at all.

    I could have recreated the entire functionality inside of URP\Runtime\Debug with different classes which would have fit my needs but in the end it all fails because of two lines that I could not easily change.
    In UniversalRenderer.cs when Setup is called on the DebugHandler I would need my own DebugHandler class, either by replacing the reference or calling it on another CustomDebugHandler class.
    However getting that reference is not easy because it has only an internal getter in ScriptableRenderer.cs and the instance is created in the contructor of that class. I really didn't want to modify ScriptableRenderer or UniversalRenderer just yet and rather have my solution a bit more modularly deployable.

    In the end I recreated a lot more of the structure of what I found in URP\Runtime\Debug (CustomDebugHandler, DebugDisplaySettingsCustom classes etc.) in addition to my panel, which is pretty small now since all the work is handed off to the classes that URP uses for setting up it's UI too and I use DebugDisplaySettingsUI.RegisterDebug to get into the rendering debugger

    Code (CSharp):
    1. #if DEVELOPMENT_BUILD || UNITY_EDITOR
    2.  
    3.     /// <summary>
    4.     /// Class that
    5.     /// </summary>
    6.     public static class CustomDebugPanel
    7.     {
    8.         private static DebugDisplaySettingsUI settingsUI = new DebugDisplaySettingsUI();
    9.         private static bool isInitialized = false;
    10.  
    11. #if UNITY_EDITOR
    12.         [InitializeOnLoadMethod]
    13. #endif
    14.         [RuntimeInitializeOnLoadMethod]
    15.         static void OnLoad()
    16.         {
    17.             if (!isInitialized)
    18.             {
    19.                 isInitialized = true;
    20.                 DebugManager.instance.RemovePanel(DebugDisplaySettingsCustom.PANEL_NAME);
    21.                 settingsUI.RegisterDebug(CustomPipelineDebugDisplaySettings.Instance);
    22.             }
    23.         }
    24.     }
    25. #endif
    To get the actual rendering to work, instead of modifying the renderpipeline files I wrote a renderer feature which is just a specialized version of RenderObjects with some specific shaders and overwriteMode = Shader from 2022.2 (which we just decided to update to which is nice). I then configure and add / remove this rendererfeature based on the settings in the render debugger panel.
    This usually results in all objects being drawn twice without SRP batching (in the release notes it's mentioned this will be fixed though *fingerscrossed) which kind of sucks. So I also added a more hacky way to get around the base drawing loop by buffering the renderers layermasks and setting all of those to nothing while my DebugRenderFeature is active.

    Certainly was a bit more involved that I had hoped but it works. I probably could have made my life easier by skipping a bit of the settings structure I found in DebugDisplaySettings and rather used the panel directly to talk to some static class to manage the rendererFeature. And there probably is an easier way to get to this point in general.

    Ideally it would be nice if it was possible to write a single or small set of classes which are picked up by their type or by attaching to some public property to extend the panel with a few settings and the DebugHandler with a few instructions as well but the connectedness of those classes and the few not easily overwritable properties make this quite difficult.

    An example:
    in DebugHandler
    Code (CSharp):
    1. readonly UniversalRenderPipelineDebugDisplaySettings m_DebugDisplaySettings;
    UniversalRenderPipelineDebugDisplaySettings holds references to the different Settings classes (Lighting, Material, etc). It would be nice to be able to create another like those and have that referenced in UniversalRenderPipelineDebugDisplaySettings but instead the references are hardcoded there and in a bunch of places the other classes. I can not inherit from DebugHandler and overwrite this readonly property with a different type in which I set this up myself either.
    Long story short, getting to the scriptableRender context access which the DebugHandler has is really difficult without customizing the entire renderpipeline, would be nice if that was easier.

    My advice to someone who attempts this in the future... taking the example from arttu above and setting up an additional URP asset which has all the stuff you need and a specific RenderObjects Feature which you can modify through that Panel and then switchting to this URP Asset when a bool in the panel is active is probably the easiest, least invasive solution and requires the least amount of code.

    I noticed this made it into the urp 15 package documentation. nice!
    https://docs.unity3d.com/Packages/c...features/rendering-debugger-add-controls.html
     
    Last edited: Mar 17, 2023
  6. arttu_p

    arttu_p

    Unity Technologies

    Joined:
    Jan 15, 2021
    Posts:
    24
    H @fleity, thanks for the feedback!

    Glad to hear the widget part is at least working well :D as for the other stuff, I should clarify a bit what I meant in my earlier messages. The intent has been to allow users to have a way to inject custom options into the Rendering Debugger on the UI level (this is what my code sample above is doing). What you are attempting to do is integrate into the URP debug system on a deeper level, which I don't think we have planned to expose. This is why DebugHandler is internal, it's just an implementation detail for how URP implements its own debug modes. Doing what you describe and integrating directly into URP debug system is of course possible, but you'll need to modify package source to do it properly and I don't recommend it, other than as a last resort.

    Certainly was a bit more involved that I had hoped but it works. I probably could have made my life easier by skipping a bit of the settings structure I found in DebugDisplaySettings and rather used the panel directly to talk to some static class to manage the rendererFeature.

    This sounds good and simple. It keeps your code more isolated from URP internals and makes it less likely that you'll encounter problems when updating to newer versions of Unity. Also depending on what your debug modes do, this approach would make your debug panels easily portable between URP and HDRP.
     
    LooperVFX and fleity like this.