Procházet zdrojové kódy

Add locking methods to the ogl resource cache (#238)

* Add locking methods to the ogl resource cache

* Remove some unused arguments

* Add the ZF32 texture format
gdkchan před 7 roky
rodič
revize
1968386808

+ 1 - 0
Ryujinx.Graphics/Gal/GalTextureFormat.cs

@@ -17,6 +17,7 @@ namespace Ryujinx.Graphics.Gal
         BC3          = 0x26,
         BC4          = 0x27,
         BC5          = 0x28,
+        ZF32         = 0x2f,
         Astc2D4x4    = 0x40,
         Astc2D5x5    = 0x41,
         Astc2D6x6    = 0x42,

+ 5 - 2
Ryujinx.Graphics/Gal/IGalRasterizer.cs

@@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal
 {
     public interface IGalRasterizer
     {
+        void LockCaches();
+        void UnlockCaches();
+
         void ClearBuffers(GalClearBufferFlags Flags);
 
         bool IsVboCached(long Key, long DataSize);
@@ -46,9 +49,9 @@ namespace Ryujinx.Graphics.Gal
 
         void CreateIbo(long Key, byte[] Buffer);
 
-        void SetVertexArray(int VbIndex, int Stride, long VboKey, GalVertexAttrib[] Attribs);
+        void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs);
 
-        void SetIndexArray(long Key, int Size, GalIndexFormat Format);
+        void SetIndexArray(int Size, GalIndexFormat Format);
 
         void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
 

+ 3 - 0
Ryujinx.Graphics/Gal/IGalTexture.cs

@@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Gal
 {
     public interface IGalTexture
     {
+        void LockCache();
+        void UnlockCache();
+
         void Create(long Key, byte[] Data, GalTexture Texture);
 
         bool TryGetCachedTexture(long Key, long DataSize, out GalTexture Texture);

+ 41 - 2
Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs

@@ -36,6 +36,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
 
         private DeleteValue DeleteValueCallback;
 
+        private Queue<T> DeletePending;
+
+        private bool Locked;
+
         public OGLCachedResource(DeleteValue DeleteValueCallback)
         {
             if (DeleteValueCallback == null)
@@ -48,11 +52,33 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             Cache = new Dictionary<long, CacheBucket>();
 
             SortedCache = new LinkedList<long>();
+
+            DeletePending = new Queue<T>();
         }
 
-        public void AddOrUpdate(long Key, T Value, long Size)
+        public void Lock()
+        {
+            Locked = true;
+        }
+
+        public void Unlock()
         {
+            Locked = false;
+
+            while (DeletePending.TryDequeue(out T Value))
+            {
+                DeleteValueCallback(Value);
+            }
+
             ClearCacheIfNeeded();
+        }
+
+        public void AddOrUpdate(long Key, T Value, long Size)
+        {
+            if (!Locked)
+            {
+                ClearCacheIfNeeded();
+            }
 
             LinkedListNode<long> Node = SortedCache.AddLast(Key);
 
@@ -60,7 +86,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
 
             if (Cache.TryGetValue(Key, out CacheBucket Bucket))
             {
-                DeleteValueCallback(Bucket.Value);
+                if (Locked)
+                {
+                    DeletePending.Enqueue(Bucket.Value);
+                }
+                else
+                {
+                    DeleteValueCallback(Bucket.Value);
+                }
 
                 SortedCache.Remove(Bucket.Node);
 
@@ -78,6 +111,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             {
                 Value = Bucket.Value;
 
+                SortedCache.Remove(Bucket.Node);
+
+                LinkedListNode<long> Node = SortedCache.AddLast(Key);
+
+                Cache[Key] = new CacheBucket(Value, Bucket.DataSize, Node);
+
                 return true;
             }
 

+ 10 - 9
Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs

@@ -129,15 +129,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
         {
             switch (Format)
             {
-                case GalTextureFormat.R32G32B32A32: return (PixelFormat.Rgba, PixelType.Float);
-                case GalTextureFormat.R16G16B16A16: return (PixelFormat.Rgba, PixelType.HalfFloat);
-                case GalTextureFormat.A8B8G8R8:     return (PixelFormat.Rgba, PixelType.UnsignedByte);
-                case GalTextureFormat.R32:          return (PixelFormat.Red,  PixelType.Float);
-                case GalTextureFormat.A1B5G5R5:     return (PixelFormat.Rgba, PixelType.UnsignedShort5551);
-                case GalTextureFormat.B5G6R5:       return (PixelFormat.Rgb,  PixelType.UnsignedShort565);
-                case GalTextureFormat.G8R8:         return (PixelFormat.Rg,   PixelType.UnsignedByte);
-                case GalTextureFormat.R16:          return (PixelFormat.Red,  PixelType.HalfFloat);
-                case GalTextureFormat.R8:           return (PixelFormat.Red,  PixelType.UnsignedByte);
+                case GalTextureFormat.R32G32B32A32: return (PixelFormat.Rgba,           PixelType.Float);
+                case GalTextureFormat.R16G16B16A16: return (PixelFormat.Rgba,           PixelType.HalfFloat);
+                case GalTextureFormat.A8B8G8R8:     return (PixelFormat.Rgba,           PixelType.UnsignedByte);
+                case GalTextureFormat.R32:          return (PixelFormat.Red,            PixelType.Float);
+                case GalTextureFormat.A1B5G5R5:     return (PixelFormat.Rgba,           PixelType.UnsignedShort5551);
+                case GalTextureFormat.B5G6R5:       return (PixelFormat.Rgb,            PixelType.UnsignedShort565);
+                case GalTextureFormat.G8R8:         return (PixelFormat.Rg,             PixelType.UnsignedByte);
+                case GalTextureFormat.R16:          return (PixelFormat.Red,            PixelType.HalfFloat);
+                case GalTextureFormat.R8:           return (PixelFormat.Red,            PixelType.UnsignedByte);
+                case GalTextureFormat.ZF32:         return (PixelFormat.DepthComponent, PixelType.Float);
             }
 
             throw new NotImplementedException(Format.ToString());

+ 14 - 2
Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs

@@ -71,6 +71,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             IndexBuffer = new IbInfo();
         }
 
+        public void LockCaches()
+        {
+            VboCache.Lock();
+            IboCache.Lock();
+        }
+
+        public void UnlockCaches()
+        {
+            VboCache.Unlock();
+            IboCache.Unlock();
+        }
+
         public void ClearBuffers(GalClearBufferFlags Flags)
         {
             ClearBufferMask Mask = ClearBufferMask.ColorBufferBit;
@@ -223,7 +235,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
         }
 
-        public void SetVertexArray(int VbIndex, int Stride, long VboKey, GalVertexAttrib[] Attribs)
+        public void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs)
         {
             if (!VboCache.TryGetValue(VboKey, out int VboHandle))
             {
@@ -270,7 +282,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             }
         }
 
-        public void SetIndexArray(long Key, int Size, GalIndexFormat Format)
+        public void SetIndexArray(int Size, GalIndexFormat Format)
         {
             IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
 

+ 10 - 0
Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs

@@ -26,6 +26,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             TextureCache = new OGLCachedResource<TCE>(DeleteTexture);
         }
 
+        public void LockCache()
+        {
+            TextureCache.Lock();
+        }
+
+        public void UnlockCache()
+        {
+            TextureCache.Unlock();
+        }
+
         private static void DeleteTexture(TCE CachedTexture)
         {
             GL.DeleteTexture(CachedTexture.Handle);

+ 18 - 2
Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs

@@ -73,6 +73,8 @@ namespace Ryujinx.HLE.Gpu.Engines
 
         private void VertexEndGl(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
         {
+            LockCaches();
+
             SetFrameBuffer(Vmm, 0);
 
             long[] Keys = UploadShaders(Vmm);
@@ -90,6 +92,20 @@ namespace Ryujinx.HLE.Gpu.Engines
             UploadTextures(Vmm, Keys);
             UploadUniforms(Vmm);
             UploadVertexArrays(Vmm);
+
+            UnlockCaches();
+        }
+
+        private void LockCaches()
+        {
+            Gpu.Renderer.Rasterizer.LockCaches();
+            Gpu.Renderer.Texture.LockCache();
+        }
+
+        private void UnlockCaches()
+        {
+            Gpu.Renderer.Rasterizer.UnlockCaches();
+            Gpu.Renderer.Texture.UnlockCache();
         }
 
         private void ClearBuffers(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
@@ -570,7 +586,7 @@ namespace Ryujinx.HLE.Gpu.Engines
                     Gpu.Renderer.Rasterizer.CreateIbo(IboKey, Data);
                 }
 
-                Gpu.Renderer.Rasterizer.SetIndexArray(IboKey, IbSize, IndexFormat);
+                Gpu.Renderer.Rasterizer.SetIndexArray(IbSize, IndexFormat);
             }
 
             List<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[32];
@@ -634,7 +650,7 @@ namespace Ryujinx.HLE.Gpu.Engines
                     Gpu.Renderer.Rasterizer.CreateVbo(VboKey, Data);
                 }
 
-                Gpu.Renderer.Rasterizer.SetVertexArray(Index, Stride, VboKey, Attribs[Index].ToArray());
+                Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray());
             }
 
             GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff);

+ 19 - 9
Ryujinx.HLE/Gpu/Texture/TextureHelper.cs

@@ -28,15 +28,25 @@ namespace Ryujinx.HLE.Gpu.Texture
         {
             switch (Texture.Format)
             {
-                case GalTextureFormat.R32G32B32A32: return Texture.Width * Texture.Height * 16;
-                case GalTextureFormat.R16G16B16A16: return Texture.Width * Texture.Height * 8;
-                case GalTextureFormat.A8B8G8R8:     return Texture.Width * Texture.Height * 4;
-                case GalTextureFormat.R32:          return Texture.Width * Texture.Height * 4;
-                case GalTextureFormat.A1B5G5R5:     return Texture.Width * Texture.Height * 2;
-                case GalTextureFormat.B5G6R5:       return Texture.Width * Texture.Height * 2;
-                case GalTextureFormat.G8R8:         return Texture.Width * Texture.Height * 2;
-                case GalTextureFormat.R16:          return Texture.Width * Texture.Height * 2;
-                case GalTextureFormat.R8:           return Texture.Width * Texture.Height;
+                case GalTextureFormat.R32G32B32A32:
+                    return Texture.Width * Texture.Height * 16;
+
+                case GalTextureFormat.R16G16B16A16:
+                    return Texture.Width * Texture.Height * 8;
+
+                case GalTextureFormat.A8B8G8R8:
+                case GalTextureFormat.R32:
+                case GalTextureFormat.ZF32:
+                    return Texture.Width * Texture.Height * 4;
+
+                case GalTextureFormat.A1B5G5R5:
+                case GalTextureFormat.B5G6R5:
+                case GalTextureFormat.G8R8:
+                case GalTextureFormat.R16:
+                    return Texture.Width * Texture.Height * 2;
+
+                case GalTextureFormat.R8:
+                    return Texture.Width * Texture.Height;
 
                 case GalTextureFormat.BC1:
                 case GalTextureFormat.BC4:

+ 1 - 0
Ryujinx.HLE/Gpu/Texture/TextureReader.cs

@@ -25,6 +25,7 @@ namespace Ryujinx.HLE.Gpu.Texture
                 case GalTextureFormat.BC3:          return Read16Bpt4x4(Memory, Texture);
                 case GalTextureFormat.BC4:          return Read8Bpt4x4 (Memory, Texture);
                 case GalTextureFormat.BC5:          return Read16Bpt4x4(Memory, Texture);
+                case GalTextureFormat.ZF32:         return Read4Bpp    (Memory, Texture);
                 case GalTextureFormat.Astc2D4x4:    return Read16Bpt4x4(Memory, Texture);
             }