diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-09-18 01:30:35 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-18 01:30:35 -0300 |
| commit | d4187aaa9d7194aa26d04aee838edbc3a38f1862 (patch) | |
| tree | 06fe725c1067b4aeca21749799b835d85e7d2787 /Ryujinx.Graphics/GpuResourceManager.cs | |
| parent | bec95cacc1061f91373a1e3a1411981af7fe2e4e (diff) | |
Allow "reinterpretation" of framebuffer/zeta formats (#418)
* (Re)Implement format reinterpretation, other changes
* Implement writeback to guest memory, some refactoring
* More refactoring, implement reinterpretation the old way again
* Clean up
* Some fixes on M2MF (old Dma engine), added partial support for P2MF, fix conditional ssy, add Z24S8 zeta format, other fixes
* nit: Formatting
* Address PR feedback
Diffstat (limited to 'Ryujinx.Graphics/GpuResourceManager.cs')
| -rw-r--r-- | Ryujinx.Graphics/GpuResourceManager.cs | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/GpuResourceManager.cs b/Ryujinx.Graphics/GpuResourceManager.cs new file mode 100644 index 00000000..ba35910d --- /dev/null +++ b/Ryujinx.Graphics/GpuResourceManager.cs @@ -0,0 +1,122 @@ +using Ryujinx.Graphics.Gal; +using Ryujinx.Graphics.Memory; +using Ryujinx.Graphics.Texture; +using System.Collections.Generic; + +namespace Ryujinx.Graphics +{ + public class GpuResourceManager + { + private NvGpu Gpu; + + private HashSet<long>[] UploadedKeys; + + public GpuResourceManager(NvGpu Gpu) + { + this.Gpu = Gpu; + + UploadedKeys = new HashSet<long>[(int)NvGpuBufferType.Count]; + + for (int Index = 0; Index < UploadedKeys.Length; Index++) + { + UploadedKeys[Index] = new HashSet<long>(); + } + } + + public void SendColorBuffer(NvGpuVmm Vmm, long Position, int Attachment, GalImage NewImage) + { + long Size = (uint)ImageUtils.GetSize(NewImage); + + MarkAsCached(Vmm, Position, Size, NvGpuBufferType.Texture); + + bool IsCached = Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage); + + if (IsCached && CachedImage.SizeMatches(NewImage)) + { + Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage); + Gpu.Renderer.RenderTarget.BindColor(Position, Attachment, NewImage); + + return; + } + + Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage); + + Gpu.Renderer.RenderTarget.BindColor(Position, Attachment, NewImage); + } + + public void SendZetaBuffer(NvGpuVmm Vmm, long Position, GalImage NewImage) + { + long Size = (uint)ImageUtils.GetSize(NewImage); + + MarkAsCached(Vmm, Position, Size, NvGpuBufferType.Texture); + + bool IsCached = Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage); + + if (IsCached && CachedImage.SizeMatches(NewImage)) + { + Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage); + Gpu.Renderer.RenderTarget.BindZeta(Position, NewImage); + + return; + } + + Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage); + + Gpu.Renderer.RenderTarget.BindZeta(Position, NewImage); + } + + public void SendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage, int TexIndex = -1) + { + long Size = (uint)ImageUtils.GetSize(NewImage); + + if (!MemoryRegionModified(Vmm, Position, Size, NvGpuBufferType.Texture)) + { + if (Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage) && CachedImage.SizeMatches(NewImage)) + { + Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage); + + if (TexIndex >= 0) + { + Gpu.Renderer.Texture.Bind(Position, TexIndex, NewImage); + } + + return; + } + } + + byte[] Data = ImageUtils.ReadTexture(Vmm, NewImage, Position); + + Gpu.Renderer.Texture.Create(Position, Data, NewImage); + + if (TexIndex >= 0) + { + Gpu.Renderer.Texture.Bind(Position, TexIndex, NewImage); + } + } + + private void MarkAsCached(NvGpuVmm Vmm, long Position, long Size, NvGpuBufferType Type) + { + Vmm.IsRegionModified(Position, Size, Type); + } + + private bool MemoryRegionModified(NvGpuVmm Vmm, long Position, long Size, NvGpuBufferType Type) + { + HashSet<long> Uploaded = UploadedKeys[(int)Type]; + + if (!Uploaded.Add(Position)) + { + return false; + } + + return Vmm.IsRegionModified(Position, Size, Type); + } + + public void ClearPbCache() + { + for (int Index = 0; Index < UploadedKeys.Length; Index++) + { + UploadedKeys[Index].Clear(); + } + } + } +} |
