Skip to content

Commit ead88bd

Browse files
UnityAljoshaEvergreen
authored andcommitted
update rendergraph samples to use the new helper functions
Update rendergraph samples to use the new helper functions to show users how to minimize writing boiler plate code. The samples are used as documentation to demonstrate how to best use RenderGraph. This PR does not change anything in URP or the product, it improves the learning materials.
1 parent 6b57d04 commit ead88bd

File tree

2 files changed

+77
-143
lines changed

2 files changed

+77
-143
lines changed

Packages/com.unity.render-pipelines.universal/Samples~/URPRenderGraphSamples/Blit/CopyRenderFeature.cs

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using UnityEngine;
22
using UnityEngine.Rendering;
33
using UnityEngine.Rendering.RenderGraphModule;
4+
using UnityEngine.Rendering.RenderGraphModule.Util;
45
using UnityEngine.Rendering.Universal;
56

67
// This example copies the active color texture to a new texture. This example is for API demonstrative purposes,
@@ -9,63 +10,45 @@ public class CopyRenderFeature : ScriptableRendererFeature
910
{
1011
class CopyRenderPass : ScriptableRenderPass
1112
{
12-
// This class stores the data needed by the pass, passed as parameter to the delegate function that executes the pass
13-
private class PassData
14-
{
15-
internal TextureHandle src;
16-
}
13+
string m_PassName = "Copy To or From Temp Texture";
1714

18-
// This static method is used to execute the pass and passed as the RenderFunc delegate to the RenderGraph render pass
19-
static void ExecutePass(PassData data, RasterGraphContext context)
15+
public CopyRenderPass()
2016
{
21-
Blitter.BlitTexture(context.cmd, data.src, new Vector4(1, 1, 0, 0), 0, false);
17+
//The pass will read the current color texture. That needs to be an intermediate texture. It's not supported to use the BackBuffer as input texture.
18+
//By setting this property, URP will automatically create an intermediate texture.
19+
//It's good practice to set it here and not from the RenderFeature. This way, the pass is selfcontaining and you can use it to directly enqueue the pass from a monobehaviour without a RenderFeature.
20+
requiresIntermediateTexture = true;
2221
}
2322

2423
// This is where the renderGraph handle can be accessed.
2524
// Each ScriptableRenderPass can use the RenderGraph handle to add multiple render passes to the render graph
2625
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
2726
{
28-
string passName = "Copy To Debug Texture";
29-
30-
// This simple pass copies the active color texture to a new texture. This sample is for API demonstrative purposes,
31-
// so the new texture is not used anywhere else in the frame, you can use the frame debugger to verify its contents.
32-
33-
// add a raster render pass to the render graph, specifying the name and the data type that will be passed to the ExecutePass function
34-
using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName, out var passData))
35-
{
36-
// UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures
37-
// The active color and depth textures are the main color and depth buffers that the camera renders into
38-
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
39-
40-
// Fill up the passData with the data needed by the pass
41-
42-
// Get the active color texture through the frame data, and set it as the source texture for the blit
43-
passData.src = resourceData.activeColorTexture;
27+
// UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures
28+
// The active color and depth textures are the main color and depth buffers that the camera renders into
29+
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
4430

45-
// The destination texture is created here,
46-
// the texture is created with the same dimensions as the active color texture, but with no depth buffer, being a copy of the color texture
47-
// we also disable MSAA as we don't need multisampled textures for this sample
31+
// The destination texture is created here,
32+
// the texture is created with the same dimensions as the active color texture
33+
var source = resourceData.activeColorTexture;
4834

49-
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
50-
RenderTextureDescriptor desc = cameraData.cameraTargetDescriptor;
51-
desc.msaaSamples = 1;
52-
desc.depthBufferBits = 0;
35+
var destinationDesc = renderGraph.GetTextureDesc(source);
36+
destinationDesc.name = $"CameraColor-{m_PassName}";
37+
destinationDesc.clearBuffer = false;
5338

54-
TextureHandle destination =
55-
UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "CopyTexture", false);
56-
57-
// We declare the src texture as an input dependency to this pass, via UseTexture()
58-
builder.UseTexture(passData.src);
59-
60-
// Setup as a render target via UseTextureFragment, which is the equivalent of using the old cmd.SetRenderTarget
61-
builder.SetRenderAttachment(destination, 0);
62-
63-
// We disable culling for this pass for the demonstrative purpose of this sample, as normally this pass would be culled,
64-
// since the destination texture is not used anywhere else
65-
builder.AllowPassCulling(false);
39+
TextureHandle destination = renderGraph.CreateTexture(destinationDesc);
40+
41+
if (RenderGraphUtils.CanAddCopyPassMSAA())
42+
{
43+
// This simple pass copies the active color texture to a new texture.
44+
renderGraph.AddCopyPass(resourceData.activeColorTexture, destination, passName: m_PassName);
6645

67-
// Assign the ExecutePass function to the render pass delegate, which will be called by the render graph when executing the pass
68-
builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePass(data, context));
46+
//Need to copy back otherwise the pass gets culled since the result of the previous copy is not read. This is just for demonstration purposes.
47+
renderGraph.AddCopyPass(destination, resourceData.activeColorTexture, passName: m_PassName);
48+
}
49+
else
50+
{
51+
Debug.Log("Can't add the copy pass due to MSAA");
6952
}
7053
}
7154
}

Packages/com.unity.render-pipelines.universal/Samples~/URPRenderGraphSamples/BlitWithMaterial/BlitAndSwapColorRendererFeature.cs

Lines changed: 49 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,118 +2,73 @@
22
using UnityEngine.Rendering.RenderGraphModule;
33
using UnityEngine.Rendering;
44
using UnityEngine.Rendering.Universal;
5+
using UnityEngine.Rendering.RenderGraphModule.Util;
6+
using UnityEngine.Experimental.Rendering;
7+
using static UnityEditor.ShaderData;
58

69
//This example blits the active CameraColor to a new texture. It shows how to do a blit with material, and how to use the ResourceData to avoid another blit back to the active color target.
710
//This example is for API demonstrative purposes.
811

9-
public class BlitAndSwapColorRendererFeature : ScriptableRendererFeature
10-
{
11-
12-
// This pass blits the whole screen for a given material to a temp texture, and swaps the UniversalResourceData.cameraColor to this temp texture.
13-
// Therefor, the next pass that references the cameraColor will reference this new temp texture as the cameraColor, saving us a blit.
14-
// Using the ResourceData, you can manage swapping of resources yourself and don't need a bespoke API like the SwapColorBuffer API that was specific for the cameraColor.
15-
// This allows you to write more decoupled passes without the added costs of avoidable copies/blits.
16-
class BlitAndSwapColorPass : ScriptableRenderPass
17-
{
18-
const string m_PassName = "BlitAndSwapColorPass";
19-
20-
// The data we want to transfer to the render function after recording.
21-
class PassData
22-
{
23-
// For the blit operation we will need the source and destination of the color attachments.
24-
public TextureHandle source;
25-
public TextureHandle destination;
26-
// We will also need a material to transform the color attachment when making a blit operation.
27-
public Material material;
28-
}
29-
30-
// Scale bias is used to blit from source to distination given a 2d scale in the x and y parameters
31-
// and an offset in the z and w parameters.
32-
static Vector4 scaleBias = new Vector4(1f, 1f, 0f, 0f);
33-
34-
// Material used in the blit operation.
35-
Material m_BlitMaterial;
36-
37-
// Function used to transfer the material from the renderer feature to the render pass.
38-
public void Setup(Material mat)
39-
{
40-
m_BlitMaterial = mat;
41-
}
42-
43-
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
44-
{
45-
var resourceData = frameData.Get<UniversalResourceData>();
46-
47-
//This should never happen since we set m_Pass.requiresIntermediateTexture = true;
48-
//Unless you set the render event to AfterRendering, where we only have the BackBuffer.
49-
if (resourceData.isActiveTargetBackBuffer)
50-
{
51-
Debug.LogError($"Skipping render pass. BlitAndSwapColorRendererFeature requires an intermediate ColorTexture, we can't use the BackBuffer as a texture input.");
52-
return;
53-
}
54-
55-
56-
// Starts the recording of the render graph pass given the name of the pass
57-
// and outputting the data used to pass data to the execution of the render function.
58-
using (var builder = renderGraph.AddRasterRenderPass<PassData>(m_PassName, out var passData))
59-
{
60-
// Initialize the pass data
61-
InitPassData(renderGraph, frameData, ref passData);
6212

63-
// Sets input.
64-
builder.UseTexture(passData.source);
13+
// This pass blits the whole screen for a given material to a temp texture, and swaps the UniversalResourceData.cameraColor to this temp texture.
14+
// Therefor, the next pass that references the cameraColor will reference this new temp texture as the cameraColor, saving us a blit.
15+
// Using the ResourceData, you can manage swapping of resources yourself and don't need a bespoke API like the SwapColorBuffer API that was specific for the cameraColor.
16+
// This allows you to write more decoupled passes without the added costs of avoidable copies/blits.
17+
public class BlitAndSwapColorPass : ScriptableRenderPass
18+
{
19+
const string m_PassName = "BlitAndSwapColorPass";
6520

66-
// Sets output.
67-
builder.SetRenderAttachment(passData.destination, 0);
21+
// Material used in the blit operation.
22+
Material m_BlitMaterial;
6823

69-
// Sets the render function.
70-
builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => ExecutePass(data, rgContext));
24+
// Function used to transfer the material from the renderer feature to the render pass.
25+
public void Setup(Material mat)
26+
{
27+
m_BlitMaterial = mat;
7128

29+
//The pass will read the current color texture. That needs to be an intermediate texture. It's not supported to use the BackBuffer as input texture.
30+
//By setting this property, URP will automatically create an intermediate texture.
31+
//It's good practice to set it here and not from the RenderFeature. This way, the pass is selfcontaining and you can use it to directly enqueue the pass from a monobehaviour without a RenderFeature.
32+
requiresIntermediateTexture = true;
33+
}
7234

73-
//FrameData allows to get and set internal pipeline buffers. Here we update the CameraColorBuffer to the texture that we just wrote to in this pass.
74-
//Because RenderGraph manages the pipeline resources and dependencies, following up passes will correctly use the right color buffer.
75-
//This optimization has some caveats. You have to be careful when the color buffer is persistent across frames and between different cameras, such as in camera stacking.
76-
//In those cases you need to make sure your texture is an RTHandle and that you properly manage the lifecycle of it.
77-
resourceData.cameraColor = passData.destination;
78-
}
79-
}
35+
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
36+
{
37+
// UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures
38+
// The active color and depth textures are the main color and depth buffers that the camera renders into
39+
var resourceData = frameData.Get<UniversalResourceData>();
8040

81-
// ExecutePass is the render function for each of the blit render graph recordings.
82-
// This is good practice to avoid using variables outside of the lambda it is called from.
83-
// It is static to avoid using member variables which could cause unintended behaviour.
84-
static void ExecutePass(PassData data, RasterGraphContext rgContext)
41+
//This should never happen since we set m_Pass.requiresIntermediateTexture = true;
42+
//Unless you set the render event to AfterRendering, where we only have the BackBuffer.
43+
if (resourceData.isActiveTargetBackBuffer)
8544
{
86-
// We can use blit with or without a material both using the static scaleBias to avoid reallocations.
87-
if (data.material == null)
88-
Blitter.BlitTexture(rgContext.cmd, data.source, scaleBias, 0, false);
89-
else
90-
Blitter.BlitTexture(rgContext.cmd, data.source, scaleBias, data.material, 0);
45+
Debug.LogError($"Skipping render pass. BlitAndSwapColorRendererFeature requires an intermediate ColorTexture, we can't use the BackBuffer as a texture input.");
46+
return;
9147
}
9248

93-
private void InitPassData(RenderGraph renderGraph, ContextContainer frameData, ref PassData passData)
94-
{
95-
// Fill up the passData with the data needed by the passes
49+
// The destination texture is created here,
50+
// the texture is created with the same dimensions as the active color texture
51+
var source = resourceData.activeColorTexture;
9652

97-
// UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures
98-
// The active color and depth textures are the main color and depth buffers that the camera renders into
99-
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
53+
var destinationDesc = renderGraph.GetTextureDesc(source);
54+
destinationDesc.name = $"CameraColor-{m_PassName}";
55+
destinationDesc.clearBuffer = false;
10056

101-
// The destination texture is created here,
102-
// the texture is created with the same dimensions as the active color texture, but with no depth buffer, being a copy of the color texture
57+
TextureHandle destination = renderGraph.CreateTexture(destinationDesc);
10358

104-
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
105-
RenderTextureDescriptor desc = cameraData.cameraTargetDescriptor;
106-
desc.depthBufferBits = 0;
59+
RenderGraphUtils.BlitMaterialParameters para = new(source, destination, m_BlitMaterial, 0);
60+
renderGraph.AddBlitPass(para, passName: m_PassName);
10761

108-
TextureHandle destination = UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, $"CameraTarget-{m_PassName}", false);
109-
110-
passData.source = resourceData.activeColorTexture;
111-
passData.destination = destination;
112-
passData.material = m_BlitMaterial;
113-
}
62+
//FrameData allows to get and set internal pipeline buffers. Here we update the CameraColorBuffer to the texture that we just wrote to in this pass.
63+
//Because RenderGraph manages the pipeline resources and dependencies, following up passes will correctly use the right color buffer.
64+
//This optimization has some caveats. You have to be careful when the color buffer is persistent across frames and between different cameras, such as in camera stacking.
65+
//In those cases you need to make sure your texture is an RTHandle and that you properly manage the lifecycle of it.
66+
resourceData.cameraColor = destination;
11467
}
68+
}
11569

116-
70+
public class BlitAndSwapColorRendererFeature : ScriptableRendererFeature
71+
{
11772
[Tooltip("The material used when making the blit operation.")]
11873
public Material material;
11974

@@ -143,11 +98,7 @@ public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingD
14398
}
14499

145100
m_Pass.Setup(material);
146-
renderer.EnqueuePass(m_Pass);
147-
148-
//The pass will read the current color texture. That needs to be an intermediate texture. It's not supported to use the BackBuffer as input texture.
149-
//By setting this property, URP will automatically create an intermediate texture.
150-
m_Pass.requiresIntermediateTexture = true;
101+
renderer.EnqueuePass(m_Pass);
151102
}
152103
}
153104

0 commit comments

Comments
 (0)