From e053c92678e52ad5a0633166416d73d4f31bcc81 Mon Sep 17 00:00:00 2001 From: Thomas Hourdel Date: Tue, 11 Jul 2017 16:01:51 +0200 Subject: [PATCH] Improved waveform performances on consoles Will need to rewrite this at some point, it uses quite a naive approach --- .../Runtime/Monitors/WaveformMonitor.cs | 16 ++++++++++----- PostProcessing/Runtime/PostProcessMonitors.cs | 4 +--- PostProcessing/Runtime/Utils/ShaderIDs.cs | 1 + PostProcessing/Shaders/Debug/Waveform.compute | 20 +++++++++---------- PostProcessing/Shaders/Debug/Waveform.shader | 2 +- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/PostProcessing/Runtime/Monitors/WaveformMonitor.cs b/PostProcessing/Runtime/Monitors/WaveformMonitor.cs index 7092999f..2dfd7c29 100644 --- a/PostProcessing/Runtime/Monitors/WaveformMonitor.cs +++ b/PostProcessing/Runtime/Monitors/WaveformMonitor.cs @@ -45,8 +45,8 @@ internal override void Render(PostProcessRenderContext context) cmd.BeginSample("Waveform"); var parameters = new Vector4( - context.width / 2, - context.height / 2, + width, + height, RuntimeUtilities.isLinearColorSpace ? 1 : 0, 0f ); @@ -55,15 +55,21 @@ internal override void Render(PostProcessRenderContext context) int kernel = compute.FindKernel("KWaveformClear"); cmd.SetComputeBufferParam(compute, kernel, "_WaveformBuffer", m_Data); cmd.SetComputeVectorParam(compute, "_Params", parameters); - cmd.SetComputeVectorParam(compute, "_BufferParams", new Vector4(width, height, 0f, 0f)); cmd.DispatchCompute(compute, kernel, Mathf.CeilToInt(width / 16f), Mathf.CeilToInt(height / 16f), 1); + // For performance reasons, especially on consoles, we'll just downscale the source + // again to reduce VMEM stalls. Eventually the whole algorithm needs to be rewritten as + // it's currently pretty naive. + cmd.GetTemporaryRT(ShaderIDs.WaveformSource, width, height, 0, FilterMode.Bilinear, context.sourceFormat); + cmd.BlitFullscreenTriangle(ShaderIDs.HalfResFinalCopy, ShaderIDs.WaveformSource); + // Gather all pixels and fill in our waveform kernel = compute.FindKernel("KWaveformGather"); cmd.SetComputeBufferParam(compute, kernel, "_WaveformBuffer", m_Data); - cmd.SetComputeTextureParam(compute, kernel, "_Source", ShaderIDs.HalfResFinalCopy); + cmd.SetComputeTextureParam(compute, kernel, "_Source", ShaderIDs.WaveformSource); cmd.SetComputeVectorParam(compute, "_Params", parameters); - cmd.DispatchCompute(compute, kernel, Mathf.CeilToInt(context.width / 2f), Mathf.CeilToInt(context.width / 2f / 256f), 1); + cmd.DispatchCompute(compute, kernel, width, Mathf.CeilToInt(height / 256f), 1); + cmd.ReleaseTemporaryRT(ShaderIDs.WaveformSource); // Generate the waveform texture var sheet = context.propertySheets.Get(context.resources.shaders.waveform); diff --git a/PostProcessing/Runtime/PostProcessMonitors.cs b/PostProcessing/Runtime/PostProcessMonitors.cs index 4fb47f0f..1ef2f18c 100644 --- a/PostProcessing/Runtime/PostProcessMonitors.cs +++ b/PostProcessing/Runtime/PostProcessMonitors.cs @@ -56,9 +56,7 @@ internal void Render(PostProcessRenderContext context) if (needHalfRes) { - var format = RenderTextureFormat.ARGBHalf; - format = SystemInfo.SupportsRenderTextureFormat(format) ? format : RenderTextureFormat.ARGB32; - cmd.GetTemporaryRT(ShaderIDs.HalfResFinalCopy, context.width / 2, context.height / 2, 0, FilterMode.Bilinear, format); + cmd.GetTemporaryRT(ShaderIDs.HalfResFinalCopy, context.width / 2, context.height / 2, 0, FilterMode.Bilinear, context.sourceFormat); cmd.Blit(context.destination, ShaderIDs.HalfResFinalCopy); } diff --git a/PostProcessing/Runtime/Utils/ShaderIDs.cs b/PostProcessing/Runtime/Utils/ShaderIDs.cs index 6616ba8e..cd1832f5 100644 --- a/PostProcessing/Runtime/Utils/ShaderIDs.cs +++ b/PostProcessing/Runtime/Utils/ShaderIDs.cs @@ -101,6 +101,7 @@ static class ShaderIDs internal static readonly int Interp = Shader.PropertyToID("_Interp"); internal static readonly int HalfResFinalCopy = Shader.PropertyToID("_HalfResFinalCopy"); + internal static readonly int WaveformSource = Shader.PropertyToID("_WaveformSource"); internal static readonly int WaveformBuffer = Shader.PropertyToID("_WaveformBuffer"); internal static readonly int VectorscopeBuffer = Shader.PropertyToID("_VectorscopeBuffer"); } diff --git a/PostProcessing/Shaders/Debug/Waveform.compute b/PostProcessing/Shaders/Debug/Waveform.compute index 0d7e7de8..d28377ea 100644 --- a/PostProcessing/Shaders/Debug/Waveform.compute +++ b/PostProcessing/Shaders/Debug/Waveform.compute @@ -7,18 +7,16 @@ SamplerState sampler_Source; CBUFFER_START(Params) float4 _Params; // x: source width, y: source height, z: linear, w: unused - float4 _BufferParams; // x: buffer width, y: buffer height, zw: unused CBUFFER_END #pragma kernel KWaveformGather [numthreads(1, 256, 1)] -void KWaveformGather(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID) +void KWaveformGather(uint2 dispatchThreadId : SV_DispatchThreadID) { // Gather local group histogram if (dispatchThreadId.x < uint(_Params.x) && dispatchThreadId.y < uint(_Params.y)) { - float2 coords = float2(dispatchThreadId) / _Params.xy; - float3 color = _Source.SampleLevel(sampler_Source, coords, 0).xyz; + float3 color = _Source[dispatchThreadId].rgb; color = saturate(color); // We want a gamma-corrected histogram (like Photoshop & all) @@ -26,12 +24,12 @@ void KWaveformGather(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupTh color = LinearToSRGB(color); // Convert channel values to histogram bins - uint3 idx = (uint3)(round(color * (_BufferParams.y - 1))); + uint3 idx = (uint3)(round(color * (_Params.y - 1))); + idx += dispatchThreadId.x * _Params.y; - uint bufferX = uint(round(coords.x * (_BufferParams.x - 1))); - if (idx.x > 0u) InterlockedAdd(_WaveformBuffer[idx.x * uint(_BufferParams.x) + bufferX].x, 1u); // Red - if (idx.y > 0u) InterlockedAdd(_WaveformBuffer[idx.y * uint(_BufferParams.x) + bufferX].y, 1u); // Green - if (idx.z > 0u) InterlockedAdd(_WaveformBuffer[idx.z * uint(_BufferParams.x) + bufferX].z, 1u); // Blue + if (idx.x > 0u) InterlockedAdd(_WaveformBuffer[idx.x].x, 1u); // Red + if (idx.y > 0u) InterlockedAdd(_WaveformBuffer[idx.y].y, 1u); // Green + if (idx.z > 0u) InterlockedAdd(_WaveformBuffer[idx.z].z, 1u); // Blue } } @@ -39,6 +37,6 @@ void KWaveformGather(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupTh [numthreads(16, 16, 1)] void KWaveformClear(uint2 dispatchThreadId : SV_DispatchThreadID) { - if (dispatchThreadId.x < uint(_BufferParams.x) && dispatchThreadId.y < uint(_BufferParams.y)) - _WaveformBuffer[dispatchThreadId.y * uint(_BufferParams.x) + dispatchThreadId.x] = uint4(0u, 0u, 0u, 0u); + if (dispatchThreadId.x < uint(_Params.x) && dispatchThreadId.y < uint(_Params.y)) + _WaveformBuffer[dispatchThreadId.y * uint(_Params.x) + dispatchThreadId.x] = uint4(0u, 0u, 0u, 0u); } diff --git a/PostProcessing/Shaders/Debug/Waveform.shader b/PostProcessing/Shaders/Debug/Waveform.shader index 52783043..eec81cb5 100644 --- a/PostProcessing/Shaders/Debug/Waveform.shader +++ b/PostProcessing/Shaders/Debug/Waveform.shader @@ -27,7 +27,7 @@ Shader "Hidden/PostProcessing/Debug/Waveform" float3 color = float3(0.0, 0.0, 0.0); uint2 uvI = i.vertex.xy; - float3 w = _WaveformBuffer[uvI.y * _Params.x + uvI.x]; + float3 w = _WaveformBuffer[uvI.x * _Params.y + uvI.y].xyz; color += red * w.r; color += green * w.g;