Any render graph code examples w/ com.unity.render-pipelines.core?

I am hoping someone can provide a git repo or external resource that provides working examples of utilizing the com.unity.render-pipelines.core package, in particular utilizing the experimental render graph system.

I've read through the docs
https://docs.unity3d.com/Packages/com.unity.render-pipelines.core@11.0/manual/index.html
and some of
Unity/Hub/Editor/2021.1.5f1/Editor/Data/Documentation/en/Manual/Graphics.html
and browsed code over at
https://github.com/Unity-Technologies/Graphics

I'm trying to get some very barebone use cases going like rendering trig waves or generating heightfields. I've chosen to ignore the URP and HDRP pipelines for now because I want to get a lower level understanding and try and tap into some of the new packages.

At some point I want to also utilize the dots + ecs stack and get my own pipe for querying entities and getting them rendered each frame. This is my first dive into graphics pipelines like this but have read through the first dozen of chapters in Real-Time Rendering and I am ready to get my hands dirty.

In particular, if someone could provide an example of how to take a single DOTS entity and get it rendered utilizing srp render graph system I would highly appreciate it.

:smile:

Bump.

Here is what I have.

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;

public class HlRenderPipeline : RenderPipeline
{
    RenderGraph m_RenderGraph;
    int m_frameIndex = 0;
    Material m_defaultMaterial;

    public HlRenderPipeline(Material defaultMaterial)
    {
        m_RenderGraph = new RenderGraph("HlRenderGraph");
        m_defaultMaterial = defaultMaterial;
    }

    // todo how to when & where to call this?
    public void CleanupRenderGraph()
    {
        m_RenderGraph.Cleanup();
        m_RenderGraph = null;
    }

    class MyRenderPassData
    {
        public float Parameter;
        public Material Material;
        public TextureHandle InputTexture;
        public TextureHandle OutputTexture;
    }

    delegate void RenderFunc<MyRenderPassData>(MyRenderPassData data, RenderGraphContext renderGraphContext) where MyRenderPassData : class, new();


    protected override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
    {
        var commandBuffer = new CommandBuffer();
        var renderGraphParams = new RenderGraphParameters()
        {
            scriptableRenderContext = renderContext,
            commandBuffer = commandBuffer,
            currentFrameIndex = m_frameIndex
        };

        m_RenderGraph.Begin(renderGraphParams);

        using (var builder = m_RenderGraph.AddRenderPass<MyRenderPassData>("My Render Pass", out var passData))
        {
            passData.Parameter = 2.5f;
            passData.Material = m_defaultMaterial;
            passData.InputTexture = builder.ReadTexture(passData.InputTexture);

            var outputTexture = m_RenderGraph.CreateTexture(
                new TextureDesc(Vector2.one)
                {
                    colorFormat = GraphicsFormat.R8G8B8A8_UNorm,
                    clearBuffer = true,
                    clearColor = Color.grey,
                    name = "MyFirstOutput"
                }
            );
            passData.OutputTexture = builder.WriteTexture(outputTexture);
            builder.SetRenderFunc((MyRenderPassData data, RenderGraphContext ctx) =>
            {
                // Render Target is already set via the use of UseColorBuffer above.
                // If builder.WriteTexture was used, you'd need to do something like that:
                // CoreUtils.SetRenderTarget(ctx.cmd, data.output);

                // Setup material for rendering
                var materialPropertyBlock = ctx.renderGraphPool.GetTempMaterialPropertyBlock();
                materialPropertyBlock.SetTexture("_MainTexture", data.InputTexture);
                materialPropertyBlock.SetFloat("_FloatParam", data.Parameter);
                CoreUtils.DrawFullScreen(ctx.cmd, data.Material, materialPropertyBlock);
            });
        }

        m_RenderGraph.Execute();
        m_frameIndex++;
    }

}

getting errors atm. Working through it. Definitely still learning fundamentals on this thing.

error line 52: "passData.InputTexture = builder.ReadTexture(passData.InputTexture);"
error: "
ArgumentException: Trying to use an invalid resource (pass My Render Pass).
UnityEngine.Experimental.Rendering.RenderGraphModule.RenderGraphBuilder.CheckResource (UnityEngine.Experimental.Rendering.RenderGraphModule.ResourceHandle& res) (at Graphics/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs:272)
UnityEngine.Experimental.Rendering.RenderGraphModule.RenderGraphBuilder.ReadTexture (UnityEngine.Experimental.Rendering.RenderGraphModule.TextureHandle& input) (at Graphics/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilder.cs:54)
HlRenderPipeline.Render (UnityEngine.Rendering.ScriptableRenderContext renderContext, UnityEngine.Camera[ ] cameras) (at Assets/Graphics/HlRenderPipeline.cs:52)
UnityEngine.Rendering.RenderPipeline.Render (UnityEngine.Rendering.ScriptableRenderContext context, System.Collections.Generic.List1[T] cameras) (at <6a104889781c465ca00c12d0953583e2>:0)
UnityEngine.Rendering.RenderPipeline.InternalRender (UnityEngine.Rendering.ScriptableRenderContext context, System.Collections.Generic.List
1[T] cameras) (at <6a104889781c465ca00c12d0953583e2>:0)
UnityEngine.Rendering.RenderPipelineManager.DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset pipe, System.IntPtr loopPtr, System.Collections.Generic.List`1[T] renderRequests, Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle safety) (at <6a104889781c465ca00c12d0953583e2>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)
"

Well of course the HDRP uses it! So yeah just going to be looking at that for examples as they are many. Couldn't find anyone else in these forums who has tried it yet interesting enough. I wonder if anyone is out there in the wild using it and just not around to answer my newbie questions. Once I get a basic hello cube working I'll post the complete code.

Here is where I'm at, still no luck. Just trying to get the screen to clear to a color atm, then after that to execute an actual shader program.

heellllppp

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;

public class HlRenderPipeline : RenderPipeline
{
    RenderGraph m_RenderGraph;
    int m_frameIndex = 0;
    Material m_defaultMaterial;
    CommandBuffer m_commandBuffer;

    public HlRenderPipeline(Material defaultMaterial)
    {
        m_RenderGraph = new RenderGraph("HlRenderGraph");
        m_defaultMaterial = defaultMaterial;
        m_commandBuffer = new CommandBuffer();
    }

    // todo how to when & where to call this?
    public void CleanupRenderGraph()
    {
        m_RenderGraph.Cleanup();
        m_RenderGraph = null;
    }

    class MyRenderPassData
    {
        public TextureHandle Target;
        public Rect Viewport;
    }

    protected override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
    {
        var renderGraphParams = new RenderGraphParameters()
        {
            scriptableRenderContext = renderContext,
            commandBuffer = m_commandBuffer,
            currentFrameIndex = m_frameIndex
        };

        m_RenderGraph.Begin(renderGraphParams);

        var outputTexture = m_RenderGraph.CreateTexture(
            new TextureDesc(Vector2.one)
            {
                colorFormat = GraphicsFormat.R8G8B8A8_UNorm,
                clearBuffer = true,
                clearColor = Color.red,
                name = "MyFirstOutput"
            }
        );

        var camera = cameras[0];

        using (var builder = m_RenderGraph.AddRenderPass<MyRenderPassData>("My Render Pass", out var passData))
        {
            passData.Target = builder.WriteTexture(outputTexture);
            passData.Viewport = camera.pixelRect;

            builder.SetRenderFunc((MyRenderPassData data, RenderGraphContext ctx) =>
            {
                ctx.cmd.SetRenderTarget(data.Target);
                ctx.cmd.SetViewport(data.Viewport);
            });

        }

        m_RenderGraph.Execute();
        m_frameIndex++;

        renderContext.ExecuteCommandBuffer(m_commandBuffer);
        m_commandBuffer.Clear();

        renderContext.Submit();
    }
}

Hey, I have a simple RenderGraph example here maybe this will help?
https://github.com/cinight/CustomSRP/tree/master/Assets/SRP0802_RenderGraph

5 Likes

In so many words; yes.

:smile:

Thank you! Diving in now.

I think my head just exploded, thank you again this is exactly what I was looking for.

Now to actually do something with it...

@ where is ming and what have you done with this example? is there a newer link that can be referenced?

@oldhighscore_1 I've updated the project to 2022.1.0b1 https://github.com/cinight/CustomSRP/tree/2022.1

4 Likes

Thank you very much! Searched something like this for two hours.

This is a great tutorial on how to write a custom SRP using RenderGraph.

There is also a lot of info in the thread on the URP RenderGraph adoption.