Skip to content

Commit

Permalink
2022.2/renderrequest-refactor to 2022.2/staging
Browse files Browse the repository at this point in the history
Jira RPFoundation: https://jira.unity3d.com/browse/GFXRPF-33
Jira Plan of Intent: https://jira.unity3d.com/browse/RND-175 

Trunk PR: https://ono.unity3d.com/unity/unity/pull-request/143098/_/graphics/renderrequest-refactor

TDD: https://docs.google.com/document/d/13wTnUUrZd6u3a2x-YnAw_1at3Hdr3HlGd1jbUGZcV7Y/edit?usp=sharing

Provide a way to trigger SRP renders from script outside of the usual pipeline loop. The way this API is set-up allows us to expand functionality in the future by having a generic type.
The current issue is that API like Camera.Render offer no control to the SRP's on how these renders should be handled and break in various ways. With this API we can provide similar API to the users while giving control to the SRP's.

This PR provides the base API and implements 2 types of rendering for URP, HDRP support will be added later.

The two request types added are StandardRequest and SingleCameraRequest.
StandardRequest renders a full camera stack in URP and does not work on overlay camera's.
StandardRequest should be supported by HDRP in a future PR as well. 

SingleCameraRequest is URP specific and only renders one camera and can be executed on overlay camera's. The overlay camera will be treated as a base camera for that request.

For this API we want as many of the RequestData types to work exactly the same for both pipelines. So where it makes sense we add them to the RenderPipeline class. For those that really don't make sense we will implement them in their respective packages only.
  • Loading branch information
robin-demoor committed Jun 25, 2022
1 parent 9ddcffe commit 76150c8
Show file tree
Hide file tree
Showing 35 changed files with 4,371 additions and 2 deletions.
Expand Up @@ -34,7 +34,7 @@ public static ProfilingSampler TryGetOrAddCameraSampler(Camera camera)
if (!exists)
{
// NOTE: camera.name allocates!
ps = new ProfilingSampler($"{nameof(UniversalRenderPipeline)}.{nameof(RenderSingleCamera)}: {camera.name}");
ps = new ProfilingSampler($"{nameof(UniversalRenderPipeline)}.{nameof(RenderSingleCameraInternal)}: {camera.name}");
s_HashSamplerCache.Add(cameraId, ps);
}
return ps;
Expand Down Expand Up @@ -317,7 +317,7 @@ protected override void Render(ScriptableRenderContext renderContext, Camera[] c
#endif
UpdateVolumeFramework(camera, null);

RenderSingleCamera(renderContext, camera);
RenderSingleCameraInternal(renderContext, camera);

using (new ProfilingScope(null, Profiling.Pipeline.endCameraRendering))
{
Expand Down Expand Up @@ -345,14 +345,105 @@ protected override void Render(ScriptableRenderContext renderContext, Camera[] c
#endif
}

protected override bool IsRenderRequestSupported<RequestData>(Camera camera, RequestData data)
{
if (data is StandardRequest)
return true;
else if (data is SingleCameraRequest)
return true;

return false;
}

protected override void ProcessRenderRequests<RequestData>(ScriptableRenderContext context, Camera camera, RequestData renderRequest)
{
StandardRequest standardRequest = renderRequest as StandardRequest;
SingleCameraRequest singleRequest = renderRequest as SingleCameraRequest;

if(standardRequest != null || singleRequest != null)
{
RenderTexture destination = standardRequest != null ? standardRequest.destination : singleRequest.destination;
int mipLevel = standardRequest != null ? standardRequest.mipLevel : singleRequest.mipLevel;
int slice = standardRequest != null ? standardRequest.slice : singleRequest.slice;
int face = standardRequest != null ? (int)standardRequest.face : (int)singleRequest.face;

//store data that will be changed
var orignalTarget = camera.targetTexture;

//set data
RenderTexture temporaryRT = null;
RenderTextureDescriptor RTDesc = destination.descriptor;
//need to set use default constructor of RenderTextureDescriptor which doesn't enable allowVerticalFlip which matters for cubemaps.
if (destination.dimension == TextureDimension.Cube)
RTDesc = new RenderTextureDescriptor();

RTDesc.colorFormat = destination.format;
RTDesc.volumeDepth = 1;
RTDesc.msaaSamples = destination.descriptor.msaaSamples;
RTDesc.dimension = TextureDimension.Tex2D;
RTDesc.width = destination.width / (int)Math.Pow(2, mipLevel);
RTDesc.height = destination.height / (int)Math.Pow(2, mipLevel);
RTDesc.width = Mathf.Max(1, RTDesc.width);
RTDesc.height = Mathf.Max(1, RTDesc.height);

//if mip is 0 and target is Texture2D we can immediately render to the requested destination
if(destination.dimension != TextureDimension.Tex2D || mipLevel != 0)
{
temporaryRT = RenderTexture.GetTemporary(RTDesc);
}

camera.targetTexture = temporaryRT ? temporaryRT : destination;

if (standardRequest != null)
{
Render(context, new Camera[] { camera });
}
else
{
RenderSingleCameraInternal(context, camera);
}

if(temporaryRT)
{
switch(destination.dimension)
{
case TextureDimension.Tex2D:
case TextureDimension.Tex2DArray:
case TextureDimension.Tex3D:
Graphics.CopyTexture(temporaryRT, 0, 0, destination, slice, mipLevel);
break;
case TextureDimension.Cube:
case TextureDimension.CubeArray:
Graphics.CopyTexture(temporaryRT, 0, 0, destination, face + slice * 6, mipLevel);
break;
}
}

//restore data
camera.targetTexture = orignalTarget;
Graphics.SetRenderTarget(orignalTarget);
RenderTexture.ReleaseTemporary(temporaryRT);
}
else
{
Debug.LogWarning("The given RenderRequest type: " + typeof(RequestData).FullName + ", is either invalid or unsupported by the current pipeline");
}
}

/// <summary>
/// Standalone camera rendering. Use this to render procedural cameras.
/// This method doesn't call <c>BeginCameraRendering</c> and <c>EndCameraRendering</c> callbacks.
/// </summary>
/// <param name="context">Render context used to record commands during execution.</param>
/// <param name="camera">Camera to render.</param>
/// <seealso cref="ScriptableRenderContext"/>
[Obsolete("RenderSingleCamera is obsolete, please use RenderPipeline.SubmiteRenderRequest with UniversalRenderer.SingleCameraRequest as RequestData type", false)]
public static void RenderSingleCamera(ScriptableRenderContext context, Camera camera)
{
RenderSingleCameraInternal(context, camera);
}

internal static void RenderSingleCameraInternal(ScriptableRenderContext context, Camera camera)
{
UniversalAdditionalCameraData additionalCameraData = null;
if (IsGameCamera(camera))
Expand Down Expand Up @@ -1530,5 +1621,13 @@ static void ApplyAdaptivePerformance(ref RenderingData renderingData)
}

#endif

public class SingleCameraRequest
{
public RenderTexture destination = null;
public int mipLevel = 0;
public CubemapFace face = CubemapFace.Unknown;
public int slice = 0;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 76150c8

Please sign in to comment.