diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2019-12-31 19:09:49 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | 59fdaa744b20f91928ee3fcaf5fabfcb7b409451 (patch) | |
| tree | f01e21d930e456398411317784c5063c532a7215 /Ryujinx.Graphics.Gpu | |
| parent | f7bcc884e46805f4dcda4fc7d7e7bccb2a3ac316 (diff) | |
GPU resource disposal
Diffstat (limited to 'Ryujinx.Graphics.Gpu')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Compute.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Methods.cs | 16 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/GpuContext.cs | 15 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 10 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureManager.cs | 14 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/BufferManager.cs | 12 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/RangeList.cs | 15 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/NvGpuFifo.cs | 3 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/CachedShader.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 61 |
11 files changed, 122 insertions, 32 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Compute.cs b/Ryujinx.Graphics.Gpu/Engine/Compute.cs index 50aac1d0..1f524671 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Compute.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Compute.cs @@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.Gpu.Engine // Note: A size of 0 is also invalid, the size must be at least 1. int sharedMemorySize = Math.Clamp(dispatchParams.SharedMemorySize & 0xffff, 1, _context.Capabilities.MaximumComputeSharedMemorySize); - ComputeShader cs = _shaderCache.GetComputeShader( + ComputeShader cs = ShaderCache.GetComputeShader( shaderGpuVa, sharedMemorySize, dispatchParams.UnpackBlockSizeX(), diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 0a52bee9..12a9744c 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -18,12 +18,14 @@ namespace Ryujinx.Graphics.Gpu.Engine partial class Methods { private readonly GpuContext _context; - - private readonly ShaderCache _shaderCache; - private readonly ShaderProgramInfo[] _currentProgramInfo; /// <summary> + /// In-memory shader cache. + /// </summary> + public ShaderCache ShaderCache { get; } + + /// <summary> /// GPU buffer manager. /// </summary> public BufferManager BufferManager { get; } @@ -44,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { _context = context; - _shaderCache = new ShaderCache(_context); + ShaderCache = new ShaderCache(_context); _currentProgramInfo = new ShaderProgramInfo[Constants.TotalShaderStages]; @@ -757,13 +759,13 @@ namespace Ryujinx.Graphics.Gpu.Engine addressesArray[index] = baseAddress + shader.Offset; } - GraphicsShader gs = _shaderCache.GetGraphicsShader(state, addresses); + GraphicsShader gs = ShaderCache.GetGraphicsShader(state, addresses); - _vsUsesInstanceId = gs.Shader[0].Program.Info.UsesInstanceId; + _vsUsesInstanceId = gs.Shaders[0].Program.Info.UsesInstanceId; for (int stage = 0; stage < Constants.TotalShaderStages; stage++) { - ShaderProgramInfo info = gs.Shader[stage].Program?.Info; + ShaderProgramInfo info = gs.Shaders[stage].Program?.Info; _currentProgramInfo[stage] = info; diff --git a/Ryujinx.Graphics.Gpu/GpuContext.cs b/Ryujinx.Graphics.Gpu/GpuContext.cs index d68dd2c0..034cc065 100644 --- a/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu /// <summary> /// GPU emulation context. /// </summary> - public class GpuContext + public sealed class GpuContext : IDisposable { /// <summary> /// Host renderer. @@ -104,5 +104,18 @@ namespace Ryujinx.Graphics.Gpu { PhysicalMemory = new PhysicalMemory(cpuMemory); } + + /// <summary> + /// Disposes all GPU resources currently cached. + /// It's an error to push any GPU commands after disposal. + /// Additionally, the GPU commands FIFO must be empty for disposal, + /// and processing of all commands must have finished. + /// </summary> + public void Dispose() + { + Methods.ShaderCache.Dispose(); + Methods.BufferManager.Dispose(); + Methods.TextureManager.Dispose(); + } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 9b5c19f3..076718e5 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// <summary> /// Represents a cached GPU texture. /// </summary> - class Texture : IRange<Texture> + class Texture : IRange<Texture>, IDisposable { private GpuContext _context; @@ -1011,5 +1011,13 @@ namespace Ryujinx.Graphics.Gpu.Image _arrayViewTexture?.Dispose(); _arrayViewTexture = null; } + + /// <summary> + /// Performs texture disposal, deleting the texture. + /// </summary> + public void Dispose() + { + DisposeTextures(); + } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index ecc5dc51..e0a8908a 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// <summary> /// Texture manager. /// </summary> - class TextureManager + class TextureManager : IDisposable { private const int OverlapsBufferInitialCapacity = 10; private const int OverlapsBufferMaxCapacity = 10000; @@ -761,5 +761,17 @@ namespace Ryujinx.Graphics.Gpu.Image { _textures.Remove(texture); } + + /// <summary> + /// Disposes all textures in the cache. + /// It's an error to use the texture manager after disposal. + /// </summary> + public void Dispose() + { + foreach (Texture texture in _textures) + { + texture.Dispose(); + } + } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 1d27bc7e..44542349 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -683,5 +683,17 @@ namespace Ryujinx.Graphics.Gpu.Memory buffer.SynchronizeMemory(address, size); } } + + /// <summary> + /// Disposes all buffers in the cache. + /// It's an error to use the buffer manager after disposal. + /// </summary> + public void Dispose() + { + foreach (Buffer buffer in _buffers) + { + buffer.Dispose(); + } + } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Memory/RangeList.cs b/Ryujinx.Graphics.Gpu/Memory/RangeList.cs index 1d185e21..75be1cf2 100644 --- a/Ryujinx.Graphics.Gpu/Memory/RangeList.cs +++ b/Ryujinx.Graphics.Gpu/Memory/RangeList.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; namespace Ryujinx.Graphics.Gpu.Memory @@ -7,11 +8,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// List of GPU resources with data on guest memory. /// </summary> /// <typeparam name="T">Type of the GPU resource</typeparam> - class RangeList<T> where T : IRange<T> + class RangeList<T> : IEnumerable<T> where T : IRange<T> { private const int ArrayGrowthSize = 32; - private List<T> _items; + private readonly List<T> _items; /// <summary> /// Creates a new GPU resources list. @@ -320,5 +321,15 @@ namespace Ryujinx.Graphics.Gpu.Memory return ~left; } + + public IEnumerator<T> GetEnumerator() + { + return _items.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _items.GetEnumerator(); + } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs index 6f51527f..9e154533 100644 --- a/Ryujinx.Graphics.Gpu/NvGpuFifo.cs +++ b/Ryujinx.Graphics.Gpu/NvGpuFifo.cs @@ -21,6 +21,9 @@ namespace Ryujinx.Graphics.Gpu /// </summary> private struct CachedMacro { + /// <summary> + /// Word offset of the code on the code memory. + /// </summary> public int Position { get; } private bool _executionPending; diff --git a/Ryujinx.Graphics.Gpu/Shader/CachedShader.cs b/Ryujinx.Graphics.Gpu/Shader/CachedShader.cs index 362d149a..418a4f40 100644 --- a/Ryujinx.Graphics.Gpu/Shader/CachedShader.cs +++ b/Ryujinx.Graphics.Gpu/Shader/CachedShader.cs @@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <summary> /// Host shader object. /// </summary> - public IShader Shader { get; set; } + public IShader HostShader { get; set; } /// <summary> /// Maxwell binary shader code. diff --git a/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs b/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs index 14c8e5c2..a1493236 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs @@ -15,14 +15,14 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <summary> /// Compiled shader for each shader stage. /// </summary> - public CachedShader[] Shader { get; } + public CachedShader[] Shaders { get; } /// <summary> /// Creates a new instance of cached graphics shader. /// </summary> public GraphicsShader() { - Shader = new CachedShader[5]; + Shaders = new CachedShader[5]; } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index b299da1a..ad2a6037 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <summary> /// Memory cache of shader code. /// </summary> - class ShaderCache + class ShaderCache : IDisposable { private const int MaxProgramSize = 0x100000; @@ -117,25 +117,25 @@ namespace Ryujinx.Graphics.Gpu.Shader if (addresses.VertexA != 0) { - gpShaders.Shader[0] = TranslateGraphicsShader(state, ShaderStage.Vertex, addresses.Vertex, addresses.VertexA); + gpShaders.Shaders[0] = TranslateGraphicsShader(state, ShaderStage.Vertex, addresses.Vertex, addresses.VertexA); } else { - gpShaders.Shader[0] = TranslateGraphicsShader(state, ShaderStage.Vertex, addresses.Vertex); + gpShaders.Shaders[0] = TranslateGraphicsShader(state, ShaderStage.Vertex, addresses.Vertex); } - gpShaders.Shader[1] = TranslateGraphicsShader(state, ShaderStage.TessellationControl, addresses.TessControl); - gpShaders.Shader[2] = TranslateGraphicsShader(state, ShaderStage.TessellationEvaluation, addresses.TessEvaluation); - gpShaders.Shader[3] = TranslateGraphicsShader(state, ShaderStage.Geometry, addresses.Geometry); - gpShaders.Shader[4] = TranslateGraphicsShader(state, ShaderStage.Fragment, addresses.Fragment); + gpShaders.Shaders[1] = TranslateGraphicsShader(state, ShaderStage.TessellationControl, addresses.TessControl); + gpShaders.Shaders[2] = TranslateGraphicsShader(state, ShaderStage.TessellationEvaluation, addresses.TessEvaluation); + gpShaders.Shaders[3] = TranslateGraphicsShader(state, ShaderStage.Geometry, addresses.Geometry); + gpShaders.Shaders[4] = TranslateGraphicsShader(state, ShaderStage.Fragment, addresses.Fragment); BackpropQualifiers(gpShaders); List<IShader> hostShaders = new List<IShader>(); - for (int stage = 0; stage < gpShaders.Shader.Length; stage++) + for (int stage = 0; stage < gpShaders.Shaders.Length; stage++) { - ShaderProgram program = gpShaders.Shader[stage].Program; + ShaderProgram program = gpShaders.Shaders[stage].Program; if (program == null) { @@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Gpu.Shader IShader hostShader = _context.Renderer.CompileShader(program); - gpShaders.Shader[stage].Shader = hostShader; + gpShaders.Shaders[stage].HostShader = hostShader; hostShaders.Add(hostShader); } @@ -182,9 +182,9 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <returns>True if the code is different, false otherwise</returns> private bool IsShaderDifferent(GraphicsShader gpShaders, ShaderAddresses addresses) { - for (int stage = 0; stage < gpShaders.Shader.Length; stage++) + for (int stage = 0; stage < gpShaders.Shaders.Length; stage++) { - CachedShader shader = gpShaders.Shader[stage]; + CachedShader shader = gpShaders.Shaders[stage]; if (shader.Code == null) { @@ -370,13 +370,13 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="program">Graphics shader cached code</param> private void BackpropQualifiers(GraphicsShader program) { - ShaderProgram fragmentShader = program.Shader[4].Program; + ShaderProgram fragmentShader = program.Shaders[4].Program; bool isFirst = true; for (int stage = 3; stage >= 0; stage--) { - if (program.Shader[stage].Program == null) + if (program.Shaders[stage].Program == null) { continue; } @@ -389,11 +389,11 @@ namespace Ryujinx.Graphics.Gpu.Shader if (isFirst && iq != string.Empty) { - program.Shader[stage].Program.Replace($"{DefineNames.OutQualifierPrefixName}{attr}", iq); + program.Shaders[stage].Program.Replace($"{DefineNames.OutQualifierPrefixName}{attr}", iq); } else { - program.Shader[stage].Program.Replace($"{DefineNames.OutQualifierPrefixName}{attr} ", string.Empty); + program.Shaders[stage].Program.Replace($"{DefineNames.OutQualifierPrefixName}{attr} ", string.Empty); } } @@ -497,5 +497,34 @@ namespace Ryujinx.Graphics.Gpu.Shader return 0; } + + /// <summary> + /// Disposes the shader cache, deleting all the cached shaders. + /// It's an error to use the shader cache after disposal. + /// </summary> + public void Dispose() + { + foreach (List<ComputeShader> list in _cpPrograms.Values) + { + foreach (ComputeShader shader in list) + { + shader.HostProgram.Dispose(); + shader.Shader.HostShader.Dispose(); + } + } + + foreach (List<GraphicsShader> list in _gpPrograms.Values) + { + foreach (GraphicsShader shader in list) + { + shader.HostProgram.Dispose(); + + foreach (CachedShader cachedShader in shader.Shaders) + { + cachedShader.HostShader?.Dispose(); + } + } + } + } } }
\ No newline at end of file |
