using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering.RenderGraphModule; using UnityEditor; namespace UnityEngine.Rendering.HighDefinition { public partial class HDRenderPipeline { bool m_FullScreenDebugPushed; Rendering.DebugOverlay m_DebugOverlay = new Rendering.DebugOverlay(); TextureHandle m_DebugFullScreenTexture; BufferHandle m_DebugFullScreenComputeBuffer; ShaderVariablesDebugDisplay m_ShaderVariablesDebugDisplayCB = new ShaderVariablesDebugDisplay(); ComputeShader m_ClearFullScreenBufferCS; int m_ClearFullScreenBufferKernel; Material m_DebugViewMaterialGBuffer; Material m_DebugViewMaterialGBufferShadowMask; Material m_currentDebugViewMaterialGBuffer; Material m_DebugDisplayLatlong; Material m_DebugFullScreen; Material m_DebugColorPicker; Material m_DebugExposure; Material m_DebugHDROutput; Material m_DebugViewTilesMaterial; Material m_DebugHDShadowMapMaterial; Material m_DebugLocalVolumetricFogMaterial; Material m_DebugBlitMaterial; Material m_DebugDrawClustersBoundsMaterial; // Color monitors Material m_DebugVectorscope; Material m_DebugWaveform; ComputeShader m_ComputePositionNormal; // Used to write a pixel's position and normal in a compute buffer to debug probe sampling #if ENABLE_VIRTUALTEXTURES Material m_VTDebugBlit; #endif private readonly DebugDisplaySettingsUI m_DebugDisplaySettingsUI = new DebugDisplaySettingsUI(); DebugDisplaySettings m_DebugDisplaySettings = new DebugDisplaySettings(); /// /// Debug display settings. /// public DebugDisplaySettings debugDisplaySettings { get { return m_DebugDisplaySettings; } } static DebugDisplaySettings s_NeutralDebugDisplaySettings = new DebugDisplaySettings(); internal DebugDisplaySettings m_CurrentDebugDisplaySettings; void InitializeDebug() { m_ComputePositionNormal = runtimeShaders.probeVolumeSamplingDebugComputeShader; m_DebugViewMaterialGBuffer = CoreUtils.CreateEngineMaterial(runtimeShaders.debugViewMaterialGBufferPS); m_DebugViewMaterialGBufferShadowMask = CoreUtils.CreateEngineMaterial(runtimeShaders.debugViewMaterialGBufferPS); m_DebugViewMaterialGBufferShadowMask.EnableKeyword("SHADOWS_SHADOWMASK"); m_DebugDisplayLatlong = CoreUtils.CreateEngineMaterial(runtimeShaders.debugDisplayLatlongPS); m_DebugFullScreen = CoreUtils.CreateEngineMaterial(runtimeShaders.debugFullScreenPS); m_DebugColorPicker = CoreUtils.CreateEngineMaterial(runtimeShaders.debugColorPickerPS); m_DebugExposure = CoreUtils.CreateEngineMaterial(runtimeShaders.debugExposurePS); m_DebugHDROutput = CoreUtils.CreateEngineMaterial(runtimeShaders.debugHDRPS); m_DebugViewTilesMaterial = CoreUtils.CreateEngineMaterial(runtimeShaders.debugViewTilesPS); m_DebugHDShadowMapMaterial = CoreUtils.CreateEngineMaterial(runtimeShaders.debugHDShadowMapPS); m_DebugLocalVolumetricFogMaterial = CoreUtils.CreateEngineMaterial(runtimeShaders.debugLocalVolumetricFogAtlasPS); m_DebugBlitMaterial = CoreUtils.CreateEngineMaterial(runtimeShaders.debugBlitQuad); m_DebugWaveform = CoreUtils.CreateEngineMaterial(runtimeShaders.debugWaveformPS); m_DebugVectorscope = CoreUtils.CreateEngineMaterial(runtimeShaders.debugVectorscopePS); m_ClearFullScreenBufferCS = runtimeShaders.clearDebugBufferCS; m_ClearFullScreenBufferKernel = m_ClearFullScreenBufferCS.FindKernel("clearMain"); #if ENABLE_VIRTUALTEXTURES m_VTDebugBlit = CoreUtils.CreateEngineMaterial(runtimeShaders.debugViewVirtualTexturingBlit); #endif } void CleanupDebug() { CoreUtils.Destroy(m_DebugViewMaterialGBuffer); CoreUtils.Destroy(m_DebugViewMaterialGBufferShadowMask); CoreUtils.Destroy(m_DebugDisplayLatlong); CoreUtils.Destroy(m_DebugFullScreen); CoreUtils.Destroy(m_DebugColorPicker); CoreUtils.Destroy(m_DebugExposure); CoreUtils.Destroy(m_DebugHDROutput); CoreUtils.Destroy(m_DebugViewTilesMaterial); CoreUtils.Destroy(m_DebugHDShadowMapMaterial); CoreUtils.Destroy(m_DebugLocalVolumetricFogMaterial); CoreUtils.Destroy(m_DebugBlitMaterial); CoreUtils.Destroy(m_DebugWaveform); CoreUtils.Destroy(m_DebugVectorscope); #if ENABLE_VIRTUALTEXTURES CoreUtils.Destroy(m_VTDebugBlit); #endif } internal bool showCascade { get => m_DebugDisplaySettings.GetDebugLightingMode() == DebugLightingMode.VisualizeCascade; set { if (value) m_DebugDisplaySettings.SetDebugLightingMode(DebugLightingMode.VisualizeCascade); else m_DebugDisplaySettings.SetDebugLightingMode(DebugLightingMode.None); } } internal bool NeedDebugDisplay() { return m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled(); } bool NeedColorPickerDebug(DebugDisplaySettings debugSettings) { return debugSettings.data.colorPickerDebugSettings.colorPickerMode != ColorPickerDebugMode.None || debugSettings.data.falseColorDebugSettings.falseColor || debugSettings.data.lightingDebugSettings.debugLightingMode == DebugLightingMode.LuminanceMeter; } bool NeedExposureDebugMode(DebugDisplaySettings debugSettings) { return debugSettings.data.lightingDebugSettings.exposureDebugMode != ExposureDebugMode.None; } bool NeedHDRDebugMode(DebugDisplaySettings debugSettings) { return debugSettings.data.lightingDebugSettings.hdrDebugMode != HDRDebugMode.None; } bool NeedsFullScreenDebugMode() { bool fullScreenDebugEnabled = m_CurrentDebugDisplaySettings.data.fullScreenDebugMode != FullScreenDebugMode.None; bool lightingDebugEnabled = m_CurrentDebugDisplaySettings.data.lightingDebugSettings.shadowDebugMode == ShadowMapDebugMode.SingleShadow; bool historyBufferViewEnabled = m_CurrentDebugDisplaySettings.data.historyBuffersView != -1; bool mipmapDebuggingEnabled = m_CurrentDebugDisplaySettings.data.mipMapDebugSettings.debugMipMapMode != DebugMipMapMode.None; return fullScreenDebugEnabled || lightingDebugEnabled || historyBufferViewEnabled || mipmapDebuggingEnabled; } unsafe void ApplyDebugDisplaySettings(HDCamera hdCamera, CommandBuffer cmd, bool aovOutput) { // See ShaderPassForward.hlsl: for forward shaders, if DEBUG_DISPLAY is enabled and no DebugLightingMode or DebugMipMapMod // modes have been set, lighting is automatically skipped (To avoid some crashed due to lighting RT not set on console). // However debug mode like colorPickerModes and false color don't need DEBUG_DISPLAY and must work with the lighting. // So we will enabled DEBUG_DISPLAY independently bool isSceneLightingDisabled = CoreUtils.IsSceneLightingDisabled(hdCamera.camera); bool debugDisplayEnabledOrSceneLightingDisabled = m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled() || isSceneLightingDisabled; // Enable globally the keyword DEBUG_DISPLAY on shader that support it with multi-compile CoreUtils.SetKeyword(cmd, "DEBUG_DISPLAY", debugDisplayEnabledOrSceneLightingDisabled); // Setting this all the time due to a strange bug that either reports a (globally) bound texture as not bound or where SetGlobalTexture doesn't behave as expected. // As a workaround we bind it regardless of debug display. Eventually with cmd.SetGlobalTexture(HDShaderIDs._DebugMatCapTexture, runtimeTextures.matcapTex); m_ShaderVariablesGlobalCB._GlobalTessellationFactorMultiplier = (m_CurrentDebugDisplaySettings.data.fullScreenDebugMode == FullScreenDebugMode.QuadOverdraw) ? 0.0f : 1.0f; if (debugDisplayEnabledOrSceneLightingDisabled || m_CurrentDebugDisplaySettings.data.colorPickerDebugSettings.colorPickerMode != ColorPickerDebugMode.None || m_CurrentDebugDisplaySettings.IsDebugExposureModeEnabled()) { var lightingDebugSettings = m_CurrentDebugDisplaySettings.data.lightingDebugSettings; var materialDebugSettings = m_CurrentDebugDisplaySettings.data.materialDebugSettings; var linearAlbedo = lightingDebugSettings.overrideAlbedoValue.linear; var linearSpecularColor = lightingDebugSettings.overrideSpecularColorValue.linear; var debugAlbedo = new Vector4(lightingDebugSettings.overrideAlbedo ? 1.0f : 0.0f, linearAlbedo.r, linearAlbedo.g, linearAlbedo.b); var debugSmoothness = new Vector4(lightingDebugSettings.overrideSmoothness ? 1.0f : 0.0f, lightingDebugSettings.overrideSmoothnessValue, 0.0f, 0.0f); var debugNormal = new Vector4(lightingDebugSettings.overrideNormal ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f); var debugAmbientOcclusion = new Vector4(lightingDebugSettings.overrideAmbientOcclusion ? 1.0f : 0.0f, lightingDebugSettings.overrideAmbientOcclusionValue, 0.0f, 0.0f); var debugSpecularColor = new Vector4(lightingDebugSettings.overrideSpecularColor ? 1.0f : 0.0f, linearSpecularColor.r, linearSpecularColor.g, linearSpecularColor.b); var debugEmissiveColor = new Vector4(lightingDebugSettings.overrideEmissiveColor ? 1.0f : 0.0f, lightingDebugSettings.overrideEmissiveColorValue.r, lightingDebugSettings.overrideEmissiveColorValue.g, lightingDebugSettings.overrideEmissiveColorValue.b); var debugTrueMetalColor = new Vector4(materialDebugSettings.materialValidateTrueMetal ? 1.0f : 0.0f, materialDebugSettings.materialValidateTrueMetalColor.r, materialDebugSettings.materialValidateTrueMetalColor.g, materialDebugSettings.materialValidateTrueMetalColor.b); ref var cb = ref m_ShaderVariablesDebugDisplayCB; var debugMaterialIndices = m_CurrentDebugDisplaySettings.GetDebugMaterialIndexes(); for (int i = 0; i < 11; ++i) { cb._DebugViewMaterialArray[i * 4] = (uint)debugMaterialIndices[i]; // Only x component is used. } for (int i = 0; i < 32; ++i) { for (int j = 0; j < 4; ++j) cb._DebugRenderingLayersColors[i * 4 + j] = m_CurrentDebugDisplaySettings.data.lightingDebugSettings.debugRenderingLayersColors[i][j]; } if (apvIsEnabled) { var subdivColors = ProbeReferenceVolume.instance.subdivisionDebugColors; for (int i = 0; i < 7; ++i) { for (int j = 0; j < 4; ++j) cb._DebugAPVSubdivColors[i * 4 + j] = subdivColors[i][j]; } } DebugLightingMode debugLightingMode = m_CurrentDebugDisplaySettings.GetDebugLightingMode(); // Mat Cap Mode Logic { bool matCapMixAlbedo = false; float matCapMixScale = 1.0f; if (debugLightingMode == DebugLightingMode.MatcapView) { matCapMixAlbedo = m_CurrentDebugDisplaySettings.data.lightingDebugSettings.matCapMixAlbedo; matCapMixScale = m_CurrentDebugDisplaySettings.data.lightingDebugSettings.matCapMixScale; } #if UNITY_EDITOR else if (isSceneLightingDisabled) { // Forcing the MatCap Mode when scene view lighting is disabled. Also use the default values debugLightingMode = DebugLightingMode.MatcapView; matCapMixAlbedo = HDRenderPipelinePreferences.matCapMode.mixAlbedo.value; matCapMixScale = HDRenderPipelinePreferences.matCapMode.viewScale.value; } #endif cb._MatcapMixAlbedo = matCapMixAlbedo ? 1 : 0; cb._MatcapViewScale = matCapMixScale; } cb._DebugLightingMode = (int)debugLightingMode; cb._DebugLightLayersMask = (int)m_CurrentDebugDisplaySettings.GetDebugLightLayersMask(); cb._DebugShadowMapMode = (int)m_CurrentDebugDisplaySettings.GetDebugShadowMapMode(); cb._DebugMipMapMode = (int)m_CurrentDebugDisplaySettings.GetDebugMipMapMode(); cb._DebugMipMapOpacity = m_CurrentDebugDisplaySettings.GetDebugMipMapOpacity(); cb._DebugMipMapStatusMode = (int) m_CurrentDebugDisplaySettings.GetDebugMipMapStatusMode(); cb._DebugMipMapShowStatusCode = m_CurrentDebugDisplaySettings.GetDebugMipMapShowStatusCode() ? 1 : 0; cb._DebugMipMapRecentlyUpdatedCooldown = m_CurrentDebugDisplaySettings.GetDebugMipMapRecentlyUpdatedCooldown(); cb._DebugIsLitShaderModeDeferred = hdCamera.frameSettings.litShaderMode == LitShaderMode.Deferred ? 1 : 0; cb._DebugMipMapModeTerrainTexture = (int)m_CurrentDebugDisplaySettings.GetDebugMipMapModeTerrainTexture(); cb._ColorPickerMode = (int)m_CurrentDebugDisplaySettings.GetDebugColorPickerMode(); cb._DebugFullScreenMode = (int)m_CurrentDebugDisplaySettings.data.fullScreenDebugMode; cb._DebugViewportSize = hdCamera.screenSize; cb._DebugLightingAlbedo = debugAlbedo; cb._DebugLightingSmoothness = debugSmoothness; cb._DebugLightingNormal = debugNormal; cb._DebugLightingAmbientOcclusion = debugAmbientOcclusion; cb._DebugLightingSpecularColor = debugSpecularColor; cb._DebugLightingEmissiveColor = debugEmissiveColor; cb._DebugLightingMaterialValidateHighColor = materialDebugSettings.materialValidateHighColor; cb._DebugLightingMaterialValidateLowColor = materialDebugSettings.materialValidateLowColor; cb._DebugLightingMaterialValidatePureMetalColor = debugTrueMetalColor; cb._MousePixelCoord = HDUtils.GetMouseCoordinates(hdCamera); cb._MouseClickPixelCoord = HDUtils.GetMouseClickCoordinates(hdCamera); cb._DebugSingleShadowIndex = m_CurrentDebugDisplaySettings.data.lightingDebugSettings.shadowDebugUseSelection ? m_DebugSelectedLightShadowIndex : (int)m_CurrentDebugDisplaySettings.data.lightingDebugSettings.shadowMapIndex; cb._DebugAOVOutput = aovOutput ? 1 : 0; #if UNITY_EDITOR cb._DebugCurrentRealTime = (float) EditorApplication.timeSinceStartup; #else cb._DebugCurrentRealTime = Time.realtimeSinceStartup; #endif ConstantBuffer.PushGlobal(cmd, m_ShaderVariablesDebugDisplayCB, HDShaderIDs._ShaderVariablesDebugDisplay); cmd.SetGlobalTexture(HDShaderIDs._DebugFont, runtimeTextures.debugFontTex); } } class MonitorsPassData { public float sizeRatio; public Material blitMaterial; public TextureHandle colorTexture; public TextureHandle downsampledInput; public Vector2Int downsampledSize; public Vector2Int inputSize; public MonitorsDebugSettings settings; public int runtimeDebugPannelWidth; // Waveform data public ComputeShader waveformCS; public BufferHandle waveformBuffer; public TextureHandle waveformTexture; public Material waveformMaterial; public int waveformClearKernel; public int waveformGatherKernel; // Vectorscope data public ComputeShader vectorscopeCS; public BufferHandle vectorscopeBuffer; public TextureHandle vectorscopeTexture; public Material vectorscopeMaterial; public Vector2Int vectorscopeSize; public int vectorscopeBufferSize; public int vectorscopeGatherKernel; public int vectorscopeClearKernel; } void RenderMonitorsOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, HDCamera hdCamera) { MonitorsDebugSettings settings = m_CurrentDebugDisplaySettings.data.monitorsDebugSettings; // If no monitor is enabled, skipping the pass if (!settings.vectorscopeToggle && !settings.waveformToggle) return; using RenderGraphBuilder builder = renderGraph.AddRenderPass("Monitors overlay", out MonitorsPassData data); // Filling in pass data data.runtimeDebugPannelWidth = HDUtils.GetRuntimeDebugPanelWidth(hdCamera); data.blitMaterial = m_DebugBlitMaterial; data.sizeRatio = settings.monitorsSize; data.colorTexture = builder.ReadWriteTexture(colorBuffer); data.settings = m_CurrentDebugDisplaySettings.data.monitorsDebugSettings; data.inputSize = new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight); // Downsampled input data.downsampledSize = new Vector2Int(hdCamera.actualWidth / 2, hdCamera.actualHeight / 2); data.downsampledInput = builder.CreateTransientTexture(new TextureDesc(data.downsampledSize.x, data.downsampledSize.y) { format = GraphicsFormat.R16G16B16A16_UNorm, name = "Downsampled color buffer" }); FillWaveformData (data, builder); FillVectorscopeData(data, (int)(hdCamera.actualHeight * data.sizeRatio), builder); builder.SetRenderFunc(static (MonitorsPassData passData, RenderGraphContext ctx) => { // Down-sampling the input HDUtils.BlitCameraTexture(ctx.cmd, passData.colorTexture, passData.downsampledInput, 0f, true); if (passData.settings.waveformToggle) RenderWaveformDebug(passData, ctx); if (passData.settings.vectorscopeToggle) RenderVectorScopeDebug(passData, ctx); // Finally composing the monitors on the color buffer const int spacing = 5; int horizontalOffset = passData.runtimeDebugPannelWidth + spacing; if (passData.settings.vectorscopeToggle) { ctx.cmd.SetGlobalTexture(HDShaderIDs._InputTexture, passData.vectorscopeTexture); ctx.cmd.SetRenderTarget (passData.colorTexture); ctx.cmd.SetViewport (new Rect(horizontalOffset, spacing, passData.vectorscopeSize.x, passData.vectorscopeSize.y)); ctx.cmd.DrawProcedural (Matrix4x4.identity, passData.blitMaterial, 0, MeshTopology.Triangles, 3, 1, null); horizontalOffset += passData.vectorscopeSize.x + spacing; } if (passData.settings.waveformToggle) { ctx.cmd.SetGlobalTexture(HDShaderIDs._InputTexture, passData.waveformTexture); ctx.cmd.SetRenderTarget (passData.colorTexture); ctx.cmd.SetViewport (new Rect(horizontalOffset, spacing, passData.inputSize.x * passData.sizeRatio, passData.inputSize.y * passData.sizeRatio)); ctx.cmd.DrawProcedural (Matrix4x4.identity, passData.blitMaterial, 0, MeshTopology.Triangles, 3, 1, null); } }); } void FillWaveformData(MonitorsPassData data, RenderGraphBuilder builder) { data.waveformCS = runtimeShaders.debugWaveformCS; data.waveformMaterial = m_DebugWaveform; data.waveformClearKernel = data.waveformCS.FindKernel("KWaveformClear"); data.waveformGatherKernel = data.waveformCS.FindKernel("KWaveformGather"); data.waveformBuffer = builder.CreateTransientBuffer( new BufferDesc(data.downsampledSize.x * data.downsampledSize.y, sizeof(uint) * 4) { name = "Waveform Debug Buffer" } ); data.waveformTexture = builder.CreateTransientTexture( new TextureDesc(data.downsampledSize.x, data.downsampledSize.y) { enableRandomWrite = true, format = GraphicsFormat.B10G11R11_UFloatPack32, name = "Waveform Debug Texture" } ); } void FillVectorscopeData(MonitorsPassData data, int size, RenderGraphBuilder builder) { data.vectorscopeCS = runtimeShaders.debugVectorscopeCS; data.vectorscopeSize = new Vector2Int(size, size); data.vectorscopeMaterial = m_DebugVectorscope; data.vectorscopeBufferSize = data.vectorscopeSize.x * data.vectorscopeSize.x; data.vectorscopeClearKernel = data.vectorscopeCS.FindKernel("KVectorscopeClear"); data.vectorscopeGatherKernel = data.vectorscopeCS.FindKernel("KVectorscopeGather"); data.vectorscopeTexture = builder.CreateTransientTexture(new TextureDesc(data.vectorscopeSize.x, data.vectorscopeSize.y) { enableRandomWrite = true, format = GetColorBufferFormat(), name = "Vectorscope Debug Texture" }); data.vectorscopeBuffer = builder.CreateTransientBuffer(new BufferDesc(data.vectorscopeBufferSize, sizeof(uint) * 4) { name = "Vectorscope Debug Buffer" }); } static void RenderVectorScopeDebug(MonitorsPassData data, RenderGraphContext ctx) { const float kThreadGroupSizeX = 16f; const float kThreadGroupSizeY = 16f; var parameters = new Vector4(data.vectorscopeSize.x, data.vectorscopeSize.y, data.settings.vectorscopeExposure); // Clearing the vectorscope buffer ctx.cmd.SetComputeBufferParam(data.vectorscopeCS, data.vectorscopeClearKernel, HDShaderIDs._VectorscopeBuffer, data.vectorscopeBuffer); ctx.cmd.SetComputeIntParam(data.vectorscopeCS, HDShaderIDs._BufferSize, data.vectorscopeSize.x); ctx.cmd.DispatchCompute(data.vectorscopeCS, data.vectorscopeClearKernel, Mathf.CeilToInt(data.vectorscopeSize.x / kThreadGroupSizeX), Mathf.CeilToInt(data.vectorscopeSize.y / kThreadGroupSizeY), 1); // Gather all pixels and fill our vectorscope ctx.cmd.SetComputeBufferParam (data.vectorscopeCS, data.vectorscopeGatherKernel, HDShaderIDs._VectorscopeBuffer, data.vectorscopeBuffer); ctx.cmd.SetComputeTextureParam(data.vectorscopeCS, data.vectorscopeGatherKernel, HDShaderIDs._Source, data.downsampledInput); ctx.cmd.DispatchCompute(data.vectorscopeCS, data.vectorscopeGatherKernel, Mathf.CeilToInt(data.downsampledSize.x / kThreadGroupSizeX), Mathf.CeilToInt(data.downsampledSize.y / kThreadGroupSizeY), 1); // Generate our vectorscope texture data.vectorscopeMaterial.SetBuffer(HDShaderIDs._VectorscopeBuffer, data.vectorscopeBuffer); data.vectorscopeMaterial.SetVector(HDShaderIDs._VectorscopeParameters, parameters); ctx.cmd.SetRenderTarget(data.vectorscopeTexture); ctx.cmd.DrawProcedural(Matrix4x4.identity, data.vectorscopeMaterial, 0, MeshTopology.Triangles, 3, 1, null); } static void RenderWaveformDebug(MonitorsPassData data, RenderGraphContext ctx) { const float kThreadGroupSizeX = 16f; const float kThreadGroupSizeY = 16f; var parameters = new Vector4(data.downsampledSize.x, data.downsampledSize.y, data.settings.waveformExposure, data.settings.waveformParade ? 1f : 0f); // Clearing the waveform buffer ctx.cmd.SetComputeBufferParam(data.waveformCS, data.waveformClearKernel, HDShaderIDs._WaveformBuffer, data.waveformBuffer); ctx.cmd.SetComputeVectorParam(data.waveformCS, HDShaderIDs._Params, parameters); ctx.cmd.DispatchCompute(data.waveformCS, data.waveformClearKernel, Mathf.CeilToInt(data.downsampledSize.x / kThreadGroupSizeX), Mathf.CeilToInt(data.downsampledSize.y / kThreadGroupSizeY), 1); // Gather all pixels and fill in our waveform ctx.cmd.SetComputeTextureParam(data.waveformCS, data.waveformGatherKernel, HDShaderIDs._Source , data.downsampledInput); ctx.cmd.SetComputeBufferParam (data.waveformCS, data.waveformGatherKernel, HDShaderIDs._WaveformBuffer, data.waveformBuffer); ctx.cmd.DispatchCompute(data.waveformCS, data.waveformGatherKernel, Mathf.CeilToInt(data.downsampledSize.x / kThreadGroupSizeX), Mathf.CeilToInt(data.downsampledSize.y / kThreadGroupSizeY), 1); // Filling the waveform texture from the buffer data.waveformMaterial.SetBuffer(HDShaderIDs._WaveformBuffer, data.waveformBuffer); data.waveformMaterial.SetVector(HDShaderIDs._WaveformParameters, parameters); ctx.cmd.SetRenderTarget(data.waveformTexture); ctx.cmd.DrawProcedural(Matrix4x4.identity, data.waveformMaterial, 0, MeshTopology.Triangles, 3, 1, null); } class TransparencyOverdrawPassData { public FrameSettings frameSettings; public ShaderVariablesDebugDisplay constantBuffer; public RendererListHandle transparencyRL; public RendererListHandle transparencyAfterPostRL; public RendererListHandle transparencyLowResRL; } void RenderTransparencyOverdraw(RenderGraph renderGraph, TextureHandle depthBuffer, CullingResults cull, HDCamera hdCamera) { if (m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled() && m_CurrentDebugDisplaySettings.data.fullScreenDebugMode == FullScreenDebugMode.TransparencyOverdraw) { TextureHandle transparencyOverdrawOutput = TextureHandle.nullHandle; using (var builder = renderGraph.AddRenderPass("Transparency Overdraw", out var passData)) { var passNames = m_Asset.currentPlatformRenderPipelineSettings.supportTransparentBackface ? m_AllTransparentPassNames : m_TransparentNoBackfaceNames; var stateBlock = new RenderStateBlock { mask = RenderStateMask.Blend, blendState = new BlendState { blendState0 = new RenderTargetBlendState { destinationColorBlendMode = BlendMode.One, sourceColorBlendMode = BlendMode.One, destinationAlphaBlendMode = BlendMode.One, sourceAlphaBlendMode = BlendMode.One, colorBlendOperation = BlendOp.Add, alphaBlendOperation = BlendOp.Add, writeMask = ColorWriteMask.All } } }; passData.frameSettings = hdCamera.frameSettings; passData.constantBuffer = m_ShaderVariablesDebugDisplayCB; builder.UseDepthBuffer(depthBuffer, DepthAccess.Read); passData.transparencyRL = builder.UseRendererList(renderGraph.CreateRendererList( CreateTransparentRendererListDesc(cull, hdCamera.camera, passNames, stateBlock: stateBlock))); passData.transparencyAfterPostRL = builder.UseRendererList( renderGraph.CreateRendererList(CreateTransparentRendererListDesc(cull, hdCamera.camera, passNames, renderQueueRange: HDRenderQueue.k_RenderQueue_AfterPostProcessTransparent, stateBlock: stateBlock))); passData.transparencyLowResRL = builder.UseRendererList( renderGraph.CreateRendererList(CreateTransparentRendererListDesc(cull, hdCamera.camera, passNames, renderQueueRange: HDRenderQueue.k_RenderQueue_LowTransparent, stateBlock: stateBlock))); transparencyOverdrawOutput = builder.UseColorBuffer(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { name = "Transparency Overdraw", format = GetColorBufferFormat(), clearBuffer = true, clearColor = Color.black }), 0); builder.SetRenderFunc( (TransparencyOverdrawPassData data, RenderGraphContext ctx) => { data.constantBuffer._DebugTransparencyOverdrawWeight = 1.0f; ConstantBuffer.PushGlobal(ctx.cmd, data.constantBuffer, HDShaderIDs._ShaderVariablesDebugDisplay); DrawTransparentRendererList(ctx.renderContext, ctx.cmd, data.frameSettings, data.transparencyRL); DrawTransparentRendererList(ctx.renderContext, ctx.cmd, data.frameSettings, data.transparencyAfterPostRL); data.constantBuffer._DebugTransparencyOverdrawWeight = 0.25f; ConstantBuffer.PushGlobal(ctx.cmd, data.constantBuffer, HDShaderIDs._ShaderVariablesDebugDisplay); DrawTransparentRendererList(ctx.renderContext, ctx.cmd, data.frameSettings, data.transparencyLowResRL); }); } PushFullScreenDebugTexture(renderGraph, transparencyOverdrawOutput, FullScreenDebugMode.TransparencyOverdraw); } } class FullScreenDebugPassData { public FrameSettings frameSettings; public BufferHandle debugBuffer; public RendererListHandle rendererList; public ComputeShader clearBufferCS; public int clearBufferCSKernel; public int width; public int height; public int viewCount; } void RenderFullScreenDebug(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, CullingResults cull, HDCamera hdCamera) { using (var builder = renderGraph.AddRenderPass("FullScreen Debug", out var passData)) { builder.UseColorBuffer(colorBuffer, 0); builder.UseDepthBuffer(depthBuffer, DepthAccess.Read); m_DebugFullScreenComputeBuffer = renderGraph.CreateBuffer(new BufferDesc(hdCamera.actualWidth * hdCamera.actualHeight * hdCamera.viewCount, sizeof(uint))); passData.frameSettings = hdCamera.frameSettings; passData.debugBuffer = builder.WriteBuffer(m_DebugFullScreenComputeBuffer); passData.rendererList = builder.UseRendererList(renderGraph.CreateRendererList(CreateOpaqueRendererListDesc(cull, hdCamera.camera, m_FullScreenDebugPassNames, renderQueueRange: RenderQueueRange.all))); passData.clearBufferCS = m_ClearFullScreenBufferCS; passData.clearBufferCSKernel = m_ClearFullScreenBufferKernel; passData.width = hdCamera.actualWidth; passData.height = hdCamera.actualHeight; passData.viewCount = hdCamera.viewCount; builder.SetRenderFunc( (FullScreenDebugPassData data, RenderGraphContext ctx) => { ctx.cmd.SetComputeVectorParam(data.clearBufferCS, HDShaderIDs._QuadOverdrawClearBuffParams, new Vector4(data.width, data.height, 0.0f, 0.0f)); ctx.cmd.SetComputeBufferParam(data.clearBufferCS, data.clearBufferCSKernel, HDShaderIDs._FullScreenDebugBuffer, data.debugBuffer); ctx.cmd.DispatchCompute(data.clearBufferCS, data.clearBufferCSKernel, HDUtils.DivRoundUp(data.width, 16), HDUtils.DivRoundUp(data.height, 16), data.viewCount); ctx.cmd.SetRandomWriteTarget(1, data.debugBuffer); CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, data.rendererList); ctx.cmd.ClearRandomWriteTargets(); }); } // This is not useful in theory but its just to register there is a fullscreen debug active PushFullScreenDebugTexture(renderGraph, ResolveMSAAColor(renderGraph, hdCamera, colorBuffer)); } class ResolveFullScreenDebugPassData { public DebugDisplaySettings debugDisplaySettings; public Material debugFullScreenMaterial; public HDCamera hdCamera; public Vector4 depthPyramidParams; public TextureHandle output; public TextureHandle input; public TextureHandle depthPyramid; public TextureHandle thickness; public BufferHandle thicknessReindex; public BufferHandle fullscreenBuffer; } TextureHandle ResolveFullScreenDebug(RenderGraph renderGraph, TextureHandle inputFullScreenDebug, TextureHandle depthPyramid, HDCamera hdCamera, GraphicsFormat rtFormat = GraphicsFormat.R16G16B16A16_SFloat) { using (var builder = renderGraph.AddRenderPass("ResolveFullScreenDebug", out var passData)) { passData.hdCamera = hdCamera; passData.debugDisplaySettings = m_CurrentDebugDisplaySettings; passData.debugFullScreenMaterial = m_DebugFullScreen; passData.input = builder.ReadTexture(inputFullScreenDebug); passData.depthPyramid = builder.ReadTexture(depthPyramid); { int mipCount = hdCamera.depthBufferMipChainInfo.mipLevelCount; int mipIndex = Mathf.Min(Mathf.FloorToInt(m_CurrentDebugDisplaySettings.data.fullscreenDebugMip * mipCount), mipCount - 1); Vector2Int mipOffset = hdCamera.depthBufferMipChainInfo.mipLevelOffsets[mipIndex]; if (m_CurrentDebugDisplaySettings.data.depthPyramidView == DepthPyramidDebugView.CheckerboardDepth && hdCamera.depthBufferMipChainInfo.mipLevelCountCheckerboard != 0) { mipIndex = Mathf.Min(mipIndex, hdCamera.depthBufferMipChainInfo.mipLevelCountCheckerboard - 1); mipOffset = hdCamera.depthBufferMipChainInfo.mipLevelOffsetsCheckerboard[mipIndex]; } passData.depthPyramidParams = new Vector4(mipIndex, mipOffset.x, mipOffset.y, 0.0f); } if (IsComputeThicknessNeeded(hdCamera)) passData.thickness = builder.ReadTexture(HDComputeThickness.Instance.GetThicknessTextureArray()); else passData.thickness = builder.ReadTexture(renderGraph.defaultResources.blackTextureArrayXR); passData.thicknessReindex = builder.ReadBuffer(renderGraph.ImportBuffer(HDComputeThickness.Instance.GetReindexMap())); // On Vulkan, not binding the Random Write Target will result in an invalid drawcall. // To avoid that, if the compute buffer is invalid, we bind a dummy compute buffer anyway. if (m_DebugFullScreenComputeBuffer.IsValid()) passData.fullscreenBuffer = builder.ReadBuffer(m_DebugFullScreenComputeBuffer); else passData.fullscreenBuffer = builder.CreateTransientBuffer(new BufferDesc(4, sizeof(uint))); passData.output = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, false /* we dont want DRS on this output target*/, true /*We want XR support on this output target*/) { format = rtFormat, name = "ResolveFullScreenDebug" })); builder.SetRenderFunc( (ResolveFullScreenDebugPassData data, RenderGraphContext ctx) => { var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); ComputeVolumetricFogSliceCountAndScreenFraction(data.hdCamera.volumeStack.GetComponent(), out var volumetricSliceCount, out _); BindGlobalThicknessBuffers(data.thickness, data.thicknessReindex, ctx.cmd); mpb.SetTexture(HDShaderIDs._DebugFullScreenTexture, data.input); mpb.SetTexture(HDShaderIDs._CameraDepthTexture, data.depthPyramid); mpb.SetFloat(HDShaderIDs._FullScreenDebugMode, (float)data.debugDisplaySettings.data.fullScreenDebugMode); mpb.SetFloat(HDShaderIDs._ApplyExposure, data.debugDisplaySettings.data.SupportsExposure() && data.debugDisplaySettings.data.applyExposure ? 1 : 0); if (data.debugDisplaySettings.data.enableDebugDepthRemap) mpb.SetVector(HDShaderIDs._FullScreenDebugDepthRemap, new Vector4(data.debugDisplaySettings.data.fullScreenDebugDepthRemap.x, data.debugDisplaySettings.data.fullScreenDebugDepthRemap.y, data.hdCamera.camera.nearClipPlane, data.hdCamera.camera.farClipPlane)); else // Setup neutral value mpb.SetVector(HDShaderIDs._FullScreenDebugDepthRemap, new Vector4(0.0f, 1.0f, 0.0f, 1.0f)); mpb.SetVector(HDShaderIDs._DebugDepthPyramidParams, data.depthPyramidParams); mpb.SetInt(HDShaderIDs._DebugContactShadowLightIndex, data.debugDisplaySettings.data.fullScreenContactShadowLightIndex); mpb.SetFloat(HDShaderIDs._TransparencyOverdrawMaxPixelCost, (float)data.debugDisplaySettings.data.transparencyDebugSettings.maxPixelCost); mpb.SetFloat(HDShaderIDs._FogVolumeOverdrawMaxValue, (float)volumetricSliceCount); mpb.SetFloat(HDShaderIDs._QuadOverdrawMaxQuadCost, (float)data.debugDisplaySettings.data.maxQuadCost); mpb.SetFloat(HDShaderIDs._VertexDensityMaxPixelCost, (float)data.debugDisplaySettings.data.maxVertexDensity); mpb.SetFloat(HDShaderIDs._MinMotionVector, data.debugDisplaySettings.data.minMotionVectorLength); mpb.SetVector(HDShaderIDs._MotionVecIntensityParams, new Vector4(data.debugDisplaySettings.data.motionVecVisualizationScale, data.debugDisplaySettings.data.motionVecIntensityHeat ? 1 : 0, 0, 0)); mpb.SetInt(HDShaderIDs._ComputeThicknessLayerIndex, (int)data.debugDisplaySettings.data.computeThicknessLayerIndex); mpb.SetInt(HDShaderIDs._ComputeThicknessShowOverlapCount, data.debugDisplaySettings.data.computeThicknessShowOverlapCount ? 1 : 0); mpb.SetFloat(HDShaderIDs._ComputeThicknessScale, data.debugDisplaySettings.data.computeThicknessScale); mpb.SetInt(HDShaderIDs._VolumetricCloudsDebugMode, (int)data.debugDisplaySettings.data.volumetricCloudDebug); ctx.cmd.SetRandomWriteTarget(1, data.fullscreenBuffer); HDUtils.DrawFullScreen(ctx.cmd, data.debugFullScreenMaterial, data.output, mpb, 0); ctx.cmd.ClearRandomWriteTargets(); }); return passData.output; } } class ResolveColorPickerDebugPassData { public HDCamera hdCamera; public DebugDisplaySettings debugDisplaySettings; public Material colorPickerMaterial; public TextureHandle output; public TextureHandle input; } TextureHandle ResolveColorPickerDebug(RenderGraph renderGraph, TextureHandle inputColorPickerDebug, HDCamera hdCamera, GraphicsFormat rtFormat = GraphicsFormat.R16G16B16A16_SFloat) { using (var builder = renderGraph.AddRenderPass("ResolveColorPickerDebug", out var passData)) { passData.hdCamera = hdCamera; passData.debugDisplaySettings = m_CurrentDebugDisplaySettings; passData.colorPickerMaterial = m_DebugColorPicker; passData.input = builder.ReadTexture(inputColorPickerDebug); passData.output = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = rtFormat, name = "ResolveColorPickerDebug" })); builder.SetRenderFunc( (ResolveColorPickerDebugPassData data, RenderGraphContext ctx) => { var falseColorDebugSettings = data.debugDisplaySettings.data.falseColorDebugSettings; var colorPickerDebugSettings = data.debugDisplaySettings.data.colorPickerDebugSettings; var falseColorThresholds = new Vector4(falseColorDebugSettings.colorThreshold0, falseColorDebugSettings.colorThreshold1, falseColorDebugSettings.colorThreshold2, falseColorDebugSettings.colorThreshold3); // Here we have three cases: // - Material debug is enabled, this is the buffer we display // - Otherwise we display the HDR buffer before postprocess and distortion // - If fullscreen debug is enabled we always use it data.colorPickerMaterial.SetTexture(HDShaderIDs._DebugColorPickerTexture, data.input); data.colorPickerMaterial.SetColor(HDShaderIDs._ColorPickerFontColor, colorPickerDebugSettings.fontColor); data.colorPickerMaterial.SetInt(HDShaderIDs._FalseColorEnabled, falseColorDebugSettings.falseColor ? 1 : 0); data.colorPickerMaterial.SetVector(HDShaderIDs._FalseColorThresholds, falseColorThresholds); data.colorPickerMaterial.SetVector(HDShaderIDs._MousePixelCoord, HDUtils.GetMouseCoordinates(data.hdCamera)); data.colorPickerMaterial.SetVector(HDShaderIDs._MouseClickPixelCoord, HDUtils.GetMouseClickCoordinates(data.hdCamera)); // The material display debug perform sRGBToLinear conversion as the final blit currently hardcodes a linearToSrgb conversion. As when we read with color picker this is not done, // we perform it inside the color picker shader. But we shouldn't do it for HDR buffer. data.colorPickerMaterial.SetFloat(HDShaderIDs._ApplyLinearToSRGB, data.debugDisplaySettings.IsDebugMaterialDisplayEnabled() ? 1.0f : 0.0f); HDUtils.DrawFullScreen(ctx.cmd, data.colorPickerMaterial, data.output); }); return passData.output; } } class DebugOverlayPassData { public Rendering.DebugOverlay debugOverlay; public TextureHandle colorBuffer; public TextureHandle depthBuffer; } class SkyReflectionOverlayPassData : DebugOverlayPassData { public LightingDebugSettings lightingDebugSettings; public Material debugLatlongMaterial; public Texture skyReflectionTexture; } void RenderSkyReflectionOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, HDCamera hdCamera) { if (!m_CurrentDebugDisplaySettings.data.lightingDebugSettings.displaySkyReflection) return; using (var builder = renderGraph.AddRenderPass("SkyReflectionOverlay", out var passData)) { passData.debugOverlay = m_DebugOverlay; passData.colorBuffer = builder.UseColorBuffer(colorBuffer, 0); passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.lightingDebugSettings = m_CurrentDebugDisplaySettings.data.lightingDebugSettings; passData.skyReflectionTexture = m_SkyManager.GetSkyReflection(hdCamera); passData.debugLatlongMaterial = m_DebugDisplayLatlong; builder.SetRenderFunc( (SkyReflectionOverlayPassData data, RenderGraphContext ctx) => { var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); ctx.cmd.SetViewport(data.debugOverlay.Next()); mpb.SetTexture(HDShaderIDs._InputCubemap, data.skyReflectionTexture); mpb.SetFloat(HDShaderIDs._Mipmap, data.lightingDebugSettings.skyReflectionMipmap); mpb.SetFloat(HDShaderIDs._ApplyExposure, 1.0f); mpb.SetFloat(HDShaderIDs._SliceIndex, data.lightingDebugSettings.cubeArraySliceIndex); ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugLatlongMaterial, 0, MeshTopology.Triangles, 3, 1, mpb); }); } } void RenderRayCountOverlay(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer, TextureHandle depthBuffer, TextureHandle rayCountTexture) { if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing)) return; m_RayCountManager.EvaluateRayCount(renderGraph, hdCamera, colorBuffer, depthBuffer, rayCountTexture); } class RenderAtlasDebugOverlayPassData : DebugOverlayPassData { public Texture atlasTexture; public int mipLevel; public Material debugBlitMaterial; } void RenderAtlasDebugOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, Texture atlas, int slice, int mipLevel, bool applyExposure, string passName, HDProfileId profileID) { using (var builder = renderGraph.AddRenderPass(passName, out var passData, ProfilingSampler.Get(profileID))) { passData.debugOverlay = m_DebugOverlay; passData.colorBuffer = builder.UseColorBuffer(colorBuffer, 0); passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.debugBlitMaterial = m_DebugBlitMaterial; passData.mipLevel = mipLevel; passData.atlasTexture = atlas; builder.SetRenderFunc( (RenderAtlasDebugOverlayPassData data, RenderGraphContext ctx) => { Debug.Assert(data.atlasTexture.dimension == TextureDimension.Tex2D || data.atlasTexture.dimension == TextureDimension.Tex2DArray); ctx.cmd.SetViewport(data.debugOverlay.Next((float)data.atlasTexture.width / data.atlasTexture.height)); int shaderPass; var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); mpb.SetFloat(HDShaderIDs._ApplyExposure, applyExposure ? 1.0f : 0.0f); mpb.SetFloat(HDShaderIDs._Mipmap, data.mipLevel); if (data.atlasTexture.dimension == TextureDimension.Tex2D) { shaderPass = 0; mpb.SetTexture(HDShaderIDs._InputTexture, data.atlasTexture); } else { shaderPass = 1; mpb.SetTexture(HDShaderIDs._InputTextureArray, data.atlasTexture); mpb.SetInt(HDShaderIDs._ArrayIndex, slice); } ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugBlitMaterial, shaderPass, MeshTopology.Triangles, 3, 1, mpb); }); } } class RenderTileClusterDebugOverlayPassData : DebugOverlayPassData { public HDCamera hdCamera; public TextureHandle depthPyramidTexture; public BufferHandle tileList; public BufferHandle lightList; public BufferHandle perVoxelLightList; public BufferHandle dispatchIndirect; public Material debugViewTilesMaterial; public LightingDebugSettings lightingDebugSettings; public Vector4 lightingViewportSize; } void RenderTileClusterDebugOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, in BuildGPULightListOutput lightLists, TextureHandle depthPyramidTexture, HDCamera hdCamera) { // Depending on the debug mode enabled we may not be building the light lists so the buffers would not be valid in this case. if (!lightLists.tileList.IsValid()) return; if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.tileClusterDebug == TileClusterDebug.None) return; using (var builder = renderGraph.AddRenderPass("RenderTileAndClusterDebugOverlay", out var passData, ProfilingSampler.Get(HDProfileId.TileClusterLightingDebug))) { passData.hdCamera = hdCamera; passData.debugOverlay = m_DebugOverlay; passData.colorBuffer = builder.UseColorBuffer(colorBuffer, 0); passData.depthPyramidTexture = builder.ReadTexture(depthPyramidTexture); passData.tileList = builder.ReadBuffer(lightLists.tileList); passData.lightList = builder.ReadBuffer(lightLists.lightList); passData.perVoxelLightList = builder.ReadBuffer(lightLists.perVoxelLightLists); passData.dispatchIndirect = builder.ReadBuffer(lightLists.dispatchIndirectBuffer); passData.debugViewTilesMaterial = m_DebugViewTilesMaterial; passData.lightingDebugSettings = m_CurrentDebugDisplaySettings.data.lightingDebugSettings; passData.lightingViewportSize = new Vector4(hdCamera.actualWidth, hdCamera.actualHeight, 1.0f / (float)hdCamera.actualWidth, 1.0f / (float)hdCamera.actualHeight); builder.SetRenderFunc( (RenderTileClusterDebugOverlayPassData data, RenderGraphContext ctx) => { int w = data.hdCamera.actualWidth; int h = data.hdCamera.actualHeight; int numTilesX = (w + 15) / 16; int numTilesY = (h + 15) / 16; int numTiles = numTilesX * numTilesY; var lightingDebug = data.lightingDebugSettings; // Debug tiles if (lightingDebug.tileClusterDebug == TileClusterDebug.MaterialFeatureVariants) { if (GetFeatureVariantsEnabled(data.hdCamera.frameSettings)) { // featureVariants data.debugViewTilesMaterial.SetInt(HDShaderIDs._NumTiles, numTiles); data.debugViewTilesMaterial.SetInt(HDShaderIDs._ViewTilesFlags, (int)lightingDebug.tileClusterDebugByCategory); data.debugViewTilesMaterial.SetVector(HDShaderIDs._MousePixelCoord, HDUtils.GetMouseCoordinates(data.hdCamera)); data.debugViewTilesMaterial.SetVector(HDShaderIDs._MouseClickPixelCoord, HDUtils.GetMouseClickCoordinates(data.hdCamera)); data.debugViewTilesMaterial.SetVector(HDShaderIDs._ClusterDebugLightViewportSize, data.lightingViewportSize); data.debugViewTilesMaterial.SetBuffer(HDShaderIDs.g_TileList, data.tileList); data.debugViewTilesMaterial.SetBuffer(HDShaderIDs.g_DispatchIndirectBuffer, data.dispatchIndirect); CoreUtils.SetKeyword(ctx.cmd, "USE_FPTL_LIGHTLIST", true); CoreUtils.SetKeyword(ctx.cmd, "USE_CLUSTERED_LIGHTLIST", false); data.debugViewTilesMaterial.DisableKeyword("SHOW_LIGHT_CATEGORIES"); data.debugViewTilesMaterial.EnableKeyword("SHOW_FEATURE_VARIANTS"); ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugViewTilesMaterial, 0, MeshTopology.Triangles, numTiles * 6); } } else // tile or cluster { bool bUseClustered = lightingDebug.tileClusterDebug == TileClusterDebug.Cluster; // lightCategories data.debugViewTilesMaterial.SetInt(HDShaderIDs._ViewTilesFlags, (int)lightingDebug.tileClusterDebugByCategory); data.debugViewTilesMaterial.SetInt(HDShaderIDs._ClusterDebugMode, bUseClustered ? (int)lightingDebug.clusterDebugMode : (int)ClusterDebugMode.VisualizeOpaque); data.debugViewTilesMaterial.SetFloat(HDShaderIDs._ClusterDebugDistance, lightingDebug.clusterDebugDistance); data.debugViewTilesMaterial.SetVector(HDShaderIDs._ClusterDebugLightViewportSize, data.lightingViewportSize); data.debugViewTilesMaterial.SetVector(HDShaderIDs._MousePixelCoord, HDUtils.GetMouseCoordinates(data.hdCamera)); data.debugViewTilesMaterial.SetVector(HDShaderIDs._MouseClickPixelCoord, HDUtils.GetMouseClickCoordinates(data.hdCamera)); data.debugViewTilesMaterial.SetBuffer(HDShaderIDs.g_vLightListTile, data.lightList); data.debugViewTilesMaterial.SetBuffer(HDShaderIDs.g_vLightListCluster, data.perVoxelLightList); data.debugViewTilesMaterial.SetTexture(HDShaderIDs._CameraDepthTexture, data.depthPyramidTexture); CoreUtils.SetKeyword(ctx.cmd, "USE_FPTL_LIGHTLIST", !bUseClustered); CoreUtils.SetKeyword(ctx.cmd, "USE_CLUSTERED_LIGHTLIST", bUseClustered); data.debugViewTilesMaterial.EnableKeyword("SHOW_LIGHT_CATEGORIES"); data.debugViewTilesMaterial.DisableKeyword("SHOW_FEATURE_VARIANTS"); if (!bUseClustered && data.hdCamera.msaaEnabled) data.debugViewTilesMaterial.EnableKeyword("DISABLE_TILE_MODE"); else data.debugViewTilesMaterial.DisableKeyword("DISABLE_TILE_MODE"); HDUtils.DrawFullScreen(ctx.cmd, data.debugViewTilesMaterial, data.colorBuffer); } }); } } class RenderShadowsDebugOverlayPassData : DebugOverlayPassData { public LightingDebugSettings lightingDebugSettings; public ShadowResult shadowTextures; public HDShadowManager shadowManager; public int debugSelectedLightShadowIndex; public int debugSelectedLightShadowCount; public Material debugShadowMapMaterial; } void RenderShadowsDebugOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, in ShadowResult shadowResult) { if (HDRenderPipeline.currentAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams.maxShadowRequests == 0 || m_CurrentDebugDisplaySettings.data.lightingDebugSettings.shadowDebugMode == ShadowMapDebugMode.None) return; using (var builder = renderGraph.AddRenderPass("RenderShadowsDebugOverlay", out var passData, ProfilingSampler.Get(HDProfileId.DisplayShadows))) { passData.debugOverlay = m_DebugOverlay; passData.colorBuffer = builder.UseColorBuffer(colorBuffer, 0); passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.Write); passData.lightingDebugSettings = m_CurrentDebugDisplaySettings.data.lightingDebugSettings; passData.shadowTextures = HDShadowManager.ReadShadowResult(shadowResult, builder); passData.shadowManager = m_ShadowManager; passData.debugSelectedLightShadowIndex = m_DebugSelectedLightShadowIndex; passData.debugSelectedLightShadowCount = m_DebugSelectedLightShadowCount; passData.debugShadowMapMaterial = m_DebugHDShadowMapMaterial; builder.SetRenderFunc( (RenderShadowsDebugOverlayPassData data, RenderGraphContext ctx) => { var lightingDebug = data.lightingDebugSettings; var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); Rect rect; switch (lightingDebug.shadowDebugMode) { case ShadowMapDebugMode.VisualizeShadowMap: int startShadowIndex = (int)lightingDebug.shadowMapIndex; int shadowRequestCount = 1; #if UNITY_EDITOR if (lightingDebug.shadowDebugUseSelection) { if (data.debugSelectedLightShadowIndex != -1 && data.debugSelectedLightShadowCount != 0) { startShadowIndex = data.debugSelectedLightShadowIndex; shadowRequestCount = data.debugSelectedLightShadowCount; } else { // We don't display any shadow map if the selected object is not a light shadowRequestCount = 0; } } #endif for (int shadowIndex = startShadowIndex; shadowIndex < startShadowIndex + shadowRequestCount; shadowIndex++) { rect = data.debugOverlay.Next(); data.shadowManager.DisplayShadowMap(data.shadowTextures, shadowIndex, ctx.cmd, data.debugShadowMapMaterial, rect.x, rect.y, rect.width, rect.height, lightingDebug.shadowMinValue, lightingDebug.shadowMaxValue, mpb); } break; case ShadowMapDebugMode.VisualizePunctualLightAtlas: rect = data.debugOverlay.Next(); data.shadowManager.DisplayShadowAtlas(data.shadowTextures.punctualShadowResult, ctx.cmd, data.debugShadowMapMaterial, rect.x, rect.y, rect.width, rect.height, lightingDebug.shadowMinValue, lightingDebug.shadowMaxValue, mpb); break; case ShadowMapDebugMode.VisualizeCachedPunctualLightAtlas: rect = data.debugOverlay.Next(); data.shadowManager.DisplayCachedPunctualShadowAtlas(data.shadowTextures.cachedPunctualShadowResult, ctx.cmd, data.debugShadowMapMaterial, rect.x, rect.y, rect.width, rect.height, lightingDebug.shadowMinValue, lightingDebug.shadowMaxValue, mpb); break; case ShadowMapDebugMode.VisualizeDirectionalLightAtlas: rect = data.debugOverlay.Next(); data.shadowManager.DisplayShadowCascadeAtlas(data.shadowTextures.directionalShadowResult, ctx.cmd, data.debugShadowMapMaterial, rect.x, rect.y, rect.width, rect.height, lightingDebug.shadowMinValue, lightingDebug.shadowMaxValue, mpb); break; case ShadowMapDebugMode.VisualizeAreaLightAtlas: rect = data.debugOverlay.Next(); data.shadowManager.DisplayAreaLightShadowAtlas(data.shadowTextures.areaShadowResult, ctx.cmd, data.debugShadowMapMaterial, rect.x, rect.y, rect.width, rect.height, lightingDebug.shadowMinValue, lightingDebug.shadowMaxValue, mpb); break; case ShadowMapDebugMode.VisualizeCachedAreaLightAtlas: rect = data.debugOverlay.Next(); data.shadowManager.DisplayCachedAreaShadowAtlas(data.shadowTextures.cachedAreaShadowResult, ctx.cmd, data.debugShadowMapMaterial, rect.x, rect.y, rect.width, rect.height, lightingDebug.shadowMinValue, lightingDebug.shadowMaxValue, mpb); break; default: break; } }); } } class RenderDecalOverlayPassData : DebugOverlayPassData { public int mipLevel; public HDCamera hdCamera; } void RenderDecalOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, HDCamera hdCamera) { if (!HDDebugDisplaySettings.Instance.decalSettings.displayAtlas) return; using (var builder = renderGraph.AddRenderPass("DecalOverlay", out var passData, ProfilingSampler.Get(HDProfileId.DisplayDebugDecalsAtlas))) { passData.debugOverlay = m_DebugOverlay; passData.colorBuffer = builder.UseColorBuffer(colorBuffer, 0); passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.mipLevel = (int)HDDebugDisplaySettings.Instance.decalSettings.mipLevel; passData.hdCamera = hdCamera; builder.SetRenderFunc( (RenderDecalOverlayPassData data, RenderGraphContext ctx) => { DecalSystem.instance.RenderDebugOverlay(data.hdCamera, ctx.cmd, data.mipLevel, data.debugOverlay); }); } } void RenderOcclusionOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, HDCamera hdCamera) { GPUResidentDrawer.RenderDebugOcclusionTestOverlay( renderGraph, HDDebugDisplaySettings.Instance?.gpuResidentDrawerSettings ?? null, hdCamera.camera.GetInstanceID(), colorBuffer); } void RenderOccluderDebugOverlay(RenderGraph renderGraph, TextureHandle colorBuffer, HDCamera hdCamera) { var debugSettings = HDDebugDisplaySettings.Instance?.gpuResidentDrawerSettings ?? null; if (debugSettings != null && debugSettings.occluderDebugViewEnable) { Rect rect = m_DebugOverlay.Next(); GPUResidentDrawer.RenderDebugOccluderOverlay( renderGraph, debugSettings, new Vector2(rect.x, rect.y), rect.height, colorBuffer); } } void RenderDebugOverlays(RenderGraph renderGraph, TextureHandle colorBuffer, TextureHandle depthBuffer, TextureHandle depthPyramidTexture, TextureHandle rayCountTexture, in BuildGPULightListOutput lightLists, in ShadowResult shadowResult, HDCamera hdCamera) { float overlayRatio = m_CurrentDebugDisplaySettings.data.debugOverlayRatio; int viewportWidth = (int)hdCamera.finalViewport.width; int viewportHeight = (int)hdCamera.finalViewport.height; int overlaySize = (int)((float)Math.Min(viewportWidth, viewportHeight) * overlayRatio); m_DebugOverlay.StartOverlay(HDUtils.GetRuntimeDebugPanelWidth(hdCamera), viewportHeight - overlaySize, overlaySize, viewportWidth); RenderSkyReflectionOverlay(renderGraph, colorBuffer, depthBuffer, hdCamera); RenderRayCountOverlay(renderGraph, hdCamera, colorBuffer, depthBuffer, rayCountTexture); if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.displayCookieAtlas) RenderAtlasDebugOverlay(renderGraph, colorBuffer, depthBuffer, m_TextureCaches.lightCookieManager.atlasTexture, 0, (int)m_CurrentDebugDisplaySettings.data.lightingDebugSettings.cookieAtlasMipLevel, applyExposure: false, "RenderCookieAtlasOverlay", HDProfileId.DisplayCookieAtlas); if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.displayReflectionProbeAtlas) RenderAtlasDebugOverlay(renderGraph, colorBuffer, depthBuffer, m_TextureCaches.reflectionProbeTextureCache.GetAtlasTexture(), (int)m_CurrentDebugDisplaySettings.data.lightingDebugSettings.reflectionProbeSlice, (int)m_CurrentDebugDisplaySettings.data.lightingDebugSettings.reflectionProbeMipLevel, applyExposure: m_CurrentDebugDisplaySettings.data.lightingDebugSettings.reflectionProbeApplyExposure, "RenderReflectionProbeAtlasOverlay", HDProfileId.DisplayReflectionProbeAtlas); RenderTileClusterDebugOverlay(renderGraph, colorBuffer, depthBuffer, lightLists, depthPyramidTexture, hdCamera); RenderShadowsDebugOverlay(renderGraph, colorBuffer, depthBuffer, shadowResult); RenderDecalOverlay(renderGraph, colorBuffer, depthBuffer, hdCamera); RenderMonitorsOverlay(renderGraph, colorBuffer, hdCamera); ProbeReferenceVolume.instance.RenderFragmentationOverlay(renderGraph, colorBuffer, depthBuffer, m_DebugOverlay); RenderOcclusionOverlay(renderGraph, colorBuffer, hdCamera); RenderOccluderDebugOverlay(renderGraph, colorBuffer, hdCamera); } void RenderLightVolumes(RenderGraph renderGraph, TextureHandle destination, TextureHandle depthBuffer, CullingResults cullResults, HDCamera hdCamera) { if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.displayLightVolumes) { s_lightVolumes.RenderLightVolumes(renderGraph, m_CurrentDebugDisplaySettings.data.lightingDebugSettings, destination, depthBuffer, cullResults, hdCamera); } } class DebugImageHistogramData { public ComputeShader debugImageHistogramCS; public ComputeBuffer imageHistogram; public int debugImageHistogramKernel; public int cameraWidth; public int cameraHeight; public TextureHandle source; } void GenerateDebugImageHistogram(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle source) { if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.exposureDebugMode != ExposureDebugMode.FinalImageHistogramView) return; using (var builder = renderGraph.AddRenderPass("Generate Debug Image Histogram", out var passData, ProfilingSampler.Get(HDProfileId.FinalImageHistogram))) { ValidateComputeBuffer(ref m_DebugImageHistogramBuffer, k_DebugImageHistogramBins, 4 * sizeof(uint)); m_DebugImageHistogramBuffer.SetData(m_EmptyDebugImageHistogram); // Clear the histogram passData.debugImageHistogramCS = runtimeShaders.debugImageHistogramCS; passData.debugImageHistogramKernel = passData.debugImageHistogramCS.FindKernel("KHistogramGen"); passData.imageHistogram = m_DebugImageHistogramBuffer; passData.cameraWidth = postProcessViewportSize.x; passData.cameraHeight = postProcessViewportSize.y; passData.source = builder.ReadTexture(source); builder.SetRenderFunc( (DebugImageHistogramData data, RenderGraphContext ctx) => { ctx.cmd.SetComputeTextureParam(data.debugImageHistogramCS, data.debugImageHistogramKernel, HDShaderIDs._SourceTexture, data.source); ctx.cmd.SetComputeBufferParam(data.debugImageHistogramCS, data.debugImageHistogramKernel, HDShaderIDs._HistogramBuffer, data.imageHistogram); int threadGroupSizeX = 16; int threadGroupSizeY = 16; int dispatchSizeX = HDUtils.DivRoundUp(data.cameraWidth / 2, threadGroupSizeX); int dispatchSizeY = HDUtils.DivRoundUp(data.cameraHeight / 2, threadGroupSizeY); int totalPixels = data.cameraWidth * data.cameraHeight; ctx.cmd.DispatchCompute(data.debugImageHistogramCS, data.debugImageHistogramKernel, dispatchSizeX, dispatchSizeY, 1); }); } } class GenerateHDRDebugData { public ComputeShader generateXYMappingCS; public TextureHandle xyBuffer; public int debugXYGenKernel; public int cameraWidth; public int cameraHeight; public Vector4 debugParameters; public TextureHandle source; } TextureHandle GenerateDebugHDRxyMapping(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle source) { if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.hdrDebugMode == HDRDebugMode.None) return TextureHandle.nullHandle; using (var builder = renderGraph.AddRenderPass("Generate HDR debug data", out var passData, ProfilingSampler.Get(HDProfileId.HDRDebugData))) { passData.generateXYMappingCS = runtimeShaders.debugHDRxyMappingCS; passData.debugXYGenKernel = passData.generateXYMappingCS.FindKernel("KCIExyGen"); passData.cameraWidth = postProcessViewportSize.x; passData.cameraHeight = postProcessViewportSize.y; passData.source = builder.ReadTexture(source); passData.xyBuffer = builder.ReadWriteTexture(renderGraph.CreateTexture(new TextureDesc(k_SizeOfHDRXYMapping, k_SizeOfHDRXYMapping, true, true) { format = GraphicsFormat.R32_SFloat, enableRandomWrite = true, clearBuffer = true, name = "HDR_xyMapping" })); ColorGamut gamut = HDROutputActiveForCameraType(hdCamera) ? HDRDisplayColorGamutForCamera(hdCamera) : ColorGamut.Rec709; HDROutputUtils.ConfigureHDROutput(passData.generateXYMappingCS, gamut, HDROutputUtils.Operation.ColorConversion); passData.debugParameters = new Vector4(k_SizeOfHDRXYMapping, k_SizeOfHDRXYMapping, 0, 0); builder.SetRenderFunc( (GenerateHDRDebugData data, RenderGraphContext ctx) => { ctx.cmd.SetComputeTextureParam(data.generateXYMappingCS, data.debugXYGenKernel, HDShaderIDs._SourceTexture, data.source); ctx.cmd.SetComputeVectorParam(data.generateXYMappingCS, HDShaderIDs._HDRxyBufferDebugParams, data.debugParameters); ctx.cmd.SetComputeTextureParam(data.generateXYMappingCS, data.debugXYGenKernel, HDShaderIDs._xyBuffer, data.xyBuffer); int threadGroupSizeX = 8; int threadGroupSizeY = 8; int dispatchSizeX = HDUtils.DivRoundUp(data.cameraWidth, threadGroupSizeX); int dispatchSizeY = HDUtils.DivRoundUp(data.cameraHeight, threadGroupSizeY); int totalPixels = data.cameraWidth * data.cameraHeight; ctx.cmd.DispatchCompute(data.generateXYMappingCS, data.debugXYGenKernel, dispatchSizeX, dispatchSizeY, 1); }); source = passData.xyBuffer; } return source; } class DebugHDRData { public LightingDebugSettings lightingDebugSettings; public Material debugHDRMaterial; public Vector4 hdrOutputParams; public Vector4 hdrOutputParams2; public Vector4 hdrDebugParams; public int debugPass; public BufferHandle xyMappingBuffer; public TextureHandle colorBuffer; public TextureHandle xyTexture; public TextureHandle debugFullScreenTexture; public TextureHandle output; } TextureHandle RenderHDRDebug(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer, TextureHandle xyBuff) { using (var builder = renderGraph.AddRenderPass("Debug HDR", out var passData)) { passData.debugHDRMaterial = m_DebugHDROutput; passData.lightingDebugSettings = m_CurrentDebugDisplaySettings.data.lightingDebugSettings; if (HDROutputActiveForCameraType(hdCamera)) GetHDROutputParameters(HDRDisplayInformationForCamera(hdCamera), HDRDisplayColorGamutForCamera(hdCamera), hdCamera.volumeStack.GetComponent(), out passData.hdrOutputParams, out passData.hdrOutputParams2); else passData.hdrOutputParams.z = 1.0f; passData.debugPass = (int)m_CurrentDebugDisplaySettings.data.lightingDebugSettings.hdrDebugMode - 1; passData.colorBuffer = builder.ReadTexture(colorBuffer); passData.debugFullScreenTexture = builder.ReadTexture(m_DebugFullScreenTexture); passData.output = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, name = "HDRDebug" })); passData.hdrDebugParams = new Vector4(k_SizeOfHDRXYMapping, k_SizeOfHDRXYMapping, 0, 0); passData.xyTexture = builder.ReadTexture(xyBuff); passData.debugHDRMaterial.enabledKeywords = null; if (HDROutputActiveForCameraType(hdCamera)) { HDROutputUtils.ConfigureHDROutput(passData.debugHDRMaterial, HDRDisplayColorGamutForCamera(hdCamera), HDROutputUtils.Operation.ColorConversion); } builder.SetRenderFunc( (DebugHDRData data, RenderGraphContext ctx) => { data.debugHDRMaterial.SetTexture(HDShaderIDs._DebugFullScreenTexture, data.debugFullScreenTexture); data.debugHDRMaterial.SetTexture(HDShaderIDs._xyBuffer, data.xyTexture); data.debugHDRMaterial.SetVector(HDShaderIDs._HDROutputParams, data.hdrOutputParams); data.debugHDRMaterial.SetVector(HDShaderIDs._HDROutputParams2, data.hdrOutputParams2); data.debugHDRMaterial.SetVector(HDShaderIDs._HDRDebugParams, data.hdrDebugParams); HDUtils.DrawFullScreen(ctx.cmd, data.debugHDRMaterial, data.output, null, data.debugPass); }); return passData.output; } } class DebugExposureData { public LightingDebugSettings lightingDebugSettings; public HDCamera hdCamera; public Material debugExposureMaterial; public Vector4 proceduralMeteringParams1; public Vector4 proceduralMeteringParams2; public TextureHandle colorBuffer; public TextureHandle debugFullScreenTexture; public TextureHandle output; public TextureHandle currentExposure; public TextureHandle previousExposure; public TextureHandle debugExposureData; public HableCurve customToneMapCurve; public int lutSize; public ComputeBuffer histogramBuffer; } TextureHandle RenderExposureDebug(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer) { using (var builder = renderGraph.AddRenderPass("Debug Exposure", out var passData)) { ComputeProceduralMeteringParams(hdCamera, out passData.proceduralMeteringParams1, out passData.proceduralMeteringParams2); passData.lightingDebugSettings = m_CurrentDebugDisplaySettings.data.lightingDebugSettings; passData.hdCamera = hdCamera; passData.debugExposureMaterial = m_DebugExposure; passData.colorBuffer = builder.ReadTexture(colorBuffer); passData.debugFullScreenTexture = builder.ReadTexture(m_DebugFullScreenTexture); passData.output = builder.WriteTexture(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, name = "ExposureDebug" })); passData.currentExposure = builder.ReadTexture(renderGraph.ImportTexture(GetExposureTexture(hdCamera))); passData.previousExposure = builder.ReadTexture(renderGraph.ImportTexture(GetPreviousExposureTexture(hdCamera))); passData.debugExposureData = builder.ReadTexture(renderGraph.ImportTexture(GetExposureDebugData())); passData.customToneMapCurve = GetCustomToneMapCurve(); passData.lutSize = GetLutSize(); passData.histogramBuffer = passData.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView ? GetDebugImageHistogramBuffer() : GetHistogramBuffer(); builder.SetRenderFunc( (DebugExposureData data, RenderGraphContext ctx) => { // Grab exposure parameters var exposureSettings = data.hdCamera.volumeStack.GetComponent(); Vector4 exposureParams = new Vector4(exposureSettings.compensation.value + data.lightingDebugSettings.debugExposure, exposureSettings.limitMin.value, exposureSettings.limitMax.value, 0f); Vector4 exposureVariants = new Vector4(1.0f, (int)exposureSettings.meteringMode.value, (int)exposureSettings.adaptationMode.value, 0.0f); Vector2 histogramFraction = exposureSettings.histogramPercentages.value / 100.0f; float evRange = exposureSettings.limitMax.value - exposureSettings.limitMin.value; float histScale = 1.0f / Mathf.Max(1e-5f, evRange); float histBias = -exposureSettings.limitMin.value * histScale; Vector4 histogramParams = new Vector4(histScale, histBias, histogramFraction.x, histogramFraction.y); data.debugExposureMaterial.SetVector(HDShaderIDs._ProceduralMaskParams, data.proceduralMeteringParams1); data.debugExposureMaterial.SetVector(HDShaderIDs._ProceduralMaskParams2, data.proceduralMeteringParams2); data.debugExposureMaterial.SetVector(HDShaderIDs._HistogramExposureParams, histogramParams); data.debugExposureMaterial.SetVector(HDShaderIDs._Variants, exposureVariants); data.debugExposureMaterial.SetVector(HDShaderIDs._ExposureParams, exposureParams); data.debugExposureMaterial.SetVector(HDShaderIDs._ExposureParams2, new Vector4(0.0f, 0.0f, ColorUtils.lensImperfectionExposureScale, ColorUtils.s_LightMeterCalibrationConstant)); data.debugExposureMaterial.SetVector(HDShaderIDs._MousePixelCoord, HDUtils.GetMouseCoordinates(data.hdCamera)); data.debugExposureMaterial.SetTexture(HDShaderIDs._SourceTexture, data.colorBuffer); data.debugExposureMaterial.SetTexture(HDShaderIDs._DebugFullScreenTexture, data.debugFullScreenTexture); data.debugExposureMaterial.SetTexture(HDShaderIDs._PreviousExposureTexture, data.previousExposure); data.debugExposureMaterial.SetTexture(HDShaderIDs._ExposureTexture, data.currentExposure); data.debugExposureMaterial.SetTexture(HDShaderIDs._ExposureWeightMask, exposureSettings.weightTextureMask.value); data.debugExposureMaterial.SetBuffer(HDShaderIDs._HistogramBuffer, data.histogramBuffer); int passIndex = 0; if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.MeteringWeighted) { passIndex = 1; data.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(data.lightingDebugSettings.displayMaskOnly ? 1 : 0, 0, 0, 0)); } if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.HistogramView) { data.debugExposureMaterial.SetTexture(HDShaderIDs._ExposureDebugTexture, data.debugExposureData); var tonemappingSettings = data.hdCamera.volumeStack.GetComponent(); bool toneMapIsEnabled = data.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Tonemapping); var tonemappingMode = toneMapIsEnabled ? tonemappingSettings.mode.value : TonemappingMode.None; bool drawTonemapCurve = tonemappingMode != TonemappingMode.None && data.lightingDebugSettings.showTonemapCurveAlongHistogramView; bool centerAroundMiddleGrey = data.lightingDebugSettings.centerHistogramAroundMiddleGrey; bool displayOverlay = data.lightingDebugSettings.displayOnSceneOverlay; data.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(drawTonemapCurve ? 1.0f : 0.0f, (int)tonemappingMode, centerAroundMiddleGrey ? 1 : 0, displayOverlay ? 1 : 0)); if (drawTonemapCurve) { if (tonemappingMode == TonemappingMode.Custom) { data.debugExposureMaterial.SetVector(HDShaderIDs._CustomToneCurve, data.customToneMapCurve.uniforms.curve); data.debugExposureMaterial.SetVector(HDShaderIDs._ToeSegmentA, data.customToneMapCurve.uniforms.toeSegmentA); data.debugExposureMaterial.SetVector(HDShaderIDs._ToeSegmentB, data.customToneMapCurve.uniforms.toeSegmentB); data.debugExposureMaterial.SetVector(HDShaderIDs._MidSegmentA, data.customToneMapCurve.uniforms.midSegmentA); data.debugExposureMaterial.SetVector(HDShaderIDs._MidSegmentB, data.customToneMapCurve.uniforms.midSegmentB); data.debugExposureMaterial.SetVector(HDShaderIDs._ShoSegmentA, data.customToneMapCurve.uniforms.shoSegmentA); data.debugExposureMaterial.SetVector(HDShaderIDs._ShoSegmentB, data.customToneMapCurve.uniforms.shoSegmentB); } } else if (tonemappingMode == TonemappingMode.External) { data.debugExposureMaterial.SetTexture(HDShaderIDs._LogLut3D, tonemappingSettings.lutTexture.value); data.debugExposureMaterial.SetVector(HDShaderIDs._LogLut3D_Params, new Vector4(1f / data.lutSize, data.lutSize - 1f, tonemappingSettings.lutContribution.value, 0f)); } passIndex = 2; } if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView) { bool finalImageRGBHisto = data.lightingDebugSettings.displayFinalImageHistogramAsRGB; data.debugExposureMaterial.SetVector(HDShaderIDs._ExposureDebugParams, new Vector4(0, 0, 0, finalImageRGBHisto ? 1 : 0)); data.debugExposureMaterial.SetBuffer(HDShaderIDs._FullImageHistogram, data.histogramBuffer); passIndex = 3; } HDUtils.DrawFullScreen(ctx.cmd, data.debugExposureMaterial, data.output, null, passIndex); }); return passData.output; } } TextureHandle RenderDebug(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle colorBuffer, TextureHandle depthBuffer, TextureHandle depthPyramidTexture, TextureHandle colorPickerDebugTexture, TextureHandle rayCountTexture, TextureHandle xyBufferMapping, in BuildGPULightListOutput lightLists, in ShadowResult shadowResult, CullingResults cullResults, GraphicsFormat colorFormat) { // We don't want any overlay for these kind of rendering if (hdCamera.camera.cameraType == CameraType.Reflection || hdCamera.camera.cameraType == CameraType.Preview) return colorBuffer; TextureHandle output = colorBuffer; if (NeedsFullScreenDebugMode() && m_FullScreenDebugPushed) { output = ResolveFullScreenDebug(renderGraph, m_DebugFullScreenTexture, depthPyramidTexture, hdCamera, colorFormat); // If we have full screen debug, this is what we want color picked, so we replace color picker input texture with the new one. if (NeedColorPickerDebug(m_CurrentDebugDisplaySettings)) colorPickerDebugTexture = PushColorPickerDebugTexture(renderGraph, output); m_FullScreenDebugPushed = false; m_DebugFullScreenComputeBuffer = BufferHandle.nullHandle; } if (NeedExposureDebugMode(m_CurrentDebugDisplaySettings)) output = RenderExposureDebug(renderGraph, hdCamera, colorBuffer); if (NeedHDRDebugMode(m_CurrentDebugDisplaySettings)) output = RenderHDRDebug(renderGraph, hdCamera, colorBuffer, xyBufferMapping); if (NeedColorPickerDebug(m_CurrentDebugDisplaySettings)) output = ResolveColorPickerDebug(renderGraph, colorPickerDebugTexture, hdCamera, colorFormat); RenderLightVolumes(renderGraph, output, depthBuffer, cullResults, hdCamera); RenderDebugOverlays(renderGraph, output, depthBuffer, depthPyramidTexture, rayCountTexture, lightLists, shadowResult, hdCamera); return output; } void RenderProbeVolumeDebug(RenderGraph renderGraph, HDCamera hdCamera, TextureHandle depthPyramidBuffer, TextureHandle normalBuffer) { if (apvIsEnabled && ProbeReferenceVolume.instance.GetProbeSamplingDebugResources(hdCamera.camera, out var resultBuffer, out Vector2 coords)) WriteApvPositionNormalDebugBuffer(renderGraph, resultBuffer, coords, depthPyramidBuffer, normalBuffer); } class WriteApvData { public ComputeShader computeShader; public BufferHandle resultBuffer; public Vector2 clickCoordinates; public TextureHandle depthBuffer; public TextureHandle normalBuffer; } // Compute worldspace position and normal at given screenspace clickCoordinates, and write it into given ResultBuffer. void WriteApvPositionNormalDebugBuffer(RenderGraph renderGraph, GraphicsBuffer resultBuffer, Vector2 clickCoordinates, TextureHandle depthBuffer, TextureHandle normalBuffer) { using (var builder = renderGraph.AddRenderPass("APV Debug Sampling", out var passData, ProfilingSampler.Get(HDProfileId.APVSamplingDebug))) { passData.resultBuffer = builder.WriteBuffer(renderGraph.ImportBuffer(resultBuffer)); passData.clickCoordinates = clickCoordinates; passData.depthBuffer = builder.ReadTexture(depthBuffer); passData.normalBuffer = builder.ReadTexture(normalBuffer); passData.computeShader = m_ComputePositionNormal; builder.SetRenderFunc( (WriteApvData data, RenderGraphContext ctx) => { int kernelHandle = data.computeShader.FindKernel("ComputePositionNormal"); ctx.cmd.SetComputeTextureParam(data.computeShader, kernelHandle, "_CameraDepthTexture", data.depthBuffer); ctx.cmd.SetComputeTextureParam(data.computeShader, kernelHandle, "_NormalBufferTexture", data.normalBuffer); ctx.cmd.SetComputeVectorParam(data.computeShader, "_positionSS", new Vector4(data.clickCoordinates.x, data.clickCoordinates.y, 0.0f, 0.0f)); ctx.cmd.SetComputeBufferParam(data.computeShader, kernelHandle, "_ResultBuffer", data.resultBuffer); ctx.cmd.DispatchCompute(data.computeShader, kernelHandle, 1, 1, 1); }); } } class DebugViewMaterialData { public TextureHandle outputColor; public TextureHandle outputDepth; public RendererListHandle opaqueRendererList; public RendererListHandle transparentRendererList; public Material debugGBufferMaterial; public FrameSettings frameSettings; public bool decalsEnabled; public BufferHandle perVoxelOffset; public DBufferOutput dbuffer; public GBufferOutput gbuffer; public TextureHandle depthBuffer; public Texture clearColorTexture; public RenderTexture clearDepthTexture; public bool clearDepth; } TextureHandle RenderDebugViewMaterial(RenderGraph renderGraph, CullingResults cull, HDCamera hdCamera, BuildGPULightListOutput lightLists, DBufferOutput dbuffer, GBufferOutput gbuffer, TextureHandle depthBuffer, TextureHandle vtFeedbackBuffer) { bool msaa = hdCamera.msaaEnabled; var output = renderGraph.CreateTexture( new TextureDesc(Vector2.one, true, true) { format = GetColorBufferFormat(), enableRandomWrite = !msaa, bindTextureMS = msaa, msaaSamples = hdCamera.msaaSamples, clearBuffer = true, clearColor = Color.clear, name = msaa ? "CameraColorMSAA" : "CameraColor" }); if (m_CurrentDebugDisplaySettings.data.materialDebugSettings.IsDebugGBufferEnabled() && hdCamera.frameSettings.litShaderMode == LitShaderMode.Deferred) { using (var builder = renderGraph.AddRenderPass("DebugViewMaterialGBuffer", out var passData, ProfilingSampler.Get(HDProfileId.DebugViewMaterialGBuffer))) { passData.debugGBufferMaterial = m_currentDebugViewMaterialGBuffer; passData.outputColor = builder.WriteTexture(output); passData.gbuffer = ReadGBuffer(gbuffer, builder); passData.depthBuffer = builder.ReadTexture(depthBuffer); builder.SetRenderFunc( (DebugViewMaterialData data, RenderGraphContext context) => { var gbufferHandles = data.gbuffer; for (int i = 0; i < gbufferHandles.gBufferCount; ++i) { data.debugGBufferMaterial.SetTexture(HDShaderIDs._GBufferTexture[i], gbufferHandles.mrt[i]); } data.debugGBufferMaterial.SetTexture(HDShaderIDs._CameraDepthTexture, data.depthBuffer); HDUtils.DrawFullScreen(context.cmd, data.debugGBufferMaterial, data.outputColor); }); } } else { // Create the depth texture that will be used for the display debug TextureHandle depth = CreateDepthBuffer(renderGraph, true, hdCamera.msaaSamples); // Render the debug water m_WaterSystem.RenderWaterDebug(renderGraph, hdCamera, output, depth); // Render the debug lines. RenderLines(renderGraph, depthBuffer, hdCamera, lightLists); ComposeLines(renderGraph, hdCamera, output, depth, TextureHandle.nullHandle, -1); using (var builder = renderGraph.AddRenderPass("DisplayDebug ViewMaterial", out var passData, ProfilingSampler.Get(HDProfileId.DisplayDebugViewMaterial))) { passData.frameSettings = hdCamera.frameSettings; passData.outputColor = builder.UseColorBuffer(output, 0); #if ENABLE_VIRTUALTEXTURES builder.UseColorBuffer(vtFeedbackBuffer, 1); #endif passData.outputDepth = builder.UseDepthBuffer(depth, DepthAccess.ReadWrite); // When rendering debug material we shouldn't rely on a depth prepass for optimizing the alpha clip test. As it is control on the material inspector side // we must override the state here. passData.opaqueRendererList = builder.UseRendererList( renderGraph.CreateRendererList(CreateOpaqueRendererListDesc(cull, hdCamera.camera, m_AllForwardOpaquePassNames, rendererConfiguration: m_CurrentRendererConfigurationBakedLighting, stateBlock: m_DepthStateOpaque))); passData.transparentRendererList = builder.UseRendererList( renderGraph.CreateRendererList(CreateTransparentRendererListDesc(cull, hdCamera.camera, m_AllTransparentPassNames, rendererConfiguration: m_CurrentRendererConfigurationBakedLighting, stateBlock: m_DepthStateNoWrite))); passData.decalsEnabled = (hdCamera.frameSettings.IsEnabled(FrameSettingsField.Decals)) && (DecalSystem.m_DecalDatasCount > 0); passData.perVoxelOffset = builder.ReadBuffer(lightLists.perVoxelOffset); passData.dbuffer = ReadDBuffer(dbuffer, builder); passData.clearColorTexture = Compositor.CompositionManager.GetClearTextureForStackedCamera(hdCamera); // returns null if is not a stacked camera passData.clearDepthTexture = Compositor.CompositionManager.GetClearDepthForStackedCamera(hdCamera); // returns null if is not a stacked camera passData.clearDepth = hdCamera.clearDepth; builder.SetRenderFunc( (DebugViewMaterialData data, RenderGraphContext context) => { // If we are doing camera stacking, then we want to clear the debug color and depth buffer using the data from the previous camera on the stack // Note: Ideally here we would like to draw directly on the same buffers as the previous camera, but currently the compositor is not using // Texture Arrays so this would not work. We might need to revise this in the future. if (data.clearColorTexture != null) { HDUtils.BlitColorAndDepth(context.cmd, data.clearColorTexture, data.clearDepthTexture, new Vector4(1, 1, 0, 0), 0, !data.clearDepth); } BindDefaultTexturesLightingBuffers(context.defaultResources, context.cmd); BindDBufferGlobalData(data.dbuffer, context); DrawOpaqueRendererList(context, data.frameSettings, data.opaqueRendererList); if (data.decalsEnabled) DecalSystem.instance.SetAtlas(context.cmd); // for clustered decals if (data.perVoxelOffset.IsValid()) context.cmd.SetGlobalBuffer(HDShaderIDs.g_vLayeredOffsetsBuffer, data.perVoxelOffset); DrawTransparentRendererList(context, data.frameSettings, data.transparentRendererList); }); } } return output; } class PushFullScreenDebugPassData { public TextureHandle input; public TextureHandle output; public int mipIndex; public bool xrTexture; public bool useCustomScaleBias; public Vector4 customScaleBias; } void PushFullScreenLightingDebugTexture(RenderGraph renderGraph, TextureHandle input, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat) { // In practice, this is only useful for the SingleShadow debug view. // TODO: See how we can make this nicer than a specific functions just for one case. if (NeedsFullScreenDebugMode() && m_FullScreenDebugPushed == false) { PushFullScreenDebugTexture(renderGraph, input, colorFormat); } } internal void PushFullScreenDebugTexture(RenderGraph renderGraph, TextureHandle input, FullScreenDebugMode debugMode, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat, bool xrTexture = true) { if (debugMode == m_CurrentDebugDisplaySettings.data.fullScreenDebugMode) { PushFullScreenDebugTexture(renderGraph, input, colorFormat, xrTexture: xrTexture); } } internal void PushFullScreenDebugTexture(RenderGraph renderGraph, TextureHandle input, Vector2 scales, FullScreenDebugMode debugMode, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat, bool xrTexture = true) { if (debugMode == m_CurrentDebugDisplaySettings.data.fullScreenDebugMode) { PushFullScreenDebugTexture(renderGraph, input, true, scales, colorFormat, xrTexture: xrTexture); } } void PushFullScreenDebugTextureMip(RenderGraph renderGraph, TextureHandle input, int lodCount, Vector4 scaleBias, FullScreenDebugMode debugMode, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat) { if (debugMode == m_CurrentDebugDisplaySettings.data.fullScreenDebugMode) { var mipIndex = Mathf.FloorToInt(m_CurrentDebugDisplaySettings.data.fullscreenDebugMip * lodCount); PushFullScreenDebugTexture(renderGraph, input, colorFormat, mipIndex); } } void PushFullScreenHistoryBuffer(RenderGraph renderGraph, TextureHandle input, HDCameraFrameHistoryType historyType, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat) { PushFullScreenDebugTexture(renderGraph, input, colorFormat); } void PushFullScreenDebugTexture(RenderGraph renderGraph, TextureHandle input, GraphicsFormat rtFormat = GraphicsFormat.R16G16B16A16_SFloat, int mipIndex = -1, bool xrTexture = true) { PushFullScreenDebugTexture(renderGraph, input, false, new Vector2(1.0f, 1.0f), rtFormat, mipIndex, xrTexture); } void PushFullScreenDebugTexture(RenderGraph renderGraph, TextureHandle input, bool useCustomScaleBias, Vector2 customScales, GraphicsFormat rtFormat = GraphicsFormat.R16G16B16A16_SFloat, int mipIndex = -1, bool xrTexture = true) { using (var builder = renderGraph.AddRenderPass("Push Full Screen Debug", out var passData)) { passData.mipIndex = mipIndex; passData.xrTexture = xrTexture; passData.input = builder.ReadTexture(input); passData.useCustomScaleBias = false; if (useCustomScaleBias) { passData.useCustomScaleBias = true; passData.customScaleBias = new Vector4(customScales.x, customScales.y, 0.0f, 0.0f); } passData.output = builder.UseColorBuffer(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = rtFormat, name = "DebugFullScreen" }), 0); builder.SetRenderFunc( (PushFullScreenDebugPassData data, RenderGraphContext ctx) => { if (data.useCustomScaleBias) { if (data.xrTexture) { if (data.mipIndex != -1) HDUtils.BlitCameraTexture(ctx.cmd, data.input, data.output, data.customScaleBias, data.mipIndex); else HDUtils.BlitCameraTexture(ctx.cmd, data.input, data.output, data.customScaleBias); } else { CoreUtils.SetRenderTarget(ctx.cmd, data.output); if (data.mipIndex != -1) HDUtils.BlitTexture2D(ctx.cmd, data.input, data.customScaleBias, data.mipIndex, false); else HDUtils.BlitTexture2D(ctx.cmd, data.input, data.customScaleBias, 0.0f, false); } } else { if (data.xrTexture) { if (data.mipIndex != -1) HDUtils.BlitCameraTexture(ctx.cmd, data.input, data.output, data.mipIndex); else HDUtils.BlitCameraTexture(ctx.cmd, data.input, data.output); } else { if (data.mipIndex != -1) HDUtils.BlitCameraTexture2D(ctx.cmd, data.input, data.output, data.mipIndex); else HDUtils.BlitCameraTexture2D(ctx.cmd, data.input, data.output); } } }); m_DebugFullScreenTexture = passData.output; } // We need this flag because otherwise if no full screen debug is pushed (like for example if the corresponding pass is disabled), when we render the result in RenderDebug m_DebugFullScreenTempBuffer will contain potential garbage m_FullScreenDebugPushed = true; } void PushFullScreenExposureDebugTexture(RenderGraph renderGraph, TextureHandle input, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat) { if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.exposureDebugMode != ExposureDebugMode.None) { PushFullScreenDebugTexture(renderGraph, input, colorFormat); } } void PushFullScreenHDRDebugTexture(RenderGraph renderGraph, TextureHandle input, GraphicsFormat colorFormat = GraphicsFormat.R16G16B16A16_SFloat) { if (m_CurrentDebugDisplaySettings.data.lightingDebugSettings.hdrDebugMode != HDRDebugMode.None) { PushFullScreenDebugTexture(renderGraph, input, colorFormat); } } #if ENABLE_VIRTUALTEXTURES class PushFullScreenVTDebugPassData { public TextureHandle input; public TextureHandle output; public Material material; public bool msaa; } void PushFullScreenVTFeedbackDebugTexture(RenderGraph renderGraph, TextureHandle input, bool msaa) { if (FullScreenDebugMode.RequestedVirtualTextureTiles == m_CurrentDebugDisplaySettings.data.fullScreenDebugMode) { using (var builder = renderGraph.AddRenderPass("Push Full Screen Debug", out var passData)) { passData.material = m_VTDebugBlit; passData.msaa = msaa; passData.input = builder.ReadTexture(input); passData.output = builder.UseColorBuffer(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, name = "DebugFullScreen" }), 0); builder.SetRenderFunc( (PushFullScreenVTDebugPassData data, RenderGraphContext ctx) => { CoreUtils.SetRenderTarget(ctx.cmd, data.output); data.material.SetTexture(data.msaa ? HDShaderIDs._BlitTextureMSAA : HDShaderIDs._BlitTexture, data.input); ctx.cmd.DrawProcedural(Matrix4x4.identity, data.material, data.msaa ? 1 : 0, MeshTopology.Triangles, 3, 1); }); m_DebugFullScreenTexture = passData.output; } m_FullScreenDebugPushed = true; } } #endif TextureHandle PushColorPickerDebugTexture(RenderGraph renderGraph, TextureHandle input) { using (var builder = renderGraph.AddRenderPass("Push To Color Picker", out var passData)) { passData.input = builder.ReadTexture(input); passData.output = builder.UseColorBuffer(renderGraph.CreateTexture(new TextureDesc(Vector2.one, true, true) { format = GraphicsFormat.R16G16B16A16_SFloat, name = "DebugColorPicker" }), 0); builder.SetRenderFunc( (PushFullScreenDebugPassData data, RenderGraphContext ctx) => { HDUtils.BlitCameraTexture(ctx.cmd, data.input, data.output); }); return passData.output; } } } }