Пример #1
0
        static void QueueForAsyncBatchReadback(AsyncRequest <CaptureState> req,
                                               Channel channel,
                                               Func <AsyncRequest <CaptureState>, AsyncRequest.Result> functor,
                                               RenderTexture target)
        {
            Func <AsyncRequest <CaptureState>, AsyncRequest <CaptureState> .Result> wrapper;

            wrapper = (AsyncRequest <CaptureState> r) =>
            {
                BatchReadback.Instance().QueueReadback(target, bytes =>
                {
                    if (functor != null)
                    {
                        r.data.SetBuffer(channel, bytes);
                        r.Enqueue(functor);
                        r.Execute();
                    }

                    return(AsyncRequest.Result.Completed);
                });
                return(AsyncRequest.Result.Completed);
            };

            req.Enqueue(wrapper);
            req.Execute(AsyncRequest.ExecutionContext.EndOfFrame);
        }
Пример #2
0
        ReadbackRequest GetReadBackRequestFromPool(AsyncRequest <CaptureCamera.CaptureState> request, CaptureCamera.Channel channel, RenderTexture renderTexture)
        {
            ReadbackRequest rbr;

            if (_requestsPool.Count > 0)
            {
                rbr = _requestsPool.Dequeue();
            }
            else
            {
                rbr = new ReadbackRequest();
            }

            rbr.request  = request;
            rbr.channel  = channel;
            rbr.callback = request.data.SetFunctor(channel, null);

            if (rbr.renderTexture == null ||
                rbr.renderTexture.width != renderTexture.width ||
                rbr.renderTexture.height != renderTexture.height ||
                !rbr.renderTexture.CompareFormat(renderTexture.graphicsFormat))
            {
                rbr.renderTexture = new RenderTexture(renderTexture);
            }

            Graphics.Blit(renderTexture, rbr.renderTexture);

            return(rbr);
        }
Пример #3
0
        /// <summary>
        /// Setup a capture request for a channel. Once completed, the functor will be called with the channel data, in the format requested.
        /// </summary>
        /// <param name="request"> AsyncRequest to enqueue readbacks to. When all are completed, the request is marked completed. </param>
        /// <param name="channel"> The channel to capture data from (color, depth etc.) </param>
        /// <param name="camera"> The Camera to capture data from. </param>
        /// <param name="format"> The graphics format you want the data to be in. </param>
        /// <param name="functor"> The completion functor to call with the data. </param>
        /// <param name="forceFlipY"> Flags allowing you to force flipY for arbitrary channels. </param>
        /// <param name="readWrite"> Specify the desired color space conversion. If Default, then will be set to sRGB for SRP Color channel. </param>
        public static void SetupCaptureRequest
        (
            AsyncRequest <CaptureState> request,
            Channel channel,
            Camera camera,
            GraphicsFormat format,
            Func <AsyncRequest <CaptureState>, AsyncRequest.Result> functor,
            ForceFlip forceFlipY,
            RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default
        )
        {
            request.data.SetFunctor(channel, functor);

            Debug.Assert(request.data.camera == camera, "Capture: Camera must match the camera in request.data.camera");
            Debug.Assert(GraphicsUtilities.SupportsRenderTextureFormat(format), $"Capture: GraphicsFormat {format} not supported for {channel} channel");

            var material = SelectShaderVariantForChannel(channel, format);

            if (scriptableRenderPipeline)
            {
                request.data.SetTrigger(channel, (cb, rtid) => SetupCaptureRequestCommandBufferForChannel(request, channel, camera, cb, rtid, material, format, forceFlipY, readWrite, HandleReadbackCompletion));
            }
            else
            {
                SetupCaptureRequestCommandBufferForChannel(request, channel, camera, null, default, material, format, forceFlipY, readWrite, HandleReadbackCompletion);
Пример #4
0
 /// <summary>
 /// With different rendering pipelines, the moment when you need to capture a camera migh be different.
 /// This method will allow for the CaptureCamera class to operate as normal, while allowing the author
 /// of the render pipeline to decide when the work get dispatched.
 /// </summary>
 /// <param name="camera">The camera that you wish to queue a request for.</param>
 /// <param name="request">The request you are queueing for this camera.</param>
 public void QueueCameraRequest(Camera camera, AsyncRequest <CaptureCamera.CaptureState> request)
 {
     if (!_instance._pendingCameraRequests.ContainsKey(camera))
     {
         _instance._pendingCameraRequests.Add(camera, new List <AsyncRequest <CaptureCamera.CaptureState> >());
     }
     _instance._pendingCameraRequests[camera].Add(request);
 }
Пример #5
0
        /// <summary>
        /// Queue a rendertexture for readback. The readback will happen after the number of requests reaches the batchsize.
        /// </summary>
        /// <param name="request">The request associated with this batch readback instance.</param>
        /// <param name="channel">Which channel this readback is for.</param>
        /// <param name="renderTexture">Render texture to readback.</param>
        public void QueueReadback(AsyncRequest <CaptureCamera.CaptureState> request, CaptureCamera.Channel channel, RenderTexture renderTexture)
        {
            Debug.Assert(request.data.GetFunctor(channel) != null, $"QueueReadback request has no completion function for {channel} channel");

            var rbr = GetReadBackRequestFromPool(request, channel, renderTexture);

            _requestsBatch.Enqueue(rbr);
            if (_requestsBatch.Count == BatchSize)
            {
                Flush();
            }
        }
Пример #6
0
        static void SetupCaptureRequest
        (
            AsyncRequest <CaptureState> req,
            Channel channel,
            Camera camera,
            CameraEvent cameraEvent,
            BuiltinRenderTextureType source,
            GraphicsFormat format,
            Func <AsyncRequest <CaptureState>, AsyncRequest <CaptureState> .Result> functor,
            bool flipY
        )
        {
            if (functor != null)
            {
                // declared for possible capture, to avoid use from other threads.
                var cameraTargetTexture = camera.targetTexture;

                RenderTexture target1 = null;
                RenderTexture target2 = null;

                Action ReleaseTargets = () =>
                {
                    if (target1 != null && target1 != cameraTargetTexture)
                    {
                        RenderTexture.ReleaseTemporary(target1);
                        target1 = null;
                    }
                    if (target2 != null)
                    {
                        Debug.Assert(target2 != cameraTargetTexture);
                        RenderTexture.ReleaseTemporary(target2);
                        target2 = null;
                    }
                };

                Material depthMaterial = null;
                if (source == BuiltinRenderTextureType.Depth)
                {
                    depthMaterial = SelectDepthShaderVariant(format);
                }

#if UNITY_2019_3_OR_NEWER
                if (scriptableRenderPipeline)
                {
                    if (CaptureOptions.useBatchReadback)
                    {
                        QueueForAsyncBatchReadback(req, channel, functor, SetupRenderTargets(ref target1, ref target2, camera, null, format, cameraTargetTexture, depthMaterial, flipY));
                    }
                    else
                    {
                        req.data.SetFunctor(channel, (AsyncRequest <CaptureState> r) =>
                        {
                            var target = SetupRenderTargets(ref target1, ref target2, camera, null, format, cameraTargetTexture, depthMaterial, flipY);
                            if (GraphicsUtilities.SupportsAsyncReadback())
                            {
                                AsyncGPUReadback.Request(target, 0, (AsyncGPUReadbackRequest request) =>
                                {
                                    ReleaseTargets();
                                    if (request.hasError)
                                    {
                                        req.error = true;
                                    }
                                    else
                                    {
                                        if (functor != null)
                                        {
                                            req.data.SetBuffer(channel, request.GetData <byte>().ToArray());
                                            req.Enqueue(functor);
                                            req.Execute();
                                        }
                                    }
                                });
                            }
                            else
                            {
                                r.data.SetBuffer(channel, GraphicsUtilities.GetPixelsSlow(target));
                                ReleaseTargets();
                                req.Enqueue(functor);
                                req.Execute();
                            }
                            return(AsyncRequest.Result.None);
                        });
                    }
                }
                else
#endif // UNITY_2019_3_OR_NEWER
                {
                    req.data.SetFunctor(channel, functor);

                    CommandBuffer commandBuffer = GetCommandBufferForCamera(cameraEvent, camera);
                    commandBuffer.name = $"CaptureCamera.{channel.ToString()}";

                    var target = SetupRenderTargets(ref target1, ref target2, camera, commandBuffer, format, cameraTargetTexture, depthMaterial, flipY);

                    if (GraphicsUtilities.SupportsAsyncReadback())
                    {
                        #if UNITY_2019_3_OR_NEWER
                        if (CaptureOptions.useBatchReadback)
                        {
                            QueueForAsyncBatchReadback(req, channel, functor, target);
                            ReleaseTargets();
                        }
                        else
                        #endif
                        {
                            commandBuffer.RequestAsyncReadback(target, (AsyncGPUReadbackRequest request) =>
                            {
                                commandBuffer.Clear();
                                if (request.hasError)
                                {
                                    req.error = true;
                                }
                                else
                                {
                                    functor = req.data.SetFunctor(channel, null);
                                    if (functor != null)
                                    {
                                        req.data.SetBuffer(channel, request.GetData <byte>().ToArray());
                                        req.Enqueue(functor);
                                        req.Execute();
                                    }
                                }
                                ReleaseTargets();
                            });
                        }
                    }
                    else
                    {
                        Func <AsyncRequest <CaptureState>, AsyncRequest <CaptureState> .Result> wrapper;
#if UNITY_2019_3_OR_NEWER
                        if (CaptureOptions.useBatchReadback)
                        {
                            wrapper = (AsyncRequest <CaptureState> r) =>
                            {
                                BatchReadback.Instance().QueueReadback(target, data =>
                                {
                                    r.data.SetBuffer(channel, data);
                                    ReleaseTargets();
                                    r.Enqueue(functor);
                                    r.Execute();
                                    return(AsyncRequest.Result.Completed);
                                });
                                return(AsyncRequest.Result.Completed);
                            };
                        }
                        else
#endif // UNITY_2019_3_OR_NEWER
                        {
                            wrapper = (AsyncRequest <CaptureState> r) =>
                            {
                                r.data.SetBuffer(channel, GraphicsUtilities.GetPixelsSlow(target));
                                ReleaseTargets();
                                r.Enqueue(functor);
                                r.Execute();
                                return(AsyncRequest.Result.Completed);
                            };
                        }
                        req.Enqueue(wrapper);
                        req.Execute(AsyncRequest.ExecutionContext.EndOfFrame);
                    }
                }
            }
        }