diff --git a/Assets/Scripts/DepthRenderPassFeature.cs b/Assets/Scripts/DepthRenderPassFeature.cs index e1c9d62..66249ee 100644 --- a/Assets/Scripts/DepthRenderPassFeature.cs +++ b/Assets/Scripts/DepthRenderPassFeature.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; @@ -8,24 +9,36 @@ using UnityEngine.XR; public class DepthRenderPassFeature : ScriptableRendererFeature { - class DepthRenderPass : ScriptableRenderPass + private static Dictionary>> m_PendingRequests = new(); + + internal class DepthRenderPass : ScriptableRenderPass { - public static Action OnDepthReady; - public static Queue Requests; - public static Queue Answers; + public static Task RequestDepthDataAsync(int id) + { + if(m_PendingRequests == null) + m_PendingRequests = new Dictionary>>(); + + var tcs = new TaskCompletionSource(); + int key = id; + if (!m_PendingRequests.TryGetValue(key, out var queue)) + { + queue = new Queue>(); + m_PendingRequests.Add(key, queue); + } + queue.Enqueue(tcs); + return tcs.Task; + } ProfilingSampler m_ProfilingSampler = new ProfilingSampler("ColorBlit"); private Material material; private RTHandle rtHandle; + private RTHandle copyRtHandle; private bool depth = false; private ComputeBuffer computeBuffer; public DepthRenderPass(Material material) { this.material = material; - - Requests = new Queue(); - Answers = new Queue(); } public void SetTarget(RTHandle handle, bool depth) @@ -48,6 +61,8 @@ public class DepthRenderPassFeature : ScriptableRendererFeature public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { ConfigureTarget(rtHandle); + var desc = renderingData.cameraData.cameraTargetDescriptor; + RenderingUtils.ReAllocateIfNeeded(ref copyRtHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp); } // Here you can implement the rendering logic. @@ -57,22 +72,31 @@ public class DepthRenderPassFeature : ScriptableRendererFeature public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { CommandBuffer cmd = CommandBufferPool.Get(); - //RTHandle rt = renderingData.cameraData.renderer.cameraColorTargetHandle; using (new ProfilingScope(cmd, m_ProfilingSampler)) { Blitter.BlitCameraTexture(cmd, rtHandle, rtHandle, material, 0); - if(Requests.Count > 0) - { - Requests.Dequeue(); - float[] resultArray = new float[computeBuffer.count]; - computeBuffer.GetData(resultArray); - Answers.Enqueue(resultArray); - } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); + + lock(m_PendingRequests) + { + if (m_PendingRequests.Count > 0) + { + int key = renderingData.cameraData.camera.GetInstanceID(); + if (m_PendingRequests.TryGetValue(key, out var queue) && queue.Count > 0) + { + float[] result = new float[computeBuffer.count]; + material.SetBuffer("distBuffer", computeBuffer); + Graphics.SetRandomWriteTarget(1, computeBuffer,false); + computeBuffer.GetData(result); + while (queue.TryDequeue(out var tcs)) + tcs.TrySetResult(result); + } + } + } } // Cleanup any allocated resources that were created during the execution of this render pass. @@ -100,18 +124,6 @@ public class DepthRenderPassFeature : ScriptableRendererFeature { DestroyComputeBuffer(); } - - if (Requests != null) - { - Requests.Clear(); - Requests = null; - } - - if (Answers != null) - { - Answers.Clear(); - Answers = null; - } } public void DestroyComputeBuffer() @@ -169,8 +181,16 @@ public class DepthRenderPassFeature : ScriptableRendererFeature Destroy(material); #endif m_ScriptablePass.Dispose(); + + if (m_PendingRequests != null) + { + foreach (var queue in m_PendingRequests.Values) + { + while (queue.TryDequeue(out var tcs)) + tcs.TrySetCanceled(); + } + m_PendingRequests.Clear(); + } } } - - diff --git a/Assets/Scripts/DepthTester.cs b/Assets/Scripts/DepthTester.cs index 07f5ed3..5ce5312 100644 --- a/Assets/Scripts/DepthTester.cs +++ b/Assets/Scripts/DepthTester.cs @@ -1,5 +1,7 @@ using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; using UnityEditor.Rendering; using UnityEngine; using UnityEngine.UIElements; @@ -14,15 +16,20 @@ public class DepthTester : MonoBehaviour private Camera camera; private float farPlane; private float nearPlane; + private int id; + private Task task; + // Start is called before the first frame update void Start() { camera = GetComponent(); + id = camera.GetInstanceID(); farPlane = camera.farClipPlane; nearPlane = camera.nearClipPlane; texture = BlendShaderController.CreateTextures(1, FrameRes, FrameRes, false)[0]; camera.targetTexture = texture; texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false); + task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id); } private void OnDisable() @@ -40,18 +47,29 @@ public class DepthTester : MonoBehaviour private void Update() { - Vector3 depthPos = transform.position + transform.right * Offset; - RenderTexture.active = texture; - texture2D.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); - texture2D.Apply(); - Color pixel = texture2D.GetPixel(texture.width / 2, texture2D.height / 2); - float depth = pixel.r; - float depthDist = depth * farPlane; - Debug.DrawLine(depthPos, depthPos + transform.forward * depthDist, Color.green); + lock(task) + { + if(task != null) + { + if(task.IsCompletedSuccessfully) + { + float[] depths = task.Result; + int centerIndex = (FrameRes / 2) * FrameRes + (FrameRes / 2); + float depth = depths[centerIndex]; + Vector3 depthPos = transform.position + transform.right * Offset; + Debug.DrawLine(depthPos, depthPos + transform.forward * depth, Color.green); + Debug.Log($"chto to risuet: dist:{depth}; depthsCount: {depths.Length}"); + task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id); + } + else if(task.IsCanceled) + { + task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id); + } + } + } Vector3 raycastPos = transform.position - transform.right * Offset; float rayDistance = 0; - if(Physics.Raycast(transform.position, transform.forward, out var hit, 100)) { rayDistance = hit.distance; diff --git a/Assets/Shaders/RenderDepth.shader b/Assets/Shaders/RenderDepth.shader index 3cadf3b..a997c7e 100644 --- a/Assets/Shaders/RenderDepth.shader +++ b/Assets/Shaders/RenderDepth.shader @@ -26,7 +26,7 @@ Shader "Hidden/RenderDepth" sampler2D _MainTex; - RWStructuredBuffer distBuffer; + RWStructuredBuffer distBuffer : register(u1); int res; bool _RenderDepth; @@ -42,7 +42,7 @@ Shader "Hidden/RenderDepth" real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(i.texcoord)); #endif depth = Linear01Depth(depth, _ZBufferParams); - distBuffer[pixelIdx.y * _ScaledScreenParams.x + pixelIdx.x] = depth * _ProjectionParams.z; + distBuffer[pixelIdx.y * (uint)_ScaledScreenParams.x + pixelIdx.x] = depth * _ProjectionParams.z; return _RenderDepth ? float4(depth, depth, depth, 1) : float4(color, 1); } ENDHLSL