using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine.Rendering.HighDefinition.Attributes; namespace UnityEngine.Rendering.HighDefinition { [GenerateHLSL(needAccessors = false, generateCBuffer = true)] unsafe struct ShaderVariablesDebugDisplay { [HLSLArray(32, typeof(Vector4))] public fixed float _DebugRenderingLayersColors[32 * 4]; [HLSLArray(11, typeof(ShaderGenUInt4))] public fixed uint _DebugViewMaterialArray[11 * 4]; // Contain the id (define in various materialXXX.cs.hlsl) of the property to display public int _DebugLightingMode; // Match enum DebugLightingMode public int _DebugLightLayersMask; public int _DebugShadowMapMode; public int _DebugMipMapMode; // Match enum DebugMipMapMode public int _DebugFullScreenMode; public float _DebugTransparencyOverdrawWeight; public int _DebugMipMapModeTerrainTexture; // Match enum DebugMipMapModeTerrainTexture public int _ColorPickerMode; // Match enum ColorPickerDebugMode public Vector4 _DebugLightingAlbedo; // x == bool override, yzw = albedo for diffuse public Vector4 _DebugLightingSmoothness; // x == bool override, y == override value public Vector4 _DebugLightingNormal; // x == bool override public Vector4 _DebugLightingAmbientOcclusion; // x == bool override, y == override value public Vector4 _DebugLightingSpecularColor; // x == bool override, yzw = specular color public Vector4 _DebugLightingEmissiveColor; // x == bool override, yzw = emissive color public Vector4 _DebugLightingMaterialValidateHighColor; // user can specific the colors for the validator error conditions public Vector4 _DebugLightingMaterialValidateLowColor; public Vector4 _DebugLightingMaterialValidatePureMetalColor; public Vector4 _MousePixelCoord; // xy unorm, zw norm public Vector4 _MouseClickPixelCoord; // xy unorm, zw norm public int _MatcapMixAlbedo; public float _MatcapViewScale; public int _DebugSingleShadowIndex; public int _DebugProbeVolumeMode; public int _DebugAOVOutput; public int _DebugDisplayPad0; public int _DebugDisplayPad1; } /// /// Full Screen Debug Mode. /// [GenerateHLSL] public enum FullScreenDebugMode { /// No Full Screen debug mode. None, // Lighting /// Minimum Full Screen Lighting debug mode value (used internally). MinLightingFullScreenDebug, /// Display Screen Space Ambient Occlusion buffer. ScreenSpaceAmbientOcclusion, /// Display Screen Space Reflections buffer used for lighting. ScreenSpaceReflections, /// Display the Transparent Screen Space Reflections buffer. TransparentScreenSpaceReflections, /// Display Contact Shadows buffer. ContactShadows, /// Display Contact Shadows fade. ContactShadowsFade, /// Display Screen Space Shadows. ScreenSpaceShadows, /// Displays the color pyramid before the refraction pass. PreRefractionColorPyramid, /// Display the Depth Pyramid. DepthPyramid, /// Display the final color pyramid for the frame. FinalColorPyramid, // Raytracing Only /// Display ray tracing light cluster. LightCluster, /// Display screen space global illumination. ScreenSpaceGlobalIllumination, /// Display recursive ray tracing. RecursiveRayTracing, /// Display ray-traced sub-surface scattering. RayTracedSubSurface, /// Maximum Full Screen Lighting debug mode value (used internally). MaxLightingFullScreenDebug, // Rendering /// Minimum Full Screen Rendering debug mode value (used internally). MinRenderingFullScreenDebug, /// Display Motion Vectors. MotionVectors, /// Display NaNs. NanTracker, /// Display Log of the color buffer. ColorLog, /// Display Depth of Field circle of confusion. DepthOfFieldCoc, /// Display Transparency Overdraw. TransparencyOverdraw, /// Display Quad Overdraw. QuadOverdraw, /// Display Vertex Density. VertexDensity, /// Display Requested Virtual Texturing tiles, colored by the mip RequestedVirtualTextureTiles, /// Maximum Full Screen Rendering debug mode value (used internally). MaxRenderingFullScreenDebug, //Material /// Minimum Full Screen Material debug mode value (used internally). MinMaterialFullScreenDebug, /// Display Diffuse Color validation mode. ValidateDiffuseColor, /// Display specular Color validation mode. ValidateSpecularColor, /// Maximum Full Screen Material debug mode value (used internally). MaxMaterialFullScreenDebug, // TODO: Move before count for 11.0 /// Display Screen Space Reflections buffer of the previous frame accumulated. ScreenSpaceReflectionsPrev, /// Display Screen Space Reflections buffer of the current frame hit. ScreenSpaceReflectionsAccum } /// /// Class managing debug display in HDRP. /// public class DebugDisplaySettings : IDebugData { static string k_PanelDisplayStats = "Display Stats"; static string k_PanelMaterials = "Material"; static string k_PanelLighting = "Lighting"; static string k_PanelVolume = "Volume"; static string k_PanelRendering = "Rendering"; static string k_PanelDecals = "Decals"; DebugUI.Widget[] m_DebugDisplayStatsItems; DebugUI.Widget[] m_DebugMaterialItems; DebugUI.Widget[] m_DebugLightingItems; DebugUI.Widget[] m_DebugVolumeItems; DebugUI.Widget[] m_DebugRenderingItems; DebugUI.Widget[] m_DebugDecalsAffectingTransparentItems; static GUIContent[] s_LightingFullScreenDebugStrings = null; static int[] s_LightingFullScreenDebugValues = null; static GUIContent[] s_RenderingFullScreenDebugStrings = null; static int[] s_RenderingFullScreenDebugValues = null; static GUIContent[] s_MaterialFullScreenDebugStrings = null; static int[] s_MaterialFullScreenDebugValues = null; static GUIContent[] s_MsaaSamplesDebugStrings = null; static int[] s_MsaaSamplesDebugValues = null; static GUIContent[] s_TileAndClusterDebugStrings = null; static int[] s_TileAndClusterDebugValues = null; static List s_CameraNames = new List(); static GUIContent[] s_CameraNamesStrings = null; static int[] s_CameraNamesValues = null; static bool needsRefreshingCameraFreezeList = true; List m_RecordedSamplers = new List(); // Accumulate values to avg over one second. class AccumulatedTiming { public float accumulatedValue = 0; public float lastAverage = 0; internal void UpdateLastAverage(int frameCount) { lastAverage = accumulatedValue / frameCount; accumulatedValue = 0.0f; } } Dictionary m_AccumulatedGPUTiming = new Dictionary(); Dictionary m_AccumulatedCPUTiming = new Dictionary(); Dictionary m_AccumulatedInlineCPUTiming = new Dictionary(); float m_TimeSinceLastAvgValue = 0.0f; int m_AccumulatedFrames = 0; const float k_AccumulationTimeInSeconds = 1.0f; List m_RecordedSamplersRT = new List(); enum DebugProfilingType { CPU, GPU, InlineCPU } /// /// Debug data. /// public class DebugData { /// Ratio of the screen size in which overlays are rendered. public float debugOverlayRatio = 0.33f; /// Current full screen debug mode. public FullScreenDebugMode fullScreenDebugMode = FullScreenDebugMode.None; /// Enable range remapping. public bool enableDebugDepthRemap = false; // False per default to be compliant with AOV depth output (AOV depth must export unmodified linear depth) /// Depth Range remapping values for some of the fullscreen mode. Only x and y are used. public Vector4 fullScreenDebugDepthRemap = new Vector4(0.0f, 1.0f, 0.0f, 0.0f); /// Current full screen debug mode mip level (when applicable). public float fullscreenDebugMip = 0.0f; /// Index of the light used for contact shadows display. public int fullScreenContactShadowLightIndex = 0; /// XR single pass test mode. public bool xrSinglePassTestMode = false; /// Whether to display the average timings every second. public bool averageProfilerTimingsOverASecond = false; /// Current material debug settings. public MaterialDebugSettings materialDebugSettings = new MaterialDebugSettings(); /// Current lighting debug settings. public LightingDebugSettings lightingDebugSettings = new LightingDebugSettings(); /// Current mip map debug settings. public MipMapDebugSettings mipMapDebugSettings = new MipMapDebugSettings(); /// Current color picker debug settings. public ColorPickerDebugSettings colorPickerDebugSettings = new ColorPickerDebugSettings(); /// Current false color debug settings. public FalseColorDebugSettings falseColorDebugSettings = new FalseColorDebugSettings(); /// Current decals debug settings. public DecalsDebugSettings decalsDebugSettings = new DecalsDebugSettings(); /// Current transparency debug settings. public TransparencyDebugSettings transparencyDebugSettings = new TransparencyDebugSettings(); /// Current volume debug settings. public VolumeDebugSettings volumeDebugSettings = new VolumeDebugSettings(); /// Current number of samples for MSAA textures. public MSAASamples msaaSamples = MSAASamples.None; /// Index of screen space shadow to display. public uint screenSpaceShadowIndex = 0; /// Max quad cost for quad overdraw display. public uint maxQuadCost = 5; /// Max vertex density for vertex density display. public uint maxVertexDensity = 10; /// Display ray tracing ray count per frame. public bool countRays = false; /// Index of the camera to freeze for visibility. public int debugCameraToFreeze = 0; // TODO: The only reason this exist is because of Material/Engine debug enums // They have repeating values, which caused issues when iterating through the enum, thus the need for explicit indices // Once we refactor material/engine debug to avoid repeating values, we should be able to remove that. //saved enum fields for when repainting internal int lightingDebugModeEnumIndex; internal int lightingFulscreenDebugModeEnumIndex; internal int materialValidatorDebugModeEnumIndex; internal int tileClusterDebugEnumIndex; internal int mipMapsEnumIndex; internal int engineEnumIndex; internal int attributesEnumIndex; internal int propertiesEnumIndex; internal int gBufferEnumIndex; internal int shadowDebugModeEnumIndex; internal int tileClusterDebugByCategoryEnumIndex; internal int clusterDebugModeEnumIndex; internal int lightVolumeDebugTypeEnumIndex; internal int renderingFulscreenDebugModeEnumIndex; internal int terrainTextureEnumIndex; internal int colorPickerDebugModeEnumIndex; internal int exposureDebugModeEnumIndex; internal int msaaSampleDebugModeEnumIndex; internal int debugCameraToFreezeEnumIndex; internal int volumeComponentEnumIndex; internal int volumeCameraEnumIndex; internal int probeVolumeDebugModeEnumIndex; internal int probeVolumeAtlasSliceModeEnumIndex; // When settings mutually exclusives enum values, we need to reset the other ones. internal void ResetExclusiveEnumIndices() { materialDebugSettings.materialEnumIndex = 0; lightingDebugModeEnumIndex = 0; mipMapsEnumIndex = 0; engineEnumIndex = 0; attributesEnumIndex = 0; propertiesEnumIndex = 0; gBufferEnumIndex = 0; lightingFulscreenDebugModeEnumIndex = 0; renderingFulscreenDebugModeEnumIndex = 0; } } DebugData m_Data; /// /// Debug data. /// public DebugData data { get => m_Data; } // Had to keep those public because HDRP tests using it (as a workaround to access proper enum values for this debug) /// List of Full Screen Rendering Debug mode names. public static GUIContent[] renderingFullScreenDebugStrings => s_RenderingFullScreenDebugStrings; /// List of Full Screen Rendering Debug mode values. public static int[] renderingFullScreenDebugValues => s_RenderingFullScreenDebugValues; /// List of Full Screen Lighting Debug mode names. public static GUIContent[] lightingFullScreenDebugStrings => s_LightingFullScreenDebugStrings; /// List of Full Screen Lighting Debug mode values. public static int[] lightingFullScreenDebugValues => s_LightingFullScreenDebugValues; internal DebugDisplaySettings() { FillFullScreenDebugEnum(ref s_LightingFullScreenDebugStrings, ref s_LightingFullScreenDebugValues, FullScreenDebugMode.MinLightingFullScreenDebug, FullScreenDebugMode.MaxLightingFullScreenDebug); FillFullScreenDebugEnum(ref s_RenderingFullScreenDebugStrings, ref s_RenderingFullScreenDebugValues, FullScreenDebugMode.MinRenderingFullScreenDebug, FullScreenDebugMode.MaxRenderingFullScreenDebug); FillFullScreenDebugEnum(ref s_MaterialFullScreenDebugStrings, ref s_MaterialFullScreenDebugValues, FullScreenDebugMode.MinMaterialFullScreenDebug, FullScreenDebugMode.MaxMaterialFullScreenDebug); var device = SystemInfo.graphicsDeviceType; if (device == GraphicsDeviceType.Metal) { s_RenderingFullScreenDebugStrings = s_RenderingFullScreenDebugStrings.Where((val, idx) => (idx + FullScreenDebugMode.MinRenderingFullScreenDebug) != FullScreenDebugMode.VertexDensity).ToArray(); s_RenderingFullScreenDebugValues = s_RenderingFullScreenDebugValues.Where((val, idx) => (idx + FullScreenDebugMode.MinRenderingFullScreenDebug) != FullScreenDebugMode.VertexDensity).ToArray(); } if (device == GraphicsDeviceType.Metal || device == GraphicsDeviceType.PlayStation4 || device == GraphicsDeviceType.PlayStation5) { s_RenderingFullScreenDebugStrings = s_RenderingFullScreenDebugStrings.Where((val, idx) => (idx + FullScreenDebugMode.MinRenderingFullScreenDebug) != FullScreenDebugMode.QuadOverdraw).ToArray(); s_RenderingFullScreenDebugValues = s_RenderingFullScreenDebugValues.Where((val, idx) => (idx + FullScreenDebugMode.MinRenderingFullScreenDebug) != FullScreenDebugMode.QuadOverdraw).ToArray(); } FillTileClusterDebugEnum(); s_MaterialFullScreenDebugStrings[(int)FullScreenDebugMode.ValidateDiffuseColor - ((int)FullScreenDebugMode.MinMaterialFullScreenDebug)] = new GUIContent("Diffuse Color"); s_MaterialFullScreenDebugStrings[(int)FullScreenDebugMode.ValidateSpecularColor - ((int)FullScreenDebugMode.MinMaterialFullScreenDebug)] = new GUIContent("Metal or SpecularColor"); s_MsaaSamplesDebugStrings = Enum.GetNames(typeof(MSAASamples)) .Select(t => new GUIContent(t)) .ToArray(); s_MsaaSamplesDebugValues = (int[])Enum.GetValues(typeof(MSAASamples)); m_Data = new DebugData(); } /// /// Get Reset action. /// /// Action IDebugData.GetReset() => () => m_Data = new DebugData(); internal float[] GetDebugMaterialIndexes() { return data.materialDebugSettings.GetDebugMaterialIndexes(); } /// /// Returns the current Light filtering mode. /// /// Current Light filtering mode. public DebugLightFilterMode GetDebugLightFilterMode() { return data.lightingDebugSettings.debugLightFilterMode; } /// /// Returns the current Lighting Debug Mode. /// /// Current Lighting Debug Mode. public DebugLightingMode GetDebugLightingMode() { return data.lightingDebugSettings.debugLightingMode; } /// /// Returns the current Light Layers Debug Mask. /// /// Current Light Layers Debug Mask. public DebugLightLayersMask GetDebugLightLayersMask() { var settings = data.lightingDebugSettings; if (!settings.debugLightLayers) return 0; #if UNITY_EDITOR if (settings.debugSelectionLightLayers) { if (UnityEditor.Selection.activeGameObject == null) return 0; var light = UnityEditor.Selection.activeGameObject.GetComponent(); if (light == null) return 0; if (settings.debugSelectionShadowLayers) return (DebugLightLayersMask)light.GetShadowLayers(); return (DebugLightLayersMask)light.GetLightLayers(); } #endif return settings.debugLightLayersFilterMask; } /// /// Returns the current Shadow Map Debug Mode. /// /// Current Shadow Map Debug Mode. public ShadowMapDebugMode GetDebugShadowMapMode() { return data.lightingDebugSettings.shadowDebugMode; } /// /// Returns the current Mip Map Debug Mode. /// /// Current Mip Map Debug Mode. public DebugMipMapMode GetDebugMipMapMode() { return data.mipMapDebugSettings.debugMipMapMode; } /// /// Returns the current Terrain Texture Mip Map Debug Mode. /// /// Current Terrain Texture Mip Map Debug Mode. public DebugMipMapModeTerrainTexture GetDebugMipMapModeTerrainTexture() { return data.mipMapDebugSettings.terrainTexture; } /// /// Returns the current Color Picker Mode. /// /// Current Color Picker Mode. public ColorPickerDebugMode GetDebugColorPickerMode() { return data.colorPickerDebugSettings.colorPickerMode; } /// /// Returns the current Probe Volume Debug Mode. /// /// Current Probe Volume Debug Mode. internal ProbeVolumeDebugMode GetProbeVolumeDebugMode() { return data.lightingDebugSettings.probeVolumeDebugMode; } /// /// Returns true if camera visibility is frozen. /// /// True if camera visibility is frozen public bool IsCameraFreezeEnabled() { return data.debugCameraToFreeze != 0; } /// /// Returns true if a specific camera is frozen for visibility. /// /// Camera to be tested. /// True if a specific camera is frozen for visibility. public bool IsCameraFrozen(Camera camera) { return IsCameraFreezeEnabled() && camera.name.Equals(s_CameraNamesStrings[data.debugCameraToFreeze].text); } /// /// Returns true if any debug display is enabled. /// /// True if any debug display is enabled. public bool IsDebugDisplayEnabled() { return data.materialDebugSettings.IsDebugDisplayEnabled() || data.lightingDebugSettings.IsDebugDisplayEnabled() || data.mipMapDebugSettings.IsDebugDisplayEnabled() || IsDebugFullScreenEnabled(); } /// /// Returns true if any material debug display is enabled. /// /// True if any material debug display is enabled. public bool IsDebugMaterialDisplayEnabled() { return data.materialDebugSettings.IsDebugDisplayEnabled(); } /// /// Returns true if any full screen debug display is enabled. /// /// True if any full screen debug display is enabled. public bool IsDebugFullScreenEnabled() { return data.fullScreenDebugMode != FullScreenDebugMode.None; } /// /// Returns true if a full screen debug display supporting the FullScreenDebug pass is enabled. /// /// True if a full screen debug display supporting the FullScreenDebug pass is enabled. internal bool IsFullScreenDebugPassEnabled() { return data.fullScreenDebugMode == FullScreenDebugMode.QuadOverdraw || data.fullScreenDebugMode == FullScreenDebugMode.VertexDensity; } /// /// Returns true if any full screen exposure debug display is enabled. /// /// True if any full screen exposure debug display is enabled. public bool IsDebugExposureModeEnabled() { return data.lightingDebugSettings.exposureDebugMode != ExposureDebugMode.None; } /// /// Returns true if material validation is enabled. /// /// True if any material validation is enabled. public bool IsMaterialValidationEnabled() { return (data.fullScreenDebugMode == FullScreenDebugMode.ValidateDiffuseColor) || (data.fullScreenDebugMode == FullScreenDebugMode.ValidateSpecularColor); } /// /// Returns true if mip map debug display is enabled. /// /// True if any mip mapdebug display is enabled. public bool IsDebugMipMapDisplayEnabled() { return data.mipMapDebugSettings.IsDebugDisplayEnabled(); } /// /// Returns true if matcap view is enabled for a particular camera. /// /// Input camera. /// True if matcap view is enabled for a particular camera. public bool IsMatcapViewEnabled(HDCamera camera) { bool sceneViewLightingDisabled = CoreUtils.IsSceneLightingDisabled(camera.camera); return sceneViewLightingDisabled || GetDebugLightingMode() == DebugLightingMode.MatcapView; } private void DisableNonMaterialDebugSettings() { data.fullScreenDebugMode = FullScreenDebugMode.None; data.lightingDebugSettings.debugLightingMode = DebugLightingMode.None; data.mipMapDebugSettings.debugMipMapMode = DebugMipMapMode.None; data.lightingDebugSettings.debugLightLayers = false; } /// /// Set the current shared material properties debug view. /// /// Desired shared material property to display. public void SetDebugViewCommonMaterialProperty(MaterialSharedProperty value) { if (value != MaterialSharedProperty.None) DisableNonMaterialDebugSettings(); data.materialDebugSettings.SetDebugViewCommonMaterialProperty(value); } /// /// Set the current material debug view. /// /// Desired material debug view. public void SetDebugViewMaterial(int value) { if (value != 0) DisableNonMaterialDebugSettings(); data.materialDebugSettings.SetDebugViewMaterial(value); } /// /// Set the current engine debug view. /// /// Desired engine debug view. public void SetDebugViewEngine(int value) { if (value != 0) DisableNonMaterialDebugSettings(); data.materialDebugSettings.SetDebugViewEngine(value); } /// /// Set current varying debug view. /// /// Desired varying debug view. public void SetDebugViewVarying(DebugViewVarying value) { if (value != 0) DisableNonMaterialDebugSettings(); data.materialDebugSettings.SetDebugViewVarying(value); } /// /// Set the current Material Property debug view. /// /// Desired property debug view. public void SetDebugViewProperties(DebugViewProperties value) { if (value != 0) DisableNonMaterialDebugSettings(); data.materialDebugSettings.SetDebugViewProperties(value); } /// /// Set the current GBuffer debug view. /// /// Desired GBuffer debug view. public void SetDebugViewGBuffer(int value) { if (value != 0) DisableNonMaterialDebugSettings(); data.materialDebugSettings.SetDebugViewGBuffer(value); } /// /// Set the current Full Screen Debug Mode. /// /// Desired Full Screen Debug mode. public void SetFullScreenDebugMode(FullScreenDebugMode value) { if (data.lightingDebugSettings.shadowDebugMode == ShadowMapDebugMode.SingleShadow) value = 0; if (value != FullScreenDebugMode.None) { data.lightingDebugSettings.debugLightingMode = DebugLightingMode.None; data.lightingDebugSettings.debugLightLayers = false; data.materialDebugSettings.DisableMaterialDebug(); data.mipMapDebugSettings.debugMipMapMode = DebugMipMapMode.None; } data.fullScreenDebugMode = value; } /// /// Set the current Shadow Map Debug Mode. /// /// Desired Shadow Map debug mode. public void SetShadowDebugMode(ShadowMapDebugMode value) { // When SingleShadow is enabled, we don't render full screen debug modes if (value == ShadowMapDebugMode.SingleShadow) data.fullScreenDebugMode = 0; data.lightingDebugSettings.shadowDebugMode = value; } /// /// Set the current Light Filtering. /// /// Desired Light Filtering. public void SetDebugLightFilterMode(DebugLightFilterMode value) { if (value != 0) { data.materialDebugSettings.DisableMaterialDebug(); data.mipMapDebugSettings.debugMipMapMode = DebugMipMapMode.None; data.lightingDebugSettings.debugLightLayers = false; } data.lightingDebugSettings.debugLightFilterMode = value; } /// /// Set the current Light layers Debug Mode /// /// Desired Light Layers Debug Mode. public void SetDebugLightLayersMode(bool value) { if (value) { data.ResetExclusiveEnumIndices(); data.lightingDebugSettings.debugLightFilterMode = DebugLightFilterMode.None; var builtins = typeof(Builtin.BuiltinData); var attr = builtins.GetCustomAttributes(true)[0] as GenerateHLSL; var renderingLayers = Array.IndexOf(builtins.GetFields(), builtins.GetField("renderingLayers")); SetDebugViewMaterial(attr.paramDefinesStart + renderingLayers); } else { SetDebugViewMaterial(0); } data.lightingDebugSettings.debugLightLayers = value; } /// /// Set the current Lighting Debug Mode. /// /// Desired Lighting Debug Mode. public void SetDebugLightingMode(DebugLightingMode value) { if (value != 0) { data.fullScreenDebugMode = FullScreenDebugMode.None; data.materialDebugSettings.DisableMaterialDebug(); data.mipMapDebugSettings.debugMipMapMode = DebugMipMapMode.None; data.lightingDebugSettings.debugLightLayers = false; } data.lightingDebugSettings.debugLightingMode = value; } /// /// Set the current Probe Volume Debug Mode. /// /// Desired Probe Volume Debug Mode. internal void SetProbeVolumeDebugMode(ProbeVolumeDebugMode value) { data.lightingDebugSettings.probeVolumeDebugMode = value; } /// /// Set the current Probe Volume Atlas Mode. /// /// Desired Probe Volume Atlas Mode. internal void SetProbeVolumeAtlasSliceMode(ProbeVolumeAtlasSliceMode value) { data.lightingDebugSettings.probeVolumeAtlasSliceMode = value; } /// /// Set the current Exposure Debug Mode. /// /// Desired Probe Volume Debug Mode. internal void SetExposureDebugMode(ExposureDebugMode value) { data.lightingDebugSettings.exposureDebugMode = value; } /// /// Set the current Mip Map Debug Mode. /// /// Desired Mip Map debug mode. public void SetMipMapMode(DebugMipMapMode value) { if (value != 0) { data.materialDebugSettings.DisableMaterialDebug(); data.lightingDebugSettings.debugLightingMode = DebugLightingMode.None; data.lightingDebugSettings.debugLightLayers = false; data.fullScreenDebugMode = FullScreenDebugMode.None; } data.mipMapDebugSettings.debugMipMapMode = value; } void EnableProfilingRecorders() { Debug.Assert(m_RecordedSamplers.Count == 0); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.HDRenderPipelineAllRenderRequest)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.VolumeUpdate)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.RenderShadowMaps)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.GBuffer)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.PrepareLightsForGPU)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.VolumeVoxelization)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.VolumetricLighting)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.RenderDeferredLightingCompute)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.ForwardOpaque)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.ForwardTransparent)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.ForwardPreRefraction)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.ColorPyramid)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.DepthPyramid)); m_RecordedSamplers.Add(ProfilingSampler.Get(HDProfileId.PostProcessing)); } void DisableProfilingRecorders() { foreach (var sampler in m_RecordedSamplers) { sampler.enableRecording = false; } m_RecordedSamplers.Clear(); } void EnableProfilingRecordersRT() { Debug.Assert(m_RecordedSamplersRT.Count == 0); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingBuildCluster)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingCullLights)); // Ray Traced Reflections m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingReflectionDirectionGeneration)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingReflectionEvaluation)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingReflectionAdjustWeight)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingReflectionUpscale)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingReflectionFilter)); // Ray Traced Ambient Occlusion m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingAmbientOcclusion)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingFilterAmbientOcclusion)); // Ray Traced Shadows m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingDirectionalLightShadow)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingLightShadow)); // Ray Traced Indirect Diffuse m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingIndirectDiffuseDirectionGeneration)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingIndirectDiffuseEvaluation)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingIndirectDiffuseUpscale)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingFilterIndirectDiffuse)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingDebugOverlay)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.ForwardPreRefraction)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RayTracingRecursiveRendering)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RayTracingPrepass)); m_RecordedSamplersRT.Add(ProfilingSampler.Get(HDProfileId.RaytracingDeferredLighting)); } void DisableProfilingRecordersRT() { foreach (var sampler in m_RecordedSamplersRT) { sampler.enableRecording = false; } m_RecordedSamplersRT.Clear(); } float GetSamplerTiming(DebugProfilingType type, ProfilingSampler sampler) { if (data.averageProfilerTimingsOverASecond) { // Find the right accumulated dictionary var accumulatedDictionary = type == DebugProfilingType.CPU ? m_AccumulatedCPUTiming : type == DebugProfilingType.InlineCPU ? m_AccumulatedInlineCPUTiming : m_AccumulatedGPUTiming; AccumulatedTiming accTiming = null; if (accumulatedDictionary.TryGetValue(sampler.name, out accTiming)) return accTiming.lastAverage; } else { return (type == DebugProfilingType.CPU) ? sampler.cpuElapsedTime : ((type == DebugProfilingType.GPU) ? sampler.gpuElapsedTime : sampler.inlineCpuElapsedTime); } return 0.0f; } ObservableList BuildProfilingSamplerList(DebugProfilingType type) { var result = new ObservableList(); // Find the right accumulated dictionary and add it there if not existing yet. var accumulatedDictionary = type == DebugProfilingType.CPU ? m_AccumulatedCPUTiming : type == DebugProfilingType.InlineCPU ? m_AccumulatedInlineCPUTiming : m_AccumulatedGPUTiming; foreach (var sampler in m_RecordedSamplers) { sampler.enableRecording = true; if (!accumulatedDictionary.ContainsKey(sampler.name)) { accumulatedDictionary.Add(sampler.name, new AccumulatedTiming()); } result.Add(new DebugUI.Value { displayName = sampler.name, getter = () => string.Format("{0:F2}", GetSamplerTiming(type, sampler)), refreshRate = 1.0f / 5.0f }); } return result; } ObservableList BuildProfilingSamplerListRT(DebugProfilingType type) { var result = new ObservableList(); // Find the right accumulated dictionary and add it there if not existing yet. var accumulatedDictionary = type == DebugProfilingType.CPU ? m_AccumulatedCPUTiming : type == DebugProfilingType.InlineCPU ? m_AccumulatedInlineCPUTiming : m_AccumulatedGPUTiming; foreach (var sampler in m_RecordedSamplersRT) { sampler.enableRecording = true; if (!accumulatedDictionary.ContainsKey(sampler.name)) { accumulatedDictionary.Add(sampler.name, new AccumulatedTiming()); } result.Add(new DebugUI.Value { displayName = sampler.name, getter = () => string.Format("{0:F2}", GetSamplerTiming(type, sampler)), refreshRate = 1.0f / 5.0f }); } return result; } void UpdateListOfAveragedProfilerTimings(List samplers, bool needUpdatingAverages) { foreach (var sampler in samplers) { // Accumulate. AccumulatedTiming accCPUTiming = null; if (m_AccumulatedCPUTiming.TryGetValue(sampler.name, out accCPUTiming)) accCPUTiming.accumulatedValue += sampler.cpuElapsedTime; AccumulatedTiming accInlineCPUTiming = null; if (m_AccumulatedInlineCPUTiming.TryGetValue(sampler.name, out accInlineCPUTiming)) accInlineCPUTiming.accumulatedValue += sampler.inlineCpuElapsedTime; AccumulatedTiming accGPUTiming = null; if (m_AccumulatedGPUTiming.TryGetValue(sampler.name, out accGPUTiming)) accGPUTiming.accumulatedValue += sampler.gpuElapsedTime; if (needUpdatingAverages) { if (accCPUTiming != null) accCPUTiming.UpdateLastAverage(m_AccumulatedFrames); if (accInlineCPUTiming != null) accInlineCPUTiming.UpdateLastAverage(m_AccumulatedFrames); if (accGPUTiming != null) accGPUTiming.UpdateLastAverage(m_AccumulatedFrames); } } } internal void UpdateAveragedProfilerTimings() { m_TimeSinceLastAvgValue += Time.unscaledDeltaTime; m_AccumulatedFrames++; bool needUpdatingAverages = m_TimeSinceLastAvgValue >= k_AccumulationTimeInSeconds; UpdateListOfAveragedProfilerTimings(m_RecordedSamplers, needUpdatingAverages); UpdateListOfAveragedProfilerTimings(m_RecordedSamplersRT, needUpdatingAverages); if (needUpdatingAverages) { m_TimeSinceLastAvgValue = 0.0f; m_AccumulatedFrames = 0; } } void RegisterDisplayStatsDebug() { var list = new List(); list.Add(new DebugUI.Value { displayName = "Frame Rate (fps)", getter = () => 1f / Time.smoothDeltaTime, refreshRate = 1f / 5f }); list.Add(new DebugUI.Value { displayName = "Frame Time (ms)", getter = () => Time.smoothDeltaTime * 1000f, refreshRate = 1f / 5f }); EnableProfilingRecorders(); list.Add(new DebugUI.BoolField { displayName = "Update every second with average", getter = () => data.averageProfilerTimingsOverASecond, setter = value => data.averageProfilerTimingsOverASecond = value }); list.Add(new DebugUI.Foldout("CPU timings (Command Buffers)", BuildProfilingSamplerList(DebugProfilingType.CPU))); list.Add(new DebugUI.Foldout("GPU timings", BuildProfilingSamplerList(DebugProfilingType.GPU))); if (HDRenderPipeline.currentAsset?.currentPlatformRenderPipelineSettings.supportRayTracing ?? true) { EnableProfilingRecordersRT(); list.Add(new DebugUI.Foldout("CPU timings RT (Command Buffers)", BuildProfilingSamplerListRT(DebugProfilingType.CPU))); list.Add(new DebugUI.Foldout("GPU timings RT", BuildProfilingSamplerListRT(DebugProfilingType.GPU))); } list.Add(new DebugUI.Foldout("Inline CPU timings", BuildProfilingSamplerList(DebugProfilingType.InlineCPU))); list.Add(new DebugUI.BoolField { displayName = "Count Rays (MRays/Frame)", getter = () => data.countRays, setter = value => data.countRays = value, onValueChanged = RefreshDisplayStatsDebug }); if (data.countRays) { list.Add(new DebugUI.Container { children = { new DebugUI.Value { displayName = "Ambient Occlusion", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.AmbientOcclusion)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Shadows Directional", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.ShadowDirectional)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Shadows Area", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.ShadowAreaLight)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Shadows Point/Spot", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.ShadowPointSpot)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Reflections Forward ", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.ReflectionForward)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Reflections Deferred", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.ReflectionDeferred)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Diffuse GI Forward", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.DiffuseGI_Forward)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Diffuse GI Deferred", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.DiffuseGI_Deferred)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Recursive Rendering", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.Recursive)) / 1e6f, refreshRate = 1f / 30f }, new DebugUI.Value { displayName = "Total", getter = () => ((float)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetRaysPerFrame(RayCountValues.Total)) / 1e6f, refreshRate = 1f / 30f }, } }); } #if DEVELOPMENT_BUILD || UNITY_EDITOR list.Add(new DebugUI.BoolField { displayName = "Debug XR Layout", getter = () => XRSystem.dumpDebugInfo, setter = value => XRSystem.dumpDebugInfo = value, onValueChanged = RefreshDisplayStatsDebug }); if (XRSystem.dumpDebugInfo) { Func Bind(Func func, T arg) => () => func(arg); for (int i = 0; i < XRSystem.passDebugInfos.Count; i++) list.Add(new DebugUI.Value { displayName = "", getter = Bind(XRSystem.ReadPassDebugInfo, i) }); } #endif m_DebugDisplayStatsItems = list.ToArray(); var panel = DebugManager.instance.GetPanel(k_PanelDisplayStats, true); panel.flags = DebugUI.Flags.RuntimeOnly; panel.children.Add(m_DebugDisplayStatsItems); } void RegisterMaterialDebug() { var list = new List(); list.Add(new DebugUI.EnumField { displayName = "Common Material Properties", getter = () => (int)data.materialDebugSettings.debugViewMaterialCommonValue, setter = value => SetDebugViewCommonMaterialProperty((MaterialSharedProperty)value), autoEnum = typeof(MaterialSharedProperty), getIndex = () => (int)data.materialDebugSettings.debugViewMaterialCommonValue, setIndex = value => { data.ResetExclusiveEnumIndices(); data.materialDebugSettings.debugViewMaterialCommonValue = (MaterialSharedProperty)value; } }); list.Add(new DebugUI.EnumField { displayName = "Material", getter = () => (data.materialDebugSettings.debugViewMaterial[0]) == 0 ? 0 : data.materialDebugSettings.debugViewMaterial[1], setter = value => SetDebugViewMaterial(value), enumNames = MaterialDebugSettings.debugViewMaterialStrings, enumValues = MaterialDebugSettings.debugViewMaterialValues, getIndex = () => data.materialDebugSettings.materialEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.materialDebugSettings.materialEnumIndex = value; } }); list.Add(new DebugUI.EnumField { displayName = "Engine", getter = () => data.materialDebugSettings.debugViewEngine, setter = value => SetDebugViewEngine(value), enumNames = MaterialDebugSettings.debugViewEngineStrings, enumValues = MaterialDebugSettings.debugViewEngineValues, getIndex = () => data.engineEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.engineEnumIndex = value; } }); list.Add(new DebugUI.EnumField { displayName = "Attributes", getter = () => (int)data.materialDebugSettings.debugViewVarying, setter = value => SetDebugViewVarying((DebugViewVarying)value), autoEnum = typeof(DebugViewVarying), getIndex = () => data.attributesEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.attributesEnumIndex = value; } }); list.Add(new DebugUI.EnumField { displayName = "Properties", getter = () => (int)data.materialDebugSettings.debugViewProperties, setter = value => SetDebugViewProperties((DebugViewProperties)value), autoEnum = typeof(DebugViewProperties), getIndex = () => data.propertiesEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.propertiesEnumIndex = value; } }); list.Add(new DebugUI.EnumField { displayName = "GBuffer", getter = () => data.materialDebugSettings.debugViewGBuffer, setter = value => SetDebugViewGBuffer(value), enumNames = MaterialDebugSettings.debugViewMaterialGBufferStrings, enumValues = MaterialDebugSettings.debugViewMaterialGBufferValues, getIndex = () => data.gBufferEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.gBufferEnumIndex = value; } }); list.Add(new DebugUI.EnumField { displayName = "Material Validator", getter = () => (int)data.fullScreenDebugMode, setter = value => SetFullScreenDebugMode((FullScreenDebugMode)value), enumNames = s_MaterialFullScreenDebugStrings, enumValues = s_MaterialFullScreenDebugValues, onValueChanged = RefreshMaterialDebug, getIndex = () => data.materialValidatorDebugModeEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.materialValidatorDebugModeEnumIndex = value; } }); if (data.fullScreenDebugMode == FullScreenDebugMode.ValidateDiffuseColor || data.fullScreenDebugMode == FullScreenDebugMode.ValidateSpecularColor) { list.Add(new DebugUI.Container { children = { new DebugUI.ColorField { displayName = "Too High Color", getter = () => data.materialDebugSettings.materialValidateHighColor, setter = value => data.materialDebugSettings.materialValidateHighColor = value, showAlpha = false, hdr = true }, new DebugUI.ColorField { displayName = "Too Low Color", getter = () => data.materialDebugSettings.materialValidateLowColor, setter = value => data.materialDebugSettings.materialValidateLowColor = value, showAlpha = false, hdr = true }, new DebugUI.ColorField { displayName = "Not A Pure Metal Color", getter = () => data.materialDebugSettings.materialValidateTrueMetalColor, setter = value => data.materialDebugSettings.materialValidateTrueMetalColor = value, showAlpha = false, hdr = true }, new DebugUI.BoolField { displayName = "Pure Metals", getter = () => data.materialDebugSettings.materialValidateTrueMetal, setter = (v) => data.materialDebugSettings.materialValidateTrueMetal = v }, } }); } m_DebugMaterialItems = list.ToArray(); var panel = DebugManager.instance.GetPanel(k_PanelMaterials, true); panel.children.Add(m_DebugMaterialItems); } void RefreshDisplayStatsDebug(DebugUI.Field field, T value) { UnregisterDebugItems(k_PanelDisplayStats, m_DebugDisplayStatsItems); RegisterDisplayStatsDebug(); } // For now we just rebuild the lighting panel if needed, but ultimately it could be done in a better way void RefreshLightingDebug(DebugUI.Field field, T value) { UnregisterDebugItems(k_PanelLighting, m_DebugLightingItems); RegisterLightingDebug(); } void RefreshDecalsDebug(DebugUI.Field field, T value) { UnregisterDebugItems(k_PanelDecals, m_DebugDecalsAffectingTransparentItems); RegisterDecalsDebug(); } void RefreshRenderingDebug(DebugUI.Field field, T value) { // Explicitly invoke the render debug unregister to handle render graph items. UnregisterDebugItems(k_PanelRendering, m_DebugRenderingItems); RegisterRenderingDebug(); } void RefreshMaterialDebug(DebugUI.Field field, T value) { UnregisterDebugItems(k_PanelMaterials, m_DebugMaterialItems); RegisterMaterialDebug(); } void RefreshVolumeDebug(DebugUI.Field field, T value) { UnregisterDebugItems(k_PanelVolume, m_DebugVolumeItems); RegisterVolumeDebug(); } void RegisterLightingDebug() { var list = new List(); { var shadows = new DebugUI.Container() { displayName = "Shadows" }; shadows.children.Add(new DebugUI.EnumField { displayName = "Debug Mode", getter = () => (int)data.lightingDebugSettings.shadowDebugMode, setter = value => SetShadowDebugMode((ShadowMapDebugMode)value), autoEnum = typeof(ShadowMapDebugMode), onValueChanged = RefreshLightingDebug, getIndex = () => data.shadowDebugModeEnumIndex, setIndex = value => data.shadowDebugModeEnumIndex = value }); if (data.lightingDebugSettings.shadowDebugMode == ShadowMapDebugMode.VisualizeShadowMap || data.lightingDebugSettings.shadowDebugMode == ShadowMapDebugMode.SingleShadow) { var container = new DebugUI.Container(); container.children.Add(new DebugUI.BoolField { displayName = "Use Selection", getter = () => data.lightingDebugSettings.shadowDebugUseSelection, setter = value => data.lightingDebugSettings.shadowDebugUseSelection = value, flags = DebugUI.Flags.EditorOnly, onValueChanged = RefreshLightingDebug }); if (!data.lightingDebugSettings.shadowDebugUseSelection) container.children.Add(new DebugUI.UIntField { displayName = "Shadow Map Index", getter = () => data.lightingDebugSettings.shadowMapIndex, setter = value => data.lightingDebugSettings.shadowMapIndex = value, min = () => 0u, max = () => (uint)(Math.Max(0, (RenderPipelineManager.currentPipeline as HDRenderPipeline).GetCurrentShadowCount() - 1u)) }); shadows.children.Add(container); } shadows.children.Add(new DebugUI.FloatField { displayName = "Global Scale Factor", getter = () => data.lightingDebugSettings.shadowResolutionScaleFactor, setter = (v) => data.lightingDebugSettings.shadowResolutionScaleFactor = v, min = () => 0.01f, max = () => 4.0f, }); shadows.children.Add(new DebugUI.BoolField { displayName = "Clear Shadow Atlas", getter = () => data.lightingDebugSettings.clearShadowAtlas, setter = (v) => data.lightingDebugSettings.clearShadowAtlas = v }); shadows.children.Add(new DebugUI.FloatField { displayName = "Range Minimum Value", getter = () => data.lightingDebugSettings.shadowMinValue, setter = value => data.lightingDebugSettings.shadowMinValue = value }); shadows.children.Add(new DebugUI.FloatField { displayName = "Range Maximum Value", getter = () => data.lightingDebugSettings.shadowMaxValue, setter = value => data.lightingDebugSettings.shadowMaxValue = value }); #if UNITY_EDITOR shadows.children.Add(new DebugUI.Button { displayName = "Log Cached Shadow Atlas Status", action = () => HDCachedShadowManager.instance.PrintLightStatusInCachedAtlas() }); #endif list.Add(shadows); } { var lighting = new DebugUI.Container() { displayName = "Lighting" }; lighting.children.Add(new DebugUI.Foldout { displayName = "Show Lights By Type", children = { new DebugUI.BoolField { displayName = "Directional Lights", getter = () => data.lightingDebugSettings.showDirectionalLight, setter = value => data.lightingDebugSettings.showDirectionalLight = value }, new DebugUI.BoolField { displayName = "Punctual Lights", getter = () => data.lightingDebugSettings.showPunctualLight, setter = value => data.lightingDebugSettings.showPunctualLight = value }, new DebugUI.BoolField { displayName = "Area Lights", getter = () => data.lightingDebugSettings.showAreaLight, setter = value => data.lightingDebugSettings.showAreaLight = value }, new DebugUI.BoolField { displayName = "Reflection Probes", getter = () => data.lightingDebugSettings.showReflectionProbe, setter = value => data.lightingDebugSettings.showReflectionProbe = value }, } }); lighting.children.Add(new DebugUI.Foldout { displayName = "Probe Volumes", children = { new DebugUI.EnumField { displayName = "Probe Volume Debug Mode", getter = () => (int)data.lightingDebugSettings.probeVolumeDebugMode, setter = value => SetProbeVolumeDebugMode((ProbeVolumeDebugMode)value), autoEnum = typeof(ProbeVolumeDebugMode), onValueChanged = RefreshLightingDebug, getIndex = () => data.probeVolumeDebugModeEnumIndex, setIndex = value => data.probeVolumeDebugModeEnumIndex = value }, new DebugUI.EnumField { displayName = "Probe Volume Atlas Slice Mode", getter = () => (int)data.lightingDebugSettings.probeVolumeAtlasSliceMode, setter = value => SetProbeVolumeAtlasSliceMode((ProbeVolumeAtlasSliceMode)value), autoEnum = typeof(ProbeVolumeAtlasSliceMode), onValueChanged = RefreshLightingDebug, getIndex = () => data.probeVolumeAtlasSliceModeEnumIndex, setIndex = value => data.probeVolumeAtlasSliceModeEnumIndex = value }, new DebugUI.FloatField { displayName = "Probe Volume Range Min Value", getter = () => data.lightingDebugSettings.probeVolumeMinValue, setter = value => data.lightingDebugSettings.probeVolumeMinValue = value }, new DebugUI.FloatField { displayName = "Probe Volume Range Max Value", getter = () => data.lightingDebugSettings.probeVolumeMaxValue, setter = value => data.lightingDebugSettings.probeVolumeMaxValue = value }, } }); var exposureFoldout = new DebugUI.Foldout { displayName = "Exposure ", children = { new DebugUI.EnumField { displayName = "Debug Mode", getter = () => (int)data.lightingDebugSettings.exposureDebugMode, setter = value => SetExposureDebugMode((ExposureDebugMode)value), autoEnum = typeof(ExposureDebugMode), onValueChanged = RefreshLightingDebug, getIndex = () => data.exposureDebugModeEnumIndex, setIndex = value => data.exposureDebugModeEnumIndex = value } } }; if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.MeteringWeighted) { exposureFoldout.children.Add( new DebugUI.BoolField() { displayName = "Display Mask Only", getter = () => data.lightingDebugSettings.displayMaskOnly, setter = value => data.lightingDebugSettings.displayMaskOnly = value }); } if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.HistogramView) { exposureFoldout.children.Add( new DebugUI.BoolField() { displayName = "Show Tonemap curve", getter = () => data.lightingDebugSettings.showTonemapCurveAlongHistogramView, setter = value => data.lightingDebugSettings.showTonemapCurveAlongHistogramView = value }); exposureFoldout.children.Add( new DebugUI.BoolField() { displayName = "Center Around Exposure", getter = () => data.lightingDebugSettings.centerHistogramAroundMiddleGrey, setter = value => data.lightingDebugSettings.centerHistogramAroundMiddleGrey = value }); } if (data.lightingDebugSettings.exposureDebugMode == ExposureDebugMode.FinalImageHistogramView) { exposureFoldout.children.Add( new DebugUI.BoolField() { displayName = "Display RGB Histogram", getter = () => data.lightingDebugSettings.displayFinalImageHistogramAsRGB, setter = value => data.lightingDebugSettings.displayFinalImageHistogramAsRGB = value }); } exposureFoldout.children.Add( new DebugUI.FloatField { displayName = "Debug Exposure Compensation", getter = () => data.lightingDebugSettings.debugExposure, setter = value => data.lightingDebugSettings.debugExposure = value }); lighting.children.Add(exposureFoldout); lighting.children.Add(new DebugUI.EnumField { displayName = "Debug Mode", getter = () => (int)data.lightingDebugSettings.debugLightingMode, setter = value => SetDebugLightingMode((DebugLightingMode)value), autoEnum = typeof(DebugLightingMode), onValueChanged = RefreshLightingDebug, getIndex = () => data.lightingDebugModeEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.lightingDebugModeEnumIndex = value; } }); lighting.children.Add(new DebugUI.BitField { displayName = "Hierarchy Debug Mode", getter = () => data.lightingDebugSettings.debugLightFilterMode, setter = value => SetDebugLightFilterMode((DebugLightFilterMode)value), enumType = typeof(DebugLightFilterMode), onValueChanged = RefreshLightingDebug, }); lighting.children.Add(new DebugUI.BoolField { displayName = "Light Layers Visualization", getter = () => data.lightingDebugSettings.debugLightLayers, setter = value => SetDebugLightLayersMode(value), onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.debugLightLayers) { var container = new DebugUI.Container(); container.children.Add(new DebugUI.BoolField { displayName = "Use Selected Light", getter = () => data.lightingDebugSettings.debugSelectionLightLayers, setter = value => data.lightingDebugSettings.debugSelectionLightLayers = value, flags = DebugUI.Flags.EditorOnly, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.debugSelectionLightLayers) { container.children.Add(new DebugUI.BoolField { displayName = "Switch to Light's Shadow Layers", getter = () => data.lightingDebugSettings.debugSelectionShadowLayers, setter = value => data.lightingDebugSettings.debugSelectionShadowLayers = value, flags = DebugUI.Flags.EditorOnly, onValueChanged = RefreshLightingDebug }); } else { var field = new DebugUI.BitField { displayName = "Filter Layers", getter = () => data.lightingDebugSettings.debugLightLayersFilterMask, setter = value => data.lightingDebugSettings.debugLightLayersFilterMask = (DebugLightLayersMask)value, enumType = typeof(DebugLightLayersMask) }; var asset = (RenderPipelineManager.currentPipeline as HDRenderPipeline).asset; for (int i = 0; i < 8; i++) field.enumNames[i + 1].text = asset.renderingLayerMaskNames[i]; container.children.Add(field); } var layersColor = new DebugUI.Foldout() { displayName = "Layers Color", flags = DebugUI.Flags.EditorOnly }; for (int i = 0; i < 8; i++) { int index = i; var asset = (RenderPipelineManager.currentPipeline as HDRenderPipeline).asset; layersColor.children.Add(new DebugUI.ColorField { displayName = asset.renderingLayerMaskNames[i], flags = DebugUI.Flags.EditorOnly, getter = () => data.lightingDebugSettings.debugRenderingLayersColors[index], setter = value => data.lightingDebugSettings.debugRenderingLayersColors[index] = value }); } container.children.Add(layersColor); lighting.children.Add(container); } list.Add(lighting); } { var material = new DebugUI.Container() { displayName = "Material Overrides" }; material.children.Add(new DebugUI.BoolField { displayName = "Override Smoothness", getter = () => data.lightingDebugSettings.overrideSmoothness, setter = value => data.lightingDebugSettings.overrideSmoothness = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.overrideSmoothness) { material.children.Add(new DebugUI.Container { children = { new DebugUI.FloatField { displayName = "Smoothness", getter = () => data.lightingDebugSettings.overrideSmoothnessValue, setter = value => data.lightingDebugSettings.overrideSmoothnessValue = value, min = () => 0f, max = () => 1f, incStep = 0.025f } } }); } material.children.Add(new DebugUI.BoolField { displayName = "Override Albedo", getter = () => data.lightingDebugSettings.overrideAlbedo, setter = value => data.lightingDebugSettings.overrideAlbedo = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.overrideAlbedo) { material.children.Add(new DebugUI.Container { children = { new DebugUI.ColorField { displayName = "Albedo", getter = () => data.lightingDebugSettings.overrideAlbedoValue, setter = value => data.lightingDebugSettings.overrideAlbedoValue = value, showAlpha = false, hdr = false } } }); } material.children.Add(new DebugUI.BoolField { displayName = "Override Normal", getter = () => data.lightingDebugSettings.overrideNormal, setter = value => data.lightingDebugSettings.overrideNormal = value }); material.children.Add(new DebugUI.BoolField { displayName = "Override Specular Color", getter = () => data.lightingDebugSettings.overrideSpecularColor, setter = value => data.lightingDebugSettings.overrideSpecularColor = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.overrideSpecularColor) { material.children.Add(new DebugUI.Container { children = { new DebugUI.ColorField { displayName = "Specular Color", getter = () => data.lightingDebugSettings.overrideSpecularColorValue, setter = value => data.lightingDebugSettings.overrideSpecularColorValue = value, showAlpha = false, hdr = false } } }); } material.children.Add(new DebugUI.BoolField { displayName = "Override Ambient Occlusion", getter = () => data.lightingDebugSettings.overrideAmbientOcclusion, setter = value => data.lightingDebugSettings.overrideAmbientOcclusion = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.overrideAmbientOcclusion) { material.children.Add(new DebugUI.Container { children = { new DebugUI.FloatField { displayName = "AmbientOcclusion", getter = () => data.lightingDebugSettings.overrideAmbientOcclusionValue, setter = value => data.lightingDebugSettings.overrideAmbientOcclusionValue = value, min = () => 0f, max = () => 1f, incStep = 0.025f } } }); } material.children.Add(new DebugUI.BoolField { displayName = "Override Emissive Color", getter = () => data.lightingDebugSettings.overrideEmissiveColor, setter = value => data.lightingDebugSettings.overrideEmissiveColor = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.overrideEmissiveColor) { material.children.Add(new DebugUI.Container { children = { new DebugUI.ColorField { displayName = "Emissive Color", getter = () => data.lightingDebugSettings.overrideEmissiveColorValue, setter = value => data.lightingDebugSettings.overrideEmissiveColorValue = value, showAlpha = false, hdr = true } } }); } list.Add(material); } list.Add(new DebugUI.EnumField { displayName = "Fullscreen Debug Mode", getter = () => (int)data.fullScreenDebugMode, setter = value => SetFullScreenDebugMode((FullScreenDebugMode)value), enumNames = s_LightingFullScreenDebugStrings, enumValues = s_LightingFullScreenDebugValues, onValueChanged = RefreshLightingDebug, getIndex = () => data.lightingFulscreenDebugModeEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.lightingFulscreenDebugModeEnumIndex = value; } }); if (data.fullScreenDebugMode == FullScreenDebugMode.ScreenSpaceShadows) { list.Add(new DebugUI.UIntField { displayName = "Screen Space Shadow Index", getter = () => data.screenSpaceShadowIndex, setter = value => data.screenSpaceShadowIndex = value, min = () => 0u, max = () => (uint)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetMaxScreenSpaceShadows() }); } switch (data.fullScreenDebugMode) { case FullScreenDebugMode.PreRefractionColorPyramid: case FullScreenDebugMode.FinalColorPyramid: case FullScreenDebugMode.DepthPyramid: { list.Add(new DebugUI.Container { children = { new DebugUI.FloatField { displayName = "Debug Mip", getter = () => data.fullscreenDebugMip, setter = value => data.fullscreenDebugMip = value, min = () => 0f, max = () => 1f, incStep = 0.05f }, new DebugUI.BoolField { displayName = "Enable Depth Remap", getter = () => data.enableDebugDepthRemap, setter = value => data.enableDebugDepthRemap = value }, new DebugUI.FloatField { displayName = "Depth range min value", getter = () => data.fullScreenDebugDepthRemap.x, setter = value => data.fullScreenDebugDepthRemap.x = value, min = () => 0f, max = () => 1f, incStep = 0.05f }, new DebugUI.FloatField { displayName = "Depth range max value", getter = () => data.fullScreenDebugDepthRemap.y, setter = value => data.fullScreenDebugDepthRemap.y = value, min = () => 0f, max = () => 1f, incStep = 0.05f } } }); break; } case FullScreenDebugMode.ContactShadows: list.Add(new DebugUI.Container { children = { new DebugUI.IntField { displayName = "Light Index", getter = () => { return data.fullScreenContactShadowLightIndex; }, setter = value => { data.fullScreenContactShadowLightIndex = value; }, min = () => - 1, // -1 will display all contact shadow max = () => LightDefinitions.s_LightListMaxPrunedEntries - 1 }, } }); break; default: data.fullscreenDebugMip = 0; break; } list.Add(new DebugUI.EnumField { displayName = "Tile/Cluster Debug", getter = () => (int)data.lightingDebugSettings.tileClusterDebug, setter = value => data.lightingDebugSettings.tileClusterDebug = (TileClusterDebug)value, autoEnum = typeof(TileClusterDebug), onValueChanged = RefreshLightingDebug, getIndex = () => data.tileClusterDebugEnumIndex, setIndex = value => data.tileClusterDebugEnumIndex = value }); if (data.lightingDebugSettings.tileClusterDebug != TileClusterDebug.None && data.lightingDebugSettings.tileClusterDebug != TileClusterDebug.MaterialFeatureVariants) { var clusterDebugContainer = new DebugUI.Container(); clusterDebugContainer.children.Add(new DebugUI.EnumField { displayName = "Tile/Cluster Debug By Category", getter = () => (int)data.lightingDebugSettings.tileClusterDebugByCategory, setter = value => data.lightingDebugSettings.tileClusterDebugByCategory = (TileClusterCategoryDebug)value, enumNames = s_TileAndClusterDebugStrings, enumValues = s_TileAndClusterDebugValues, getIndex = () => data.tileClusterDebugByCategoryEnumIndex, setIndex = value => data.tileClusterDebugByCategoryEnumIndex = value }); if (data.lightingDebugSettings.tileClusterDebug == TileClusterDebug.Cluster) { clusterDebugContainer.children.Add(new DebugUI.EnumField { displayName = "Cluster Debug Mode", getter = () => (int)data.lightingDebugSettings.clusterDebugMode, setter = value => data.lightingDebugSettings.clusterDebugMode = (ClusterDebugMode)value, autoEnum = typeof(ClusterDebugMode), onValueChanged = RefreshLightingDebug, getIndex = () => data.clusterDebugModeEnumIndex, setIndex = value => data.clusterDebugModeEnumIndex = value }); if (data.lightingDebugSettings.clusterDebugMode == ClusterDebugMode.VisualizeSlice) clusterDebugContainer.children.Add(new DebugUI.FloatField { displayName = "Cluster Distance", getter = () => data.lightingDebugSettings.clusterDebugDistance, setter = value => data.lightingDebugSettings.clusterDebugDistance = value, min = () => 0f, max = () => 100.0f, incStep = 0.05f }); } list.Add(clusterDebugContainer); } list.Add(new DebugUI.BoolField { displayName = "Display Sky Reflection", getter = () => data.lightingDebugSettings.displaySkyReflection, setter = value => data.lightingDebugSettings.displaySkyReflection = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.displaySkyReflection) { list.Add(new DebugUI.Container { children = { new DebugUI.FloatField { displayName = "Sky Reflection Mipmap", getter = () => data.lightingDebugSettings.skyReflectionMipmap, setter = value => data.lightingDebugSettings.skyReflectionMipmap = value, min = () => 0f, max = () => 1f, incStep = 0.05f } } }); } list.Add(new DebugUI.BoolField { displayName = "Display Light Volumes", getter = () => data.lightingDebugSettings.displayLightVolumes, setter = value => data.lightingDebugSettings.displayLightVolumes = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.displayLightVolumes) { var container = new DebugUI.Container { children = { new DebugUI.EnumField { displayName = "Light Volume Debug Type", getter = () => (int)data.lightingDebugSettings.lightVolumeDebugByCategory, setter = value => data.lightingDebugSettings.lightVolumeDebugByCategory = (LightVolumeDebug)value, autoEnum = typeof(LightVolumeDebug), getIndex = () => data.lightVolumeDebugTypeEnumIndex, setIndex = value => data.lightVolumeDebugTypeEnumIndex = value, onValueChanged = RefreshLightingDebug } } }; if (data.lightingDebugSettings.lightVolumeDebugByCategory == LightVolumeDebug.Gradient) { container.children.Add(new DebugUI.UIntField { displayName = "Max Debug Light Count", getter = () => (uint)data.lightingDebugSettings.maxDebugLightCount, setter = value => data.lightingDebugSettings.maxDebugLightCount = value, min = () => 0, max = () => 24, incStep = 1 }); } list.Add(container); } list.Add(new DebugUI.BoolField { displayName = "Display Cookie Atlas", getter = () => data.lightingDebugSettings.displayCookieAtlas, setter = value => data.lightingDebugSettings.displayCookieAtlas = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.displayCookieAtlas) { list.Add(new DebugUI.Container { children = { new DebugUI.UIntField { displayName = "Mip Level", getter = () => data.lightingDebugSettings.cookieAtlasMipLevel, setter = value => data.lightingDebugSettings.cookieAtlasMipLevel = value, min = () => 0, max = () => (uint)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetCookieAtlasMipCount()}, new DebugUI.BoolField { displayName = "Clear Cookie Atlas", getter = () => data.lightingDebugSettings.clearCookieAtlas, setter = value => data.lightingDebugSettings.clearCookieAtlas = value} } }); } list.Add(new DebugUI.BoolField { displayName = "Display Planar Reflection Atlas", getter = () => data.lightingDebugSettings.displayPlanarReflectionProbeAtlas, setter = value => data.lightingDebugSettings.displayPlanarReflectionProbeAtlas = value, onValueChanged = RefreshLightingDebug }); if (data.lightingDebugSettings.displayPlanarReflectionProbeAtlas) { list.Add(new DebugUI.Container { children = { new DebugUI.UIntField { displayName = "Mip Level", getter = () => data.lightingDebugSettings.planarReflectionProbeMipLevel, setter = value => data.lightingDebugSettings.planarReflectionProbeMipLevel = value, min = () => 0, max = () => (uint)(RenderPipelineManager.currentPipeline as HDRenderPipeline).GetPlanarReflectionProbeMipCount()}, new DebugUI.BoolField { displayName = "Clear Planar Atlas", getter = () => data.lightingDebugSettings.clearPlanarReflectionProbeAtlas, setter = value => data.lightingDebugSettings.clearPlanarReflectionProbeAtlas = value}, } }); } list.Add(new DebugUI.FloatField { displayName = "Debug Overlay Screen Ratio", getter = () => data.debugOverlayRatio, setter = v => data.debugOverlayRatio = v, min = () => 0.1f, max = () => 1f }); m_DebugLightingItems = list.ToArray(); var panel = DebugManager.instance.GetPanel(k_PanelLighting, true); panel.children.Add(m_DebugLightingItems); } void RegisterVolumeDebug() { var list = new List(); int componentIndex = 0; var componentNames = new List() { new GUIContent("None") }; var componentValues = new List() { componentIndex++ }; foreach (var type in VolumeDebugSettings.componentTypes) { componentNames.Add(new GUIContent() { text = VolumeDebugSettings.ComponentDisplayName(type) }); componentValues.Add(componentIndex++); } list.Add(new DebugUI.EnumField { displayName = "Component", getter = () => data.volumeDebugSettings.selectedComponent, setter = value => data.volumeDebugSettings.selectedComponent = value, enumNames = componentNames.ToArray(), enumValues = componentValues.ToArray(), getIndex = () => data.volumeComponentEnumIndex, setIndex = value => { data.volumeComponentEnumIndex = value; }, onValueChanged = RefreshVolumeDebug, }); if (data.volumeDebugSettings.selectedComponent != 0) { componentIndex = 0; componentNames = new List() { new GUIContent("None") }; componentValues = new List() { componentIndex++ }; #if UNITY_EDITOR componentNames.Add(new GUIContent() { text = "Editor Camera" }); componentValues.Add(componentIndex++); #endif foreach (var camera in VolumeDebugSettings.cameras) { componentNames.Add(new GUIContent() { text = camera.name }); componentValues.Add(componentIndex++); } list.Add(new DebugUI.EnumField { displayName = "Camera", getter = () => data.volumeDebugSettings.selectedCameraIndex, setter = value => data.volumeDebugSettings.selectedCameraIndex = value, enumNames = componentNames.ToArray(), enumValues = componentValues.ToArray(), getIndex = () => data.volumeCameraEnumIndex, setIndex = value => { data.volumeCameraEnumIndex = value; }, onValueChanged = RefreshVolumeDebug, }); if (data.volumeDebugSettings.selectedCameraIndex != 0) { DebugUI.Widget makeWidget(string name, VolumeParameter param) { if (param == null) return new DebugUI.Value() { displayName = name, getter = () => "-" }; // Special overrides if (param.GetType() == typeof(ColorParameter)) { var p = (ColorParameter)param; return new DebugUI.ColorField() { displayName = name, hdr = p.hdr, showAlpha = p.showAlpha, getter = () => p.value, setter = _ => {} }; } if (param.GetType() == typeof(BoolParameter)) { var p = (BoolParameter)param; return new DebugUI.BoolField() { displayName = name, getter = () => p.value, setter = _ => {} }; } // For parameters that do not override `ToString` var property = param.GetType().GetProperty("value"); var toString = property.PropertyType.GetMethod("ToString", Type.EmptyTypes); if ((toString == null) || (toString.DeclaringType == typeof(object)) || (toString.DeclaringType == typeof(UnityEngine.Object))) { // Check if the parameter has a name var nameProp = property.PropertyType.GetProperty("name"); if (nameProp == null) return new DebugUI.Value() { displayName = name, getter = () => "Debug view not supported" }; // Return the parameter name return new DebugUI.Value() { displayName = name, getter = () => { var value = property.GetValue(param); if (value == null || value.Equals(null)) return "None"; var valueString = nameProp.GetValue(value); return valueString == null ? "None" : valueString; } }; } // Call the ToString method return new DebugUI.Value() { displayName = name, getter = () => { var value = property.GetValue(param); return value == null ? "None" : value.ToString(); } }; } Type selectedType = data.volumeDebugSettings.selectedComponentType; var stackComponent = data.volumeDebugSettings.selectedCameraVolumeStack.GetComponent(selectedType); var volumes = data.volumeDebugSettings.GetVolumes(); var table = new DebugUI.Table() { displayName = "Parameter", isReadOnly = true }; var inst = (VolumeComponent)ScriptableObject.CreateInstance(selectedType); // First row for volume info float timer = 0.0f, refreshRate = 0.2f; var row = new DebugUI.Table.Row() { displayName = "Volume Info", children = { new DebugUI.Value() { displayName = "Interpolated Value", getter = () => { // This getter is called first at each render // It is used to update the volumes if (Time.time - timer < refreshRate) return ""; timer = Time.deltaTime; if (data.volumeDebugSettings.selectedCameraIndex != 0) { var newVolumes = data.volumeDebugSettings.GetVolumes(); if (!data.volumeDebugSettings.RefreshVolumes(newVolumes)) { for (int i = 0; i < newVolumes.Length; i++) { var visible = data.volumeDebugSettings.VolumeHasInfluence(newVolumes[i]); table.SetColumnVisibility(i + 1, visible); } return ""; } } RefreshVolumeDebug(null, false); return ""; } } } }; row.opened = true; foreach (var volume in volumes) { var profile = volume.HasInstantiatedProfile() ? volume.profile : volume.sharedProfile; row.children.Add(new DebugUI.Value() { displayName = volume.name + " (" + profile.name + ")", getter = () => { var scope = volume.isGlobal ? "Global" : "Local"; var weight = data.volumeDebugSettings.GetVolumeWeight(volume); return scope + " (" + (weight * 100f) + "%)"; } }); } row.children.Add(new DebugUI.Value() { displayName = "Default Value", getter = () => "" }); table.children.Add(row); // Build rows - recursively handles nested parameters var rows = new List(); void AddParameterRows(Type type, string baseName = null) { void AddRow(FieldInfo f, string prefix) { var fieldName = prefix + f.Name; var attr = (DisplayInfoAttribute[])f.GetCustomAttributes(typeof(DisplayInfoAttribute), true); if (attr.Length != 0) fieldName = prefix + attr[0].name; #if UNITY_EDITOR // Would be nice to have the equivalent for the runtime debug. else fieldName = UnityEditor.ObjectNames.NicifyVariableName(fieldName); #endif int currentParam = rows.Count; row = new DebugUI.Table.Row() { displayName = fieldName, children = { makeWidget("Interpolated Value", stackComponent.parameters[currentParam]) } }; foreach (var volume in volumes) { VolumeParameter param = null; var profile = volume.HasInstantiatedProfile() ? volume.profile : volume.sharedProfile; if (profile.TryGet(selectedType, out VolumeComponent component) && component.parameters[currentParam].overrideState) param = component.parameters[currentParam]; row.children.Add(makeWidget(volume.name + " (" + profile.name + ")", param)); } row.children.Add(makeWidget("Default Value", inst.parameters[currentParam])); rows.Add(row); } var fields = type .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .OrderBy(t => t.MetadataToken); foreach (var field in fields) { var fieldType = field.FieldType; if (fieldType.IsSubclassOf(typeof(VolumeParameter))) AddRow(field, baseName ?? ""); else if (!fieldType.IsArray && fieldType.IsClass) AddParameterRows(fieldType, baseName ?? (field.Name + " ")); } } AddParameterRows(selectedType); foreach (var r in rows.OrderBy(t => t.displayName)) table.children.Add(r); data.volumeDebugSettings.RefreshVolumes(volumes); for (int i = 0; i < volumes.Length; i++) table.SetColumnVisibility(i + 1, data.volumeDebugSettings.VolumeHasInfluence(volumes[i])); list.Add(table); } } m_DebugVolumeItems = list.ToArray(); var panel = DebugManager.instance.GetPanel(k_PanelVolume, true); panel.children.Add(m_DebugVolumeItems); } void RegisterRenderingDebug() { var widgetList = new List(); widgetList.Add( new DebugUI.EnumField { displayName = "Fullscreen Debug Mode", getter = () => (int)data.fullScreenDebugMode, setter = value => SetFullScreenDebugMode((FullScreenDebugMode)value), onValueChanged = RefreshRenderingDebug, enumNames = s_RenderingFullScreenDebugStrings, enumValues = s_RenderingFullScreenDebugValues, getIndex = () => data.renderingFulscreenDebugModeEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.renderingFulscreenDebugModeEnumIndex = value; } } ); if (data.fullScreenDebugMode == FullScreenDebugMode.TransparencyOverdraw) { widgetList.Add(new DebugUI.Container { children = { new DebugUI.FloatField {displayName = "Max Pixel Cost", getter = () => data.transparencyDebugSettings.maxPixelCost, setter = value => data.transparencyDebugSettings.maxPixelCost = value, min = () => 0.25f, max = () => 2048.0f} } }); } else if (data.fullScreenDebugMode == FullScreenDebugMode.QuadOverdraw) { widgetList.Add(new DebugUI.Container { children = { new DebugUI.UIntField {displayName = "Max Quad Cost", getter = () => data.maxQuadCost, setter = value => data.maxQuadCost = value, min = () => 1, max = () => 10} } }); } else if (data.fullScreenDebugMode == FullScreenDebugMode.VertexDensity) { widgetList.Add(new DebugUI.Container { children = { new DebugUI.UIntField {displayName = "Max Vertex Density", getter = () => data.maxVertexDensity, setter = value => data.maxVertexDensity = value, min = () => 1, max = () => 100} } }); } widgetList.AddRange(new DebugUI.Widget[] { new DebugUI.EnumField { displayName = "MipMaps", getter = () => (int)data.mipMapDebugSettings.debugMipMapMode, setter = value => SetMipMapMode((DebugMipMapMode)value), autoEnum = typeof(DebugMipMapMode), onValueChanged = RefreshRenderingDebug, getIndex = () => data.mipMapsEnumIndex, setIndex = value => { data.ResetExclusiveEnumIndices(); data.mipMapsEnumIndex = value; } }, }); if (data.mipMapDebugSettings.debugMipMapMode != DebugMipMapMode.None) { widgetList.Add(new DebugUI.Container { children = { new DebugUI.EnumField { displayName = "Terrain Texture", getter = () => (int)data.mipMapDebugSettings.terrainTexture, setter = value => data.mipMapDebugSettings.terrainTexture = (DebugMipMapModeTerrainTexture)value, autoEnum = typeof(DebugMipMapModeTerrainTexture), getIndex = () => data.terrainTextureEnumIndex, setIndex = value => data.terrainTextureEnumIndex = value } } }); } widgetList.AddRange(new[] { new DebugUI.Container { displayName = "Color Picker", flags = DebugUI.Flags.EditorOnly, children = { new DebugUI.EnumField { displayName = "Debug Mode", getter = () => (int)data.colorPickerDebugSettings.colorPickerMode, setter = value => data.colorPickerDebugSettings.colorPickerMode = (ColorPickerDebugMode)value, autoEnum = typeof(ColorPickerDebugMode), getIndex = () => data.colorPickerDebugModeEnumIndex, setIndex = value => data.colorPickerDebugModeEnumIndex = value }, new DebugUI.ColorField { displayName = "Font Color", flags = DebugUI.Flags.EditorOnly, getter = () => data.colorPickerDebugSettings.fontColor, setter = value => data.colorPickerDebugSettings.fontColor = value } } } }); widgetList.Add(new DebugUI.BoolField { displayName = "False Color Mode", getter = () => data.falseColorDebugSettings.falseColor, setter = value => data.falseColorDebugSettings.falseColor = value, onValueChanged = RefreshRenderingDebug }); if (data.falseColorDebugSettings.falseColor) { widgetList.Add(new DebugUI.Container { flags = DebugUI.Flags.EditorOnly, children = { new DebugUI.FloatField { displayName = "Range Threshold 0", getter = () => data.falseColorDebugSettings.colorThreshold0, setter = value => data.falseColorDebugSettings.colorThreshold0 = Mathf.Min(value, data.falseColorDebugSettings.colorThreshold1) }, new DebugUI.FloatField { displayName = "Range Threshold 1", getter = () => data.falseColorDebugSettings.colorThreshold1, setter = value => data.falseColorDebugSettings.colorThreshold1 = Mathf.Clamp(value, data.falseColorDebugSettings.colorThreshold0, data.falseColorDebugSettings.colorThreshold2) }, new DebugUI.FloatField { displayName = "Range Threshold 2", getter = () => data.falseColorDebugSettings.colorThreshold2, setter = value => data.falseColorDebugSettings.colorThreshold2 = Mathf.Clamp(value, data.falseColorDebugSettings.colorThreshold1, data.falseColorDebugSettings.colorThreshold3) }, new DebugUI.FloatField { displayName = "Range Threshold 3", getter = () => data.falseColorDebugSettings.colorThreshold3, setter = value => data.falseColorDebugSettings.colorThreshold3 = Mathf.Max(value, data.falseColorDebugSettings.colorThreshold2) }, } }); } if (HDRenderPipeline.currentAsset?.currentPlatformRenderPipelineSettings.supportMSAA ?? true) { widgetList.AddRange(new DebugUI.Widget[] { new DebugUI.EnumField { displayName = "MSAA Samples", getter = () => (int)data.msaaSamples, setter = value => data.msaaSamples = (MSAASamples)value, enumNames = s_MsaaSamplesDebugStrings, enumValues = s_MsaaSamplesDebugValues, getIndex = () => data.msaaSampleDebugModeEnumIndex, setIndex = value => data.msaaSampleDebugModeEnumIndex = value }, }); } widgetList.AddRange(new DebugUI.Widget[] { new DebugUI.EnumField { displayName = "Freeze Camera for culling", getter = () => data.debugCameraToFreeze, setter = value => data.debugCameraToFreeze = value, enumNames = s_CameraNamesStrings, enumValues = s_CameraNamesValues, getIndex = () => data.debugCameraToFreezeEnumIndex, setIndex = value => data.debugCameraToFreezeEnumIndex = value }, }); if (XRGraphicsAutomatedTests.enabled) { widgetList.Add(new DebugUI.BoolField { displayName = "XR single-pass test mode", getter = () => data.xrSinglePassTestMode, setter = value => data.xrSinglePassTestMode = value }); } m_DebugRenderingItems = widgetList.ToArray(); var panel = DebugManager.instance.GetPanel(k_PanelRendering, true); panel.children.Add(m_DebugRenderingItems); } void RegisterDecalsDebug() { var decalAffectingTransparent = new DebugUI.Container() { displayName = "Decals Affecting Transparent Objects", children = { new DebugUI.BoolField { displayName = "Display Atlas", getter = () => data.decalsDebugSettings.displayAtlas, setter = value => data.decalsDebugSettings.displayAtlas = value}, new DebugUI.UIntField { displayName = "Mip Level", getter = () => data.decalsDebugSettings.mipLevel, setter = value => data.decalsDebugSettings.mipLevel = value, min = () => 0u, max = () => (uint)(RenderPipelineManager.currentPipeline as HDRenderPipeline)?.GetDecalAtlasMipCount() } } }; m_DebugDecalsAffectingTransparentItems = new DebugUI.Widget[] { decalAffectingTransparent }; var panel = DebugManager.instance.GetPanel(k_PanelDecals, true); panel.children.Add(m_DebugDecalsAffectingTransparentItems); } internal void RegisterDebug() { RegisterDecalsDebug(); RegisterDisplayStatsDebug(); RegisterMaterialDebug(); RegisterLightingDebug(); RegisterVolumeDebug(); RegisterRenderingDebug(); DebugManager.instance.RegisterData(this); } internal void UnregisterDebug() { UnregisterDebugItems(k_PanelDecals, m_DebugDecalsAffectingTransparentItems); DisableProfilingRecorders(); if (HDRenderPipeline.currentAsset?.currentPlatformRenderPipelineSettings.supportRayTracing ?? true) DisableProfilingRecordersRT(); UnregisterDebugItems(k_PanelDisplayStats, m_DebugDisplayStatsItems); UnregisterDebugItems(k_PanelMaterials, m_DebugMaterialItems); UnregisterDebugItems(k_PanelLighting, m_DebugLightingItems); UnregisterDebugItems(k_PanelVolume, m_DebugVolumeItems); UnregisterDebugItems(k_PanelRendering, m_DebugRenderingItems); DebugManager.instance.UnregisterData(this); } void UnregisterDebugItems(string panelName, DebugUI.Widget[] items) { var panel = DebugManager.instance.GetPanel(panelName); if (panel != null) panel.children.Remove(items); } void FillFullScreenDebugEnum(ref GUIContent[] strings, ref int[] values, FullScreenDebugMode min, FullScreenDebugMode max) { int count = max - min - 1; strings = new GUIContent[count + 1]; values = new int[count + 1]; strings[0] = new GUIContent(FullScreenDebugMode.None.ToString()); values[0] = (int)FullScreenDebugMode.None; int index = 1; for (int i = (int)min + 1; i < (int)max; ++i) { strings[index] = new GUIContent(((FullScreenDebugMode)i).ToString()); values[index] = i; index++; } } void FillTileClusterDebugEnum() { string[] names = Enum.GetNames(typeof(TileClusterCategoryDebug)); for (int i = 0; i < names.Length; ++i) { var n = names[i]; names[i] = n.Replace("Environment", "ReflectionProbes"); } s_TileAndClusterDebugStrings = names .Select(t => new GUIContent(t)) .ToArray(); s_TileAndClusterDebugValues = (int[])Enum.GetValues(typeof(TileClusterCategoryDebug)); } static string FormatVector(Vector3 v) { return string.Format("({0:F6}, {1:F6}, {2:F6})", v.x, v.y, v.z); } internal static void RegisterCamera(IFrameSettingsHistoryContainer container) { string name = container.panelName; if (s_CameraNames.FindIndex(x => x.text.Equals(name)) < 0) { s_CameraNames.Add(new GUIContent(name)); needsRefreshingCameraFreezeList = true; } if (!FrameSettingsHistory.IsRegistered(container)) { var history = FrameSettingsHistory.RegisterDebug(container); DebugManager.instance.RegisterData(history); } } internal static void UnRegisterCamera(IFrameSettingsHistoryContainer container) { string name = container.panelName; int indexOfCamera = s_CameraNames.FindIndex(x => x.text.Equals(name)); if (indexOfCamera > 0) { s_CameraNames.RemoveAt(indexOfCamera); needsRefreshingCameraFreezeList = true; } if (FrameSettingsHistory.IsRegistered(container)) { DebugManager.instance.UnregisterData(container); FrameSettingsHistory.UnRegisterDebug(container); } } internal bool IsDebugDisplayRemovePostprocess() { return data.materialDebugSettings.IsDebugDisplayEnabled() || data.lightingDebugSettings.IsDebugDisplayRemovePostprocess() || data.mipMapDebugSettings.IsDebugDisplayEnabled(); } internal void UpdateMaterials() { if (data.mipMapDebugSettings.debugMipMapMode != 0) Texture.SetStreamingTextureMaterialDebugProperties(); } internal void UpdateCameraFreezeOptions() { if (needsRefreshingCameraFreezeList) { s_CameraNames.Insert(0, new GUIContent("None")); s_CameraNamesStrings = s_CameraNames.ToArray(); s_CameraNamesValues = Enumerable.Range(0, s_CameraNames.Count()).ToArray(); UnregisterDebugItems(k_PanelRendering, m_DebugRenderingItems); RegisterRenderingDebug(); needsRefreshingCameraFreezeList = false; } } internal bool DebugHideSky(HDCamera hdCamera) { return (IsMatcapViewEnabled(hdCamera) || GetDebugLightingMode() == DebugLightingMode.DiffuseLighting || GetDebugLightingMode() == DebugLightingMode.SpecularLighting || GetDebugLightingMode() == DebugLightingMode.DirectDiffuseLighting || GetDebugLightingMode() == DebugLightingMode.DirectSpecularLighting || GetDebugLightingMode() == DebugLightingMode.IndirectDiffuseLighting || GetDebugLightingMode() == DebugLightingMode.ReflectionLighting || GetDebugLightingMode() == DebugLightingMode.RefractionLighting ); } internal bool DebugNeedsExposure() { DebugLightingMode debugLighting = data.lightingDebugSettings.debugLightingMode; DebugViewGbuffer debugGBuffer = (DebugViewGbuffer)data.materialDebugSettings.debugViewGBuffer; return (debugLighting == DebugLightingMode.DirectDiffuseLighting || debugLighting == DebugLightingMode.DirectSpecularLighting || debugLighting == DebugLightingMode.IndirectDiffuseLighting || debugLighting == DebugLightingMode.ReflectionLighting || debugLighting == DebugLightingMode.RefractionLighting || debugLighting == DebugLightingMode.EmissiveLighting || debugLighting == DebugLightingMode.DiffuseLighting || debugLighting == DebugLightingMode.SpecularLighting || debugLighting == DebugLightingMode.VisualizeCascade) || (data.lightingDebugSettings.overrideAlbedo || data.lightingDebugSettings.overrideNormal || data.lightingDebugSettings.overrideSmoothness || data.lightingDebugSettings.overrideSpecularColor || data.lightingDebugSettings.overrideEmissiveColor || data.lightingDebugSettings.overrideAmbientOcclusion) || (debugGBuffer == DebugViewGbuffer.BakeDiffuseLightingWithAlbedoPlusEmissive) || (data.lightingDebugSettings.debugLightFilterMode != DebugLightFilterMode.None) || (data.fullScreenDebugMode == FullScreenDebugMode.PreRefractionColorPyramid || data.fullScreenDebugMode == FullScreenDebugMode.FinalColorPyramid || data.fullScreenDebugMode == FullScreenDebugMode.TransparentScreenSpaceReflections || data.fullScreenDebugMode == FullScreenDebugMode.ScreenSpaceReflections || data.fullScreenDebugMode == FullScreenDebugMode.ScreenSpaceReflectionsPrev || data.fullScreenDebugMode == FullScreenDebugMode.ScreenSpaceReflectionsAccum || data.fullScreenDebugMode == FullScreenDebugMode.LightCluster || data.fullScreenDebugMode == FullScreenDebugMode.ScreenSpaceShadows || data.fullScreenDebugMode == FullScreenDebugMode.NanTracker || data.fullScreenDebugMode == FullScreenDebugMode.ColorLog) || data.fullScreenDebugMode == FullScreenDebugMode.ScreenSpaceGlobalIllumination; } } }