using System; using UnityEngine; using UnityEngine.PathTracing.Lightmapping; using UnityEngine.Rendering; namespace UnityEditor.PathTracing.Debugging { internal static class AdaptiveSamplingDebugHelpers { internal static class ShaderIDs { public static readonly int TemporaryRT = Shader.PropertyToID("BakeLightmapDriverTemporaryRT"); public static readonly int SecondTemporaryRT = Shader.PropertyToID("BakeLightmapDriverSecondTemporaryRT"); } static internal void LogTotalSamplesTaken(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture accumulatedOutput, uint maxSampleCount) { int width = accumulatedOutput.width; int height = accumulatedOutput.height; UInt64 totalSampleSum = GetSampleCountSum(cmd, helpers, accumulatedOutput); UInt64 maxSampleSum = (UInt64)width * (UInt64)height * (UInt64)maxSampleCount; Debug.Log($"total samples taken:\t{totalSampleSum}\tout of: \t{maxSampleSum}\tfraction:\t{(double)totalSampleSum / (double)maxSampleSum}"); } static internal LightmapIntegrationHelpers.AdaptiveSample GetAdaptiveSample(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture accumulatedOutput, RenderTexture adaptiveOutput, int sampleX, int sampleY) { Debug.Assert(accumulatedOutput.width == adaptiveOutput.width && accumulatedOutput.height == adaptiveOutput.height); var width = adaptiveOutput.width; var height = adaptiveOutput.height; Color accumulatedOutputValue = LightmapIntegrationHelpers.GetValue(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.GetValueKernel, sampleX, sampleY, width, height, accumulatedOutput); float accumulatedLuminance = LightmapIntegrationHelpers.Luminance(accumulatedOutputValue); Color adaptiveOutputValue = LightmapIntegrationHelpers.GetValue(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.GetValueKernel, sampleX, sampleY, width, height, adaptiveOutput); LightmapIntegrationHelpers.AdaptiveSample sample = new LightmapIntegrationHelpers.AdaptiveSample(); sample.sampleCount = (uint)accumulatedOutputValue.a; sample.accumulatedLuminance = accumulatedLuminance; sample.mean = adaptiveOutputValue.r; sample.meanSqr = adaptiveOutputValue.g; sample.variance = adaptiveOutputValue.b; sample.standardError = adaptiveOutputValue.a; // missing sample.varianceFiltered = 0.0f;// LightmapIntegrationHelpers.GetValue(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.GetValueKernel, sampleX, sampleY, width, height, lightmappingContext.AdaptiveOutput).b; sample.active = false;// LightmapIntegrationHelpers.GetValue(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.GetValueKernel, sampleX, sampleY, width, height, secondTemporaryRT).r > 0.5f; return sample; } static internal void WriteAdaptiveDebugImages(string path, string filenamePostfix, CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture accumulatedOutput, RenderTexture adaptiveOutput, uint totalSampleCount, float varianceScale, float errorScale, float adaptiveThreshold) { WriteIrradiance(cmd, helpers, accumulatedOutput, $"{path}/irradiance_{filenamePostfix}.r2d"); WriteSampleCount(cmd, helpers, accumulatedOutput, totalSampleCount, $"{path}/sampleCount_{filenamePostfix}.r2d"); WriteVariance(cmd, helpers, adaptiveOutput, varianceScale, $"{path}/variance_{filenamePostfix}.r2d"); // this may be double filtered in converged parts of the lightmap WriteFilteredVariance(cmd, helpers, adaptiveOutput, varianceScale, $"{path}/varianceFiltered_{filenamePostfix}.r2d"); WriteStandardError(cmd, helpers, adaptiveOutput, errorScale, $"{path}/standardError_{filenamePostfix}.r2d"); WriteActiveTexels(cmd, helpers, adaptiveOutput, adaptiveThreshold, $"{path}/active_{filenamePostfix}.r2d"); SerializationHelpers.WriteRenderTexture(cmd, $"{path}/adaptive_{filenamePostfix}.r2d", adaptiveOutput); } static void WriteIrradiance(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture accumulatedOutput, string filename) { int width = accumulatedOutput.width; int height = accumulatedOutput.height; int tempRTID = ShaderIDs.TemporaryRT; cmd.GetTemporaryRT(tempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.CopyTexture(accumulatedOutput, tempRTID); LightmapIntegrationHelpers.NormalizeByAlpha(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.NormalizeByAlphaKernel, width, height, tempRTID); LightmapIntegrationHelpers.SetChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.SetChannelKernel, tempRTID, width, height, 3, 1.0f); SerializationHelpers.WriteRenderTexture(cmd, tempRTID, TextureFormat.RGBAFloat, width, height, filename); cmd.ReleaseTemporaryRT(tempRTID); } static void WriteSampleCount(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture accumulatedOutput, uint maxSampleCount, string filename) { int width = accumulatedOutput.width; int height = accumulatedOutput.height; int tempRTID = ShaderIDs.TemporaryRT; cmd.GetTemporaryRT(tempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.CopyTexture(accumulatedOutput, tempRTID); LightmapIntegrationHelpers.BroadcastChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.BroadcastChannelKernel, tempRTID, width, height, 3); LightmapIntegrationHelpers.SetChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.SetChannelKernel, tempRTID, width, height, 3, 1.0f); float samplesScale = 1.0f / maxSampleCount; LightmapIntegrationHelpers.MultiplyRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.MultiplyKernel, tempRTID, width, height, new Vector4(samplesScale, samplesScale, samplesScale, 1.0f)); SerializationHelpers.WriteRenderTexture(cmd, tempRTID, TextureFormat.RGBAFloat, width, height, filename); cmd.ReleaseTemporaryRT(tempRTID); } static void WriteVariance(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture adaptiveOutput, float scale, string filename) { int width = adaptiveOutput.width; int height = adaptiveOutput.height; int tempRTID = ShaderIDs.TemporaryRT; cmd.GetTemporaryRT(tempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.CopyTexture(adaptiveOutput, tempRTID); LightmapIntegrationHelpers.BroadcastChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.BroadcastChannelKernel, tempRTID, width, height, 2); LightmapIntegrationHelpers.SetChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.SetChannelKernel, tempRTID, width, height, 3, 1.0f); LightmapIntegrationHelpers.MultiplyRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.MultiplyKernel, tempRTID, width, height, new Vector4(scale, scale, scale, 1.0f)); SerializationHelpers.WriteRenderTexture(cmd, tempRTID, TextureFormat.RGBAFloat, width, height, filename); cmd.ReleaseTemporaryRT(tempRTID); } static void WriteFilteredVariance(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture adaptiveOutput, float scale, string filename) { int width = adaptiveOutput.width; int height = adaptiveOutput.height; int tempRTID = ShaderIDs.TemporaryRT; cmd.GetTemporaryRT(tempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.CopyTexture(adaptiveOutput, tempRTID); LightmapIntegrationHelpers.ReferenceBoxFilterRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.ReferenceBoxFilterBlueChannelKernel, tempRTID, width, height, 2); LightmapIntegrationHelpers.BroadcastChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.BroadcastChannelKernel, tempRTID, width, height, 2); LightmapIntegrationHelpers.SetChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.SetChannelKernel, tempRTID, width, height, 3, 1.0f); LightmapIntegrationHelpers.MultiplyRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.MultiplyKernel, tempRTID, width, height, new Vector4(scale, scale, scale, 1.0f)); SerializationHelpers.WriteRenderTexture(cmd, tempRTID, TextureFormat.RGBAFloat, width, height, filename); cmd.ReleaseTemporaryRT(tempRTID); } static void WriteStandardError(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture adaptiveOutput, float scale, string filename) { int width = adaptiveOutput.width; int height = adaptiveOutput.height; int tempRTID = ShaderIDs.TemporaryRT; cmd.GetTemporaryRT(tempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.CopyTexture(adaptiveOutput, tempRTID); LightmapIntegrationHelpers.BroadcastChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.BroadcastChannelKernel, tempRTID, width, height, 3); LightmapIntegrationHelpers.SetChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.SetChannelKernel, tempRTID, width, height, 3, 1.0f); LightmapIntegrationHelpers.MultiplyRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.MultiplyKernel, tempRTID, width, height, new Vector4(scale, scale, scale, 1.0f)); SerializationHelpers.WriteRenderTexture(cmd, tempRTID, TextureFormat.RGBAFloat, width, height, filename); cmd.ReleaseTemporaryRT(tempRTID); } static int GetActiveTexelImage(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture adaptiveOutput, float adaptiveThreshold) { int width = adaptiveOutput.width; int height = adaptiveOutput.height; int tempRTID = ShaderIDs.TemporaryRT; int secondTempRTID = ShaderIDs.SecondTemporaryRT; cmd.GetTemporaryRT(secondTempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.GetTemporaryRT(tempRTID, width, height, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear, 1, true); cmd.CopyTexture(adaptiveOutput, tempRTID); LightmapIntegrationHelpers.BroadcastChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.BroadcastChannelKernel, tempRTID, width, height, 3); LightmapIntegrationHelpers.StandardErrorThresholdRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.StandardErrorThresholdKernel, tempRTID, adaptiveOutput, adaptiveThreshold, secondTempRTID, width, height); cmd.ReleaseTemporaryRT(tempRTID); return secondTempRTID; } static void WriteActiveTexels(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture adaptiveOutput, float adaptiveThreshold, string filename) { int width = adaptiveOutput.width; int height = adaptiveOutput.height; int tempRTID = GetActiveTexelImage(cmd, helpers, adaptiveOutput, adaptiveThreshold); SerializationHelpers.WriteRenderTexture(cmd, tempRTID, TextureFormat.RGBAFloat, width, height, filename); cmd.ReleaseTemporaryRT(tempRTID); } static UInt64 GetSampleCountSum(CommandBuffer cmd, LightmapIntegrationHelpers.ComputeHelpers helpers, RenderTexture accumulatedOutput) { int width = accumulatedOutput.width; int height = accumulatedOutput.height; var temporaryRT = new RenderTexture(width, height, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear) { name = "temporaryRT (GetSampleCountSum)", enableRandomWrite = true, hideFlags = HideFlags.HideAndDontSave }; temporaryRT.Create(); cmd.CopyTexture(accumulatedOutput, temporaryRT); LightmapIntegrationHelpers.BroadcastChannelRenderTexture(cmd, helpers.ComputeHelperShader, LightmapIntegrationHelpers.ComputeHelpers.BroadcastChannelKernel, temporaryRT, width, height, 3); Graphics.ExecuteCommandBuffer(cmd); cmd.Clear(); double totalSampleSum = LightmapIntegrationHelpers.GetSum(width, height, temporaryRT).x; temporaryRT.Release(); CoreUtils.Destroy(temporaryRT); return (UInt64)totalSampleSum; } } }