WaveformMonitor.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System;
  2. namespace UnityEngine.Rendering.PostProcessing
  3. {
  4. /// <summary>
  5. /// This class holds settings for the Waveform monitor.
  6. /// </summary>
  7. [Serializable]
  8. public sealed class WaveformMonitor : Monitor
  9. {
  10. /// <summary>
  11. /// The exposure multiplier applied to the waveform values.
  12. /// </summary>
  13. public float exposure = 0.12f;
  14. /// <summary>
  15. /// The height of the rendered waveform.
  16. /// </summary>
  17. /// <remarks>
  18. /// Waveforms display localized values so the width is dynamic and depends on the current
  19. /// aspect ratio.
  20. /// </remarks>
  21. public int height = 256;
  22. ComputeBuffer m_Data;
  23. const int k_ThreadGroupSize = 256;
  24. const int k_ThreadGroupSizeX = 16;
  25. const int k_ThreadGroupSizeY = 16;
  26. internal override void OnDisable()
  27. {
  28. base.OnDisable();
  29. if (m_Data != null)
  30. m_Data.Release();
  31. m_Data = null;
  32. }
  33. internal override bool NeedsHalfRes()
  34. {
  35. return true;
  36. }
  37. internal override bool ShaderResourcesAvailable(PostProcessRenderContext context)
  38. {
  39. return context.resources.computeShaders.waveform;
  40. }
  41. internal override void Render(PostProcessRenderContext context)
  42. {
  43. // Waveform show localized data, so width depends on the aspect ratio
  44. float ratio = (context.width / 2f) / (context.height / 2f);
  45. int width = Mathf.FloorToInt(height * ratio);
  46. CheckOutput(width, height);
  47. exposure = Mathf.Max(0f, exposure);
  48. int count = width * height;
  49. if (m_Data == null)
  50. {
  51. m_Data = new ComputeBuffer(count, sizeof(uint) << 2);
  52. }
  53. else if (m_Data.count < count)
  54. {
  55. m_Data.Release();
  56. m_Data = new ComputeBuffer(count, sizeof(uint) << 2);
  57. }
  58. var compute = context.resources.computeShaders.waveform;
  59. var cmd = context.command;
  60. cmd.BeginSample("Waveform");
  61. var parameters = new Vector4(
  62. width,
  63. height,
  64. RuntimeUtilities.isLinearColorSpace ? 1 : 0,
  65. 0f
  66. );
  67. // Clear the buffer on every frame
  68. int kernel = compute.FindKernel("KWaveformClear");
  69. cmd.SetComputeBufferParam(compute, kernel, "_WaveformBuffer", m_Data);
  70. cmd.SetComputeVectorParam(compute, "_Params", parameters);
  71. cmd.DispatchCompute(compute, kernel, Mathf.CeilToInt(width / (float)k_ThreadGroupSizeX), Mathf.CeilToInt(height / (float)k_ThreadGroupSizeY), 1);
  72. // For performance reasons, especially on consoles, we'll just downscale the source
  73. // again to reduce VMEM stalls. Eventually the whole algorithm needs to be rewritten as
  74. // it's currently pretty naive.
  75. cmd.GetTemporaryRT(ShaderIDs.WaveformSource, width, height, 0, FilterMode.Bilinear, context.sourceFormat);
  76. cmd.BlitFullscreenTriangle(ShaderIDs.HalfResFinalCopy, ShaderIDs.WaveformSource);
  77. // Gather all pixels and fill in our waveform
  78. kernel = compute.FindKernel("KWaveformGather");
  79. cmd.SetComputeBufferParam(compute, kernel, "_WaveformBuffer", m_Data);
  80. cmd.SetComputeTextureParam(compute, kernel, "_Source", ShaderIDs.WaveformSource);
  81. cmd.SetComputeVectorParam(compute, "_Params", parameters);
  82. cmd.DispatchCompute(compute, kernel, width, Mathf.CeilToInt(height / (float)k_ThreadGroupSize), 1);
  83. cmd.ReleaseTemporaryRT(ShaderIDs.WaveformSource);
  84. // Generate the waveform texture
  85. var sheet = context.propertySheets.Get(context.resources.shaders.waveform);
  86. sheet.properties.SetVector(ShaderIDs.Params, new Vector4(width, height, exposure, 0f));
  87. sheet.properties.SetBuffer(ShaderIDs.WaveformBuffer, m_Data);
  88. cmd.BlitFullscreenTriangle(BuiltinRenderTextureType.None, output, sheet, 0);
  89. cmd.EndSample("Waveform");
  90. }
  91. }
  92. }