Ejemplo n.º 1
0
    public void WaitForCompletion()
    {
        if (Status != AsyncTextureReaderStatus.Reading)
        {
            return;
        }

        Update();

        if (Type == ReadType.Native)
        {
            if (!NativeReadRequest.done)
            {
                NativeReadRequest.WaitForCompletion();
            }
            Update();
        }
        else if (Type == ReadType.LinuxOpenGL)
        {
            if (LinuxId >= 0)
            {
                while (AsyncTextureReaderImports.AsyncTextureReaderGetStatus(LinuxId) != AsyncTextureReaderStatus.Finished)
                {
                    AsyncTextureReaderImports.AsyncTextureReaderWaitForCompletion(LinuxId);
                    GL.IssuePluginEvent(LinuxUpdate, LinuxId);
                }
                Status = AsyncTextureReaderStatus.Reading;
            }
            Update();
        }
    }
Ejemplo n.º 2
0
    public void Start()
    {
        Debug.Assert(Status != AsyncTextureReaderStatus.Reading);

        if (Type == ReadType.None)
        {
            return;
        }
        else if (Type == ReadType.Native)
        {
            NativeReadRequest = AsyncGPUReadback.Request(Texture, 0, NativeReadFormat);
        }
        else if (Type == ReadType.LinuxOpenGL)
        {
            if (LinuxId >= 0)
            {
                unsafe
                {
                    AsyncTextureReaderImports.AsyncTextureReaderStart(LinuxId, new IntPtr(Data.GetUnsafePtr()));
                }
                GL.IssuePluginEvent(LinuxUpdate, LinuxId);
            }
        }

        Status = AsyncTextureReaderStatus.Reading;
    }
Ejemplo n.º 3
0
 public void Destroy()
 {
     if (Type == ReadType.LinuxOpenGL)
     {
         AsyncTextureReaderImports.AsyncTextureReaderDestroy(LinuxId);
         GL.IssuePluginEvent(LinuxUpdate, LinuxId);
         LinuxId = -1;
     }
 }
Ejemplo n.º 4
0
 public void Destroy()
 {
     if (Type == ReadType.LinuxOpenGL)
     {
         AsyncTextureReaderImports.AsyncTextureReaderDestroy(LinuxId);
         GL.IssuePluginEvent(LinuxUpdate, LinuxId);
         LinuxId = -1;
         if (Data.IsCreated)
         {
             Data.Dispose();
         }
     }
     else if (Type == ReadType.Sync)
     {
         if (Data.IsCreated)
         {
             Data.Dispose();
         }
     }
 }
Ejemplo n.º 5
0
    public AsyncTextureReader(RenderTexture texture)
    {
        Status  = AsyncTextureReaderStatus.Idle;
        Texture = texture;

        // WARNING - if you change this, you'll need to update code below
        Debug.Assert(
            texture.format == RenderTextureFormat.ARGBFloat ||
            texture.format == RenderTextureFormat.RGFloat ||
            texture.format == RenderTextureFormat.RFloat ||
            texture.format == RenderTextureFormat.ARGB32);

        Debug.Assert(texture.dimension == TextureDimension.Tex2D);

        var sync = System.Environment.GetEnvironmentVariable("FORCE_SYNC_GPU_READBACK");

        if (sync == null)
        {
            if (SystemInfo.supportsAsyncGPUReadback)
            {
                int length;
                Type = ReadType.Native;
                if (texture.format == RenderTextureFormat.ARGBFloat)
                {
                    BytesPerPixel    = 16;
                    NativeReadFormat = TextureFormat.RGBAFloat;
                    length           = Texture.width * Texture.height;
                }
                else if (texture.format == RenderTextureFormat.RGFloat)
                {
                    BytesPerPixel    = 8;
                    NativeReadFormat = TextureFormat.RGFloat;
                    length           = Texture.width * Texture.height;
                }
                else if (texture.format == RenderTextureFormat.RFloat)
                {
                    BytesPerPixel    = 4;
                    NativeReadFormat = TextureFormat.RFloat;
                    length           = Texture.width * Texture.height;
                }
                else // if (texture.format == RenderTextureFormat.ARGB32)
                {
                    BytesPerPixel    = 3;
                    NativeReadFormat = TextureFormat.RGB24;
                    length           = Texture.width * Texture.height * BytesPerPixel;
                }
                Data = new NativeArray <T>(length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
                return;
            }

            if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore &&
                SystemInfo.operatingSystemFamily == OperatingSystemFamily.Linux)
            {
                var version = SystemInfo.graphicsDeviceVersion;
                version = version.Split(new char[] { ' ' }, 3)[1];
                var parts = version.Split(new char[] { '.' });
                int major = int.Parse(parts[0]);
                int minor = int.Parse(parts[1]);
                //Debug.Log($"OpenGL version = {major}.{minor}");

                if (major > 3 || major == 3 && minor >= 2) // GL_ARB_sync
                {
                    debug = new DebugDelegate(DebugCallback);
                    AsyncTextureReaderImports.AsyncTextureReaderSetDebug(Marshal.GetFunctionPointerForDelegate(debug));

                    int length;
                    if (texture.format == RenderTextureFormat.ARGBFloat)
                    {
                        BytesPerPixel = 16;
                        length        = Texture.width * Texture.height;
                    }
                    else if (texture.format == RenderTextureFormat.RGFloat)
                    {
                        BytesPerPixel = 8;
                        length        = Texture.width * Texture.height;
                    }
                    else if (texture.format == RenderTextureFormat.RFloat)
                    {
                        BytesPerPixel = 4;
                        length        = Texture.width * Texture.height;
                    }
                    else // if (texture.format == RenderTextureFormat.ARGB32)
                    {
                        BytesPerPixel = 4;
                        length        = Texture.width * Texture.height * BytesPerPixel;
                    }

                    texture.Create();
                    Data    = new NativeArray <T>(length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
                    LinuxId = AsyncTextureReaderImports.AsyncTextureReaderCreate(texture.GetNativeTexturePtr(), Data.Length);
                    if (LinuxId >= 0)
                    {
                        LinuxUpdate = AsyncTextureReaderImports.AsyncTextureReaderGetUpdate();
                        GL.IssuePluginEvent(LinuxUpdate, LinuxId);

                        Type = ReadType.LinuxOpenGL;
                    }
                    else
                    {
                        Debug.Log("ERROR: failed to create native AsyncTextureReader");
                    }
                    return;
                }
            }
        }

        if (texture.format != RenderTextureFormat.ARGB32)
        {
            Debug.Log("ERROR: fallback AsyncTextureReader supports only ARGB32 texture format");
            Type = ReadType.None;
            return;
        }

        Type          = ReadType.Sync;
        BytesPerPixel = 3;
        Data          = new NativeArray <T>(texture.width * texture.height * BytesPerPixel, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
        ReadTexture   = new Texture2D(texture.width, texture.height, TextureFormat.RGB24, false);
    }
Ejemplo n.º 6
0
    public void Update()
    {
        if (Texture.IsCreated() == false)
        {
            // need to recreate native RenderTexture handle, because it is lost
            // this happens, for example, when you resize Unity Editor window on Linux
            if (Type == ReadType.Native)
            {
                NativeReadRequest.WaitForCompletion();
            }
            else if (Type == ReadType.LinuxOpenGL)
            {
                AsyncTextureReaderImports.AsyncTextureReaderDestroy(LinuxId);
                GL.IssuePluginEvent(LinuxUpdate, LinuxId);

                Texture.Create();
                LinuxId = AsyncTextureReaderImports.AsyncTextureReaderCreate(Texture.GetNativeTexturePtr(), Data.Length);
                GL.IssuePluginEvent(LinuxUpdate, LinuxId);
            }

            Status = AsyncTextureReaderStatus.Idle;
            return;
        }

        if (Status != AsyncTextureReaderStatus.Reading)
        {
            return;
        }

        if (Type == ReadType.Native)
        {
            if (NativeReadRequest.done)
            {
                if (NativeReadRequest.layerCount == 0)
                {
                    // start reading request was not issued yet
                    return;
                }
                // this will happen only if AsyncGPUReadback.Request was issued
                if (NativeReadRequest.hasError)
                {
                    return;
                }

                Data.CopyFrom(NativeReadRequest.GetData <T>());
                Status = AsyncTextureReaderStatus.Finished;
            }
        }
        else if (Type == ReadType.LinuxOpenGL)
        {
            if (LinuxId >= 0)
            {
                Status = AsyncTextureReaderImports.AsyncTextureReaderGetStatus(LinuxId);
                if (Status != AsyncTextureReaderStatus.Finished)
                {
                    GL.IssuePluginEvent(LinuxUpdate, LinuxId);
                    Status = AsyncTextureReaderImports.AsyncTextureReaderGetStatus(LinuxId);
                }
            }
            else
            {
                Status = AsyncTextureReaderStatus.Finished;
            }
        }
        else if (Type == ReadType.Sync)
        {
            var current = RenderTexture.active;
            RenderTexture.active = Texture;
            ReadTexture.ReadPixels(new Rect(0, 0, Texture.width, Texture.height), 0, 0);
            ReadTexture.Apply();
            RenderTexture.active = current;

            int    size  = ReadTexture.width * ReadTexture.height * BytesPerPixel;
            byte[] bytes = ReadTexture.GetRawTextureData();
            unsafe
            {
                fixed(void *ptr = bytes)
                {
                    Buffer.MemoryCopy(ptr, Data.GetUnsafePtr(), size, size);
                }
            }
            Status = AsyncTextureReaderStatus.Finished;
        }
    }
Ejemplo n.º 7
0
    public AsyncTextureReader(RenderTexture texture)
    {
        Status  = AsyncTextureReaderStatus.Idle;
        Texture = texture;

        // WARNING - if you change this, you'll need to update code below
        Debug.Assert(
            texture.format == RenderTextureFormat.ARGBFloat ||
            texture.format == RenderTextureFormat.RGFloat ||
            texture.format == RenderTextureFormat.RFloat ||
            texture.format == RenderTextureFormat.ARGB32);

        Debug.Assert(texture.dimension == TextureDimension.Tex2D);

        var sync = System.Environment.GetEnvironmentVariable("FORCE_SYNC_GPU_READBACK");

        if (sync == null)
        {
            if (SystemInfo.supportsAsyncGPUReadback)
            {
                Type = ReadType.Native;
                if (texture.format == RenderTextureFormat.ARGBFloat)
                {
                    BytesPerPixel    = 16;
                    NativeReadFormat = TextureFormat.RGBAFloat;
                    ElementCount     = Texture.width * Texture.height;
                    SizeInBytes      = ElementCount * BytesPerPixel;
                }
                else if (texture.format == RenderTextureFormat.RGFloat)
                {
                    BytesPerPixel    = 8;
                    NativeReadFormat = TextureFormat.RGFloat;
                    ElementCount     = Texture.width * Texture.height;
                    SizeInBytes      = ElementCount * BytesPerPixel;
                }
                else if (texture.format == RenderTextureFormat.RFloat)
                {
                    BytesPerPixel    = 4;
                    NativeReadFormat = TextureFormat.RFloat;
                    ElementCount     = Texture.width * Texture.height;
                    SizeInBytes      = ElementCount * BytesPerPixel;
                }
                else // if (texture.format == RenderTextureFormat.ARGB32)
                {
                    BytesPerPixel    = 3;
                    NativeReadFormat = TextureFormat.RGB24;
                    ElementCount     = Texture.width * Texture.height * BytesPerPixel;
                    SizeInBytes      = ElementCount;
                }
                Data = new T[ElementCount];
                return;
            }

            if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLCore &&
                SystemInfo.operatingSystemFamily == OperatingSystemFamily.Linux)
            {
                var version = SystemInfo.graphicsDeviceVersion;
                version = version.Split(new char[] { ' ' }, 3)[1];
                var parts = version.Split(new char[] { '.' });
                int major = int.Parse(parts[0]);
                int minor = int.Parse(parts[1]);
                //Debug.Log($"OpenGL version = {major}.{minor}");

                // OpenGL extensions required:
                // ARB_buffer_storage (from 4.4)
                // ARB_shader_image_load_store (from 4.2)
                // ARB_sync (from 3.2)
                if (major > 4 || major == 4 && minor >= 4)
                {
                    debug = new DebugDelegate(DebugCallback);
                    AsyncTextureReaderImports.AsyncTextureReaderSetDebug(Marshal.GetFunctionPointerForDelegate(debug));

                    if (texture.format == RenderTextureFormat.ARGBFloat)
                    {
                        BytesPerPixel = 16;
                        ElementCount  = Texture.width * Texture.height;
                        SizeInBytes   = ElementCount * BytesPerPixel;
                    }
                    else if (texture.format == RenderTextureFormat.RGFloat)
                    {
                        BytesPerPixel = 8;
                        ElementCount  = Texture.width * Texture.height;
                        SizeInBytes   = ElementCount * BytesPerPixel;
                    }
                    else if (texture.format == RenderTextureFormat.RFloat)
                    {
                        BytesPerPixel = 4;
                        ElementCount  = Texture.width * Texture.height;
                        SizeInBytes   = ElementCount * BytesPerPixel;
                    }
                    else // if (texture.format == RenderTextureFormat.ARGB32)
                    {
                        BytesPerPixel = 4;
                        ElementCount  = Texture.width * Texture.height * BytesPerPixel;
                        SizeInBytes   = ElementCount;
                    }

                    Data = new T[ElementCount];
                    texture.Create();
                    LinuxId = AsyncTextureReaderImports.AsyncTextureReaderCreate(texture.GetNativeTexturePtr(), SizeInBytes);
                    if (LinuxId >= 0)
                    {
                        LinuxUpdate = AsyncTextureReaderImports.AsyncTextureReaderGetUpdate();
                        GL.IssuePluginEvent(LinuxUpdate, LinuxId);

                        Type = ReadType.LinuxOpenGL;
                    }
                    else
                    {
                        Debug.Log("ERROR: failed to create native AsyncTextureReader");
                    }
                    return;
                }
            }
        }

        if (texture.format != RenderTextureFormat.ARGB32)
        {
            Debug.Log("ERROR: fallback AsyncTextureReader supports only ARGB32 texture format");
            Type = ReadType.None;
            return;
        }

        Type          = ReadType.Sync;
        BytesPerPixel = 3;
        ElementCount  = Texture.width * Texture.height * BytesPerPixel;
        SizeInBytes   = ElementCount;
        Data          = new T[ElementCount];
        ReadTexture   = new Texture2D(texture.width, texture.height, TextureFormat.RGB24, false);
    }
Ejemplo n.º 8
0
    public void Update()
    {
        if (Texture.IsCreated() == false)
        {
            // need to recreate native RenderTexture handle, because it is lost
            // this happens, for example, when you resize Unity Editor window on Linux
            if (Type == ReadType.Native)
            {
                NativeReadRequest.WaitForCompletion();
            }
            else if (Type == ReadType.LinuxOpenGL)
            {
                AsyncTextureReaderImports.AsyncTextureReaderDestroy(LinuxId);
                GL.IssuePluginEvent(LinuxUpdate, LinuxId);

                Texture.Create();
                LinuxId = AsyncTextureReaderImports.AsyncTextureReaderCreate(Texture.GetNativeTexturePtr(), SizeInBytes);
                GL.IssuePluginEvent(LinuxUpdate, LinuxId);
            }

            Status = AsyncTextureReaderStatus.Idle;
            return;
        }

        if (Status != AsyncTextureReaderStatus.Reading)
        {
            return;
        }

        if (Type == ReadType.Native)
        {
            if (NativeReadRequest.done)
            {
                if (NativeReadRequest.layerCount == 0)
                {
                    // start reading request was not issued yet
                    return;
                }
                // this will happen only if AsyncGPUReadback.Request was issued
                if (NativeReadRequest.hasError)
                {
                    return;
                }

                NativeReadRequest.GetData <T>().CopyTo(Data);
                Status = AsyncTextureReaderStatus.Finished;
            }
        }
        else if (Type == ReadType.LinuxOpenGL)
        {
            if (LinuxId >= 0)
            {
                Status = AsyncTextureReaderImports.AsyncTextureReaderGetStatus(LinuxId);
                if (Status != AsyncTextureReaderStatus.Finished)
                {
                    GL.IssuePluginEvent(LinuxUpdate, LinuxId);
                    Status = AsyncTextureReaderImports.AsyncTextureReaderGetStatus(LinuxId);
                }
                if (Status == AsyncTextureReaderStatus.Finished)
                {
                    IntPtr src    = AsyncTextureReaderImports.AsyncTextureReaderGetBuffer(LinuxId);
                    var    handle = GCHandle.Alloc(Data, GCHandleType.Pinned);
                    try
                    {
                        IntPtr dst = handle.AddrOfPinnedObject();
                        unsafe
                        {
                            Buffer.MemoryCopy((void *)src, (void *)dst, SizeInBytes, SizeInBytes);
                        }
                    }
                    finally
                    {
                        handle.Free();
                    }
                }
            }
            else
            {
                Status = AsyncTextureReaderStatus.Finished;
            }
        }
        else if (Type == ReadType.Sync)
        {
            var current = RenderTexture.active;
            RenderTexture.active = Texture;
            ReadTexture.ReadPixels(new Rect(0, 0, Texture.width, Texture.height), 0, 0);
            ReadTexture.Apply();
            RenderTexture.active = current;

            ReadTexture.GetRawTextureData <T>().CopyTo(Data);
            Status = AsyncTextureReaderStatus.Finished;
        }
    }
Ejemplo n.º 9
0
    public void Update()
    {
        if (Status != AsyncTextureReaderStatus.Reading)
        {
            return;
        }

        if (Type == ReadType.Native)
        {
            if (NativeReadRequest.done)
            {
                if (NativeReadRequest.layerCount == 0)
                {
                    // start reading request was not issued yet
                    return;
                }
                // this will happen only if AsyncGPUReadback.Request was issued
                if (NativeReadRequest.hasError)
                {
                    return;
                }

                Data   = NativeReadRequest.GetData <T>();
                Status = AsyncTextureReaderStatus.Finished;
            }
        }
        else if (Type == ReadType.LinuxOpenGL)
        {
            if (LinuxId >= 0)
            {
                Status = AsyncTextureReaderImports.AsyncTextureReaderGetStatus(LinuxId);
                if (Status != AsyncTextureReaderStatus.Finished)
                {
                    GL.IssuePluginEvent(LinuxUpdate, LinuxId);
                }
            }
            else
            {
                Status = AsyncTextureReaderStatus.Finished;
            }
        }
        else if (Type == ReadType.Sync)
        {
            var current = RenderTexture.active;
            RenderTexture.active = Texture;
            ReadTexture.ReadPixels(new Rect(0, 0, Texture.width, Texture.height), 0, 0);
            ReadTexture.Apply();
            RenderTexture.active = current;

            int    size  = ReadTexture.width * ReadTexture.height * BytesPerPixel;
            byte[] bytes = ReadTexture.GetRawTextureData();
            unsafe
            {
                fixed(void *ptr = bytes)
                {
                    Buffer.MemoryCopy(ptr, Data.GetUnsafePtr(), size, size);
                }
            }
            Status = AsyncTextureReaderStatus.Finished;
        }
    }