static void SetupAlternateGetBlockSize()
 {
     _blockSizeMap = new Dictionary <GraphicsFormat, int>();
     foreach (GraphicsFormat format in Enum.GetValues(typeof(GraphicsFormat)))
     {
         _blockSizeMap[format]      = (int)GraphicsFormatUtility.GetBlockSize(format);
         _componentCountMap[format] = (int)GraphicsFormatUtility.GetComponentCount(format);
     }
 }
        /// <summary>
        /// Get the number of components for a given format.
        /// </summary>
        /// <param name="format">Graphics format you are using.</param>
        /// <returns>Returns the number of components.</returns>
        public static int GetComponentCount(GraphicsFormat format)
        {
#if UNITY_2019_3_OR_NEWER
            return((int)GraphicsFormatUtility.GetComponentCount(format));
#else
            if (!_componentCountMap.ContainsKey(format))
            {
                throw new NotSupportedException("ComponentCountMap doesn't contain key for format");
            }
            return(_componentCountMap[format]);
#endif
        }
        // formats with higher sorting code appear first on the dropdown lists
        static uint GetSortCodeForFormat(TextureFormat fmt)
        {
            var f = GraphicsFormatUtility.GetGraphicsFormat(fmt, false);

            // first by: normalized, floating point, integer
            uint type;

            if (GraphicsFormatUtility.IsNormFormat(f))
            {
                type = 3;
            }
            else if (GraphicsFormatUtility.IsHalfFormat(f) || GraphicsFormatUtility.IsFloatFormat(f))
            {
                type = 2;
            }
            else if (GraphicsFormatUtility.IsIntegerFormat(f))
            {
                type = 1;
            }
            else
            {
                type = 0;
            }

            // then by component count: RGBA, RGB, RG, R/A
            var components = GraphicsFormatUtility.GetComponentCount(f);

            // then compression: first compressed regular, then compressed Crunch, then uncompressed
            uint compression = 0;

            if (GraphicsFormatUtility.IsCompressedFormat(f))
            {
                compression++;
                if (!GraphicsFormatUtility.IsCrunchFormat(fmt))
                {
                    compression++;
                }
            }

            return((type << 24) | (components << 16) | (compression << 8));
        }
        /// <summary>
        /// Perform the readback from the provided Render texture using ReadPixels API.
        /// </summary>
        /// <param name="renderTexture">Input source Render texture for the readback.</param>
        /// <returns>Returns a byte array of the RGB data retrieved from the readback.</returns>
        /// <exception cref="NotSupportedException"></exception>
        public static byte[] GetPixelsSlow(RenderTexture renderTexture)
        {
            var graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(renderTexture.format, false);
            var pixelSize      = GraphicsUtilities.GetBlockSize(graphicsFormat);
            var channels       = GraphicsFormatUtility.GetComponentCount(graphicsFormat);
            var channelSize    = pixelSize / channels;
            var rect           = new Rect(0, 0, renderTexture.width, renderTexture.height);

            // for RGB(A) we can just return the raw data.
            if (channels >= 3 && channels <= 4)
            {
                var texture = new Texture2D(renderTexture.width, renderTexture.height);
                RenderTexture.active = renderTexture;
                texture.ReadPixels(rect, 0, 0);
                RenderTexture.active = null;
                var data = texture.GetRawTextureData();
                UnityEngine.Object.Destroy(texture);
                return(data);
            }
            else
            {
                Debug.Assert(channels == 1, "Can only handle a single channel RT.");

                // Read pixels must be one of RGBA32, ARGB32, RGB24, RGBAFloat or RGBAHalf.
                // So R16 and RFloat will be converted to RGBAFloat.
                var texture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBAFloat, false);

                RenderTexture.active = renderTexture;
                texture.ReadPixels(rect, 0, 0);
                RenderTexture.active = null;

                var length = renderTexture.width * renderTexture.height;
                var input  = ArrayUtilities.Cast <float>(texture.GetRawTextureData());
                UnityEngine.Object.Destroy(texture);

                Array output = null;

                int index = 0;
                switch (channelSize)
                {
                case 2:
                    short[] shorts    = ArrayUtilities.Allocate <short>(length);
                    var     si        = 0;
                    var     numerator = (1 << 16) - 1;
                    while (index < length)
                    {
                        shorts[index++] = (short)(numerator * input[si]);
                        si += 4;
                    }
                    output = shorts;
                    break;

                case 4:
                    float[] floats = ArrayUtilities.Allocate <float>(length);
                    var     fi     = 0;
                    while (index < length)
                    {
                        floats[index++] = input[fi];
                        fi += 4;
                    }
                    output = floats;
                    break;

                default:
                    throw new NotSupportedException();
                }

                return(ArrayUtilities.Cast <byte>(output));
            }
        }
    private void ProcessBatch()
    {
        while (_requestsBatch.Count > 0)
        {
            var request        = _requestsBatch.Dequeue();
            var graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(request.renderTexture.format, false);
            var pixelSize      = GraphicsFormatUtility.GetBlockSize(graphicsFormat);
            var channels       = GraphicsFormatUtility.GetComponentCount(graphicsFormat);
            var channelSize    = pixelSize / channels;
            var rect           = new Rect(0, 0, request.renderTexture.width, request.renderTexture.height);

            if (channels >= 3 && channels <= 4)
            {
                if (request.texture == null)
                {
                    request.texture = new Texture2D(request.renderTexture.width, request.renderTexture.height, request.renderTexture.graphicsFormat, TextureCreationFlags.None);
                }
                RenderTexture.active = request.renderTexture;
                request.texture.ReadPixels(rect, 0, 0);
                request.InvokeCallback(request.texture.GetRawTextureData());
                RenderTexture.active = null;
            }
            else
            {
                Debug.Assert(channels == 1, "Can only handle a single channel RT.");

                // Read pixels must be one of RGBA32, ARGB32, RGB24, RGBAFloat or RGBAHalf.
                // So R16 and RFloat will be converted to RGBAFloat.
                var texture = new Texture2D(request.renderTexture.width, request.renderTexture.height, TextureFormat.RGBAFloat, false);
                RenderTexture.active = request.renderTexture;
                texture.ReadPixels(rect, 0, 0);
                RenderTexture.active = null;

                var length = request.renderTexture.width * request.renderTexture.height;
                var input  = ArrayUtilities.Cast <float>(texture.GetRawTextureData());
                UnityEngine.Object.Destroy(texture);

                int index = 0;
                switch (channelSize)
                {
                case 2:
                    short[] shorts    = ArrayUtilities.Allocate <short>(length);
                    var     si        = 0;
                    var     numerator = (1 << 16) - 1;
                    while (index < length)
                    {
                        shorts[index++] = (short)(numerator * input[si]);
                        si += 4;
                    }
                    var shortOutputNativeArray = new NativeArray <byte>(ArrayUtilities.Cast <byte>(shorts), Allocator.Persistent);
                    request.InvokeCallback(ArrayUtilities.Cast <byte>(shorts));
                    break;

                case 4:
                    float[] floats = ArrayUtilities.Allocate <float>(length);
                    var     fi     = 0;
                    while (index < length)
                    {
                        floats[index++] = input[fi];
                        fi += 4;
                    }
                    var floatOutputNativeArray = new NativeArray <byte>(ArrayUtilities.Cast <byte>(floats), Allocator.Persistent);
                    request.InvokeCallback(ArrayUtilities.Cast <byte>(floats));
                    break;

                default:
                    throw new NotSupportedException();
                }
            }


            _requestsPool.Enqueue(request);
        }
    }