using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.Universal
{
///
/// Generate HDR debug data into the given color target
///
internal class HDRDebugViewPass : ScriptableRenderPass
{
private enum HDRDebugPassId
{
CIExyPrepass = 0,
DebugViewPass = 1
}
PassData m_PassData;
RTHandle m_CIExyTarget; // xyBuffer;
RTHandle m_PassthroughRT;
RTHandle m_CameraTargetHandle;
///
/// Creates a new HDRDebugViewPass instance.
///
/// The Material to use.
///
public HDRDebugViewPass(Material mat)
{
base.profilingSampler = new ProfilingSampler(nameof(HDRDebugViewPass));
renderPassEvent = RenderPassEvent.AfterRendering + 3;
m_PassData = new PassData() { material = mat };
// Disabling native render passes (for non-RG) because it renders to 2 different render targets
useNativeRenderPass = false;
}
// Common to RenderGraph and non-RenderGraph paths
private class PassData
{
internal Material material;
internal HDRDebugMode hdrDebugMode;
internal Vector4 luminanceParameters;
internal CameraData cameraData;
}
///
/// Get a descriptor for the required color texture for this pass
///
///
///
public static void ConfigureDescriptor(ref RenderTextureDescriptor descriptor)
{
descriptor.useMipMap = false;
descriptor.autoGenerateMips = false;
descriptor.useDynamicScale = true;
descriptor.depthBufferBits = (int)DepthBits.None;
}
public static void ConfigureDescriptorForCIEPrepass(ref RenderTextureDescriptor descriptor)
{
descriptor.graphicsFormat = GraphicsFormat.R32_SFloat;
descriptor.width = descriptor.height = ShaderConstants._SizeOfHDRXYMapping;
descriptor.enableRandomWrite = true;
descriptor.msaaSamples = 1;
descriptor.dimension = TextureDimension.Tex2D;
descriptor.vrUsage = VRTextureUsage.None; // We only need one for both eyes in VR
}
internal static Vector4 GetLuminanceParameters(ref CameraData cameraData)
{
var luminanceParams = Vector4.zero;
if (cameraData.isHDROutputActive)
{
Tonemapping tonemapping = VolumeManager.instance.stack.GetComponent();
UniversalRenderPipeline.GetHDROutputLuminanceParameters(cameraData.hdrDisplayInformation, cameraData.hdrDisplayColorGamut, tonemapping, out luminanceParams);
}
else
{
luminanceParams.z = 1.0f;
}
return luminanceParams;
}
private static void ExecuteCIExyPrepass(CommandBuffer cmd, PassData data, RTHandle sourceTexture, RTHandle xyTarget, RTHandle destTexture)
{
using (new ProfilingScope(cmd, new ProfilingSampler("Generate HDR DebugView CIExy")))
{
CoreUtils.SetRenderTarget(cmd, destTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.None, Color.clear);
var debugParameters = new Vector4(ShaderConstants._SizeOfHDRXYMapping, ShaderConstants._SizeOfHDRXYMapping, 0, 0);
cmd.SetRandomWriteTarget(ShaderConstants._CIExyUAVIndex, xyTarget);
data.material.SetVector(ShaderConstants._HDRDebugParamsId, debugParameters);
data.material.SetVector(ShaderPropertyId.hdrOutputLuminanceParams, data.luminanceParameters);
Vector2 viewportScale = sourceTexture.useScaling ? new Vector2(sourceTexture.rtHandleProperties.rtHandleScale.x, sourceTexture.rtHandleProperties.rtHandleScale.y) : Vector2.one;
Blitter.BlitTexture(cmd, sourceTexture, viewportScale, data.material, 0);
cmd.ClearRandomWriteTargets();
}
}
private static void ExecuteHDRDebugViewFinalPass(CommandBuffer cmd, PassData data,RTHandle sourceTexture, RTHandle destination, RTHandle xyTarget)
{
using (new ProfilingScope(cmd, new ProfilingSampler("HDR DebugView")))
{
if (data.cameraData.isHDROutputActive)
{
HDROutputUtils.ConfigureHDROutput(data.material, data.cameraData.hdrDisplayColorGamut, HDROutputUtils.Operation.ColorEncoding);
}
data.material.SetTexture(ShaderConstants._xyTextureId, xyTarget);
Vector4 debugParameters = new Vector4(ShaderConstants._SizeOfHDRXYMapping, ShaderConstants._SizeOfHDRXYMapping, 0, 0);
data.material.SetVector(ShaderConstants._HDRDebugParamsId, debugParameters);
data.material.SetVector(ShaderPropertyId.hdrOutputLuminanceParams, data.luminanceParameters);
data.material.SetInteger(ShaderConstants._DebugHDRModeId, (int)data.hdrDebugMode);
RenderingUtils.FinalBlit(cmd, ref data.cameraData, sourceTexture, destination, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, data.material, 1);
}
}
// Non-RenderGraph path
public void Dispose()
{
m_CIExyTarget?.Release();
m_PassthroughRT?.Release();
m_CameraTargetHandle?.Release();
}
///
/// Configure the pass
///
/// Active DebugMode for HDR.
public void Setup(ref CameraData cameraData, HDRDebugMode hdrdebugMode)
{
RenderTextureDescriptor descriptor = cameraData.cameraTargetDescriptor;
DebugHandler.ConfigureColorDescriptorForDebugScreen(ref descriptor, cameraData.pixelWidth, cameraData.pixelHeight);
RenderingUtils.ReAllocateIfNeeded(ref m_PassthroughRT, descriptor, name: "_HDRDebugDummyRT");
ConfigureDescriptorForCIEPrepass(ref descriptor);
RenderingUtils.ReAllocateIfNeeded(ref m_CIExyTarget, descriptor, name: "_xyBuffer");
m_PassData.hdrDebugMode = hdrdebugMode;
}
///
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var cmd = renderingData.commandBuffer;
m_PassData.luminanceParameters = GetLuminanceParameters(ref renderingData.cameraData);
m_PassData.cameraData = renderingData.cameraData;
var sourceTexture = renderingData.cameraData.renderer.cameraColorTargetHandle;
var cameraTarget = RenderingUtils.GetCameraTargetIdentifier(ref renderingData);
// Create RTHandle alias to use RTHandle apis
if (m_CameraTargetHandle != cameraTarget)
{
m_CameraTargetHandle?.Release();
m_CameraTargetHandle = RTHandles.Alloc(cameraTarget);
}
m_PassData.material.enabledKeywords = null;
GetActiveDebugHandler(ref renderingData)?.UpdateShaderGlobalPropertiesForFinalValidationPass(cmd, ref m_PassData.cameraData, true);
CoreUtils.SetRenderTarget(cmd, m_CIExyTarget, ClearFlag.Color, Color.clear);
ExecutePass(cmd, m_PassData, sourceTexture, m_CIExyTarget);
}
private void ExecutePass(CommandBuffer cmd, PassData data, RTHandle sourceTexture, RTHandle xyTarget)
{
//CIExyPrepass
ExecuteCIExyPrepass(cmd, data, sourceTexture, xyTarget, m_PassthroughRT);
//HDR DebugView - should always be the last stack of the camera
ExecuteHDRDebugViewFinalPass(cmd, data, m_PassthroughRT, m_CameraTargetHandle, xyTarget);
data.cameraData.renderer.ConfigureCameraTarget(m_CameraTargetHandle, m_CameraTargetHandle);
}
internal class ShaderConstants
{
public static readonly int _DebugHDRModeId = Shader.PropertyToID("_DebugHDRMode");
public static readonly int _HDRDebugParamsId = Shader.PropertyToID("_HDRDebugParams");
public static readonly int _xyTextureId = Shader.PropertyToID("_xyBuffer");
public static readonly int _SizeOfHDRXYMapping = 512;
public static readonly int _CIExyUAVIndex = 1;
}
}
}