Improved and simplified window texture presentation
This commit is contained in:
parent
b2b2e04669
commit
16d88c21fc
11 changed files with 137 additions and 497 deletions
|
@ -76,8 +76,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
state.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
|
||||
}
|
||||
|
||||
public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address);
|
||||
|
||||
private void UpdateState(GpuState state)
|
||||
{
|
||||
// Shaders must be the first one to be updated if modified, because
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.GAL.Texture;
|
||||
using Ryujinx.Graphics.Gpu.Engine;
|
||||
using Ryujinx.Graphics.Gpu.Image;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Gpu.State;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu
|
||||
|
@ -24,6 +21,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||
|
||||
public DmaPusher DmaPusher { get; }
|
||||
|
||||
public Window Window { get; }
|
||||
|
||||
internal int SequenceNumber { get; private set; }
|
||||
|
||||
private Lazy<Capabilities> _caps;
|
||||
|
@ -44,6 +43,8 @@ namespace Ryujinx.Graphics.Gpu
|
|||
|
||||
DmaPusher = new DmaPusher(this);
|
||||
|
||||
Window = new Window(this);
|
||||
|
||||
_caps = new Lazy<Capabilities>(GetCapabilities);
|
||||
}
|
||||
|
||||
|
@ -52,37 +53,6 @@ namespace Ryujinx.Graphics.Gpu
|
|||
SequenceNumber++;
|
||||
}
|
||||
|
||||
public ITexture GetTexture(
|
||||
ulong address,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
bool isLinear,
|
||||
int gobBlocksInY,
|
||||
Format format,
|
||||
int bytesPerPixel)
|
||||
{
|
||||
FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);
|
||||
|
||||
TextureInfo info = new TextureInfo(
|
||||
address,
|
||||
width,
|
||||
height,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
stride,
|
||||
isLinear,
|
||||
gobBlocksInY,
|
||||
1,
|
||||
1,
|
||||
Target.Texture2D,
|
||||
formatInfo);
|
||||
|
||||
return Methods.GetTexture(address)?.HostTexture;
|
||||
}
|
||||
|
||||
private Capabilities GetCapabilities()
|
||||
{
|
||||
return Renderer.GetCapabilities();
|
||||
|
|
|
@ -335,18 +335,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_info.FormatInfo.Format == Format.R8G8B8A8Srgb &&
|
||||
info.FormatInfo.Format == Format.R8G8B8A8Unorm && !strict)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_info.FormatInfo.Format == Format.R8G8B8A8Unorm &&
|
||||
info.FormatInfo.Format == Format.R8G8B8A8Srgb && !strict)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return _info.FormatInfo.Format == info.FormatInfo.Format;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
private ITexture[] _rtHostColors;
|
||||
private ITexture _rtHostDs;
|
||||
|
||||
private ConcurrentRangeList<Texture> _textures;
|
||||
private RangeList<Texture> _textures;
|
||||
|
||||
private AutoDeleteCache _cache;
|
||||
|
||||
|
@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
_rtHostColors = new ITexture[Constants.TotalRenderTargets];
|
||||
|
||||
_textures = new ConcurrentRangeList<Texture>();
|
||||
_textures = new RangeList<Texture>();
|
||||
|
||||
_cache = new AutoDeleteCache();
|
||||
}
|
||||
|
@ -561,28 +561,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
info.SwizzleA);
|
||||
}
|
||||
|
||||
public Texture Find2(ulong address)
|
||||
{
|
||||
Texture[] ts = _textures.FindOverlaps(address, 1);
|
||||
|
||||
if (ts.Length == 2)
|
||||
{
|
||||
return ts[1];
|
||||
}
|
||||
|
||||
if (ts.Length == 0)
|
||||
{
|
||||
ts = _textures.FindOverlaps(address - 1, 2);
|
||||
}
|
||||
|
||||
if (ts.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return ts[0];
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
foreach (Texture texture in _cache)
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Memory
|
||||
{
|
||||
class ConcurrentRangeList<T> where T : IRange<T>
|
||||
{
|
||||
private List<T> _items;
|
||||
|
||||
public ConcurrentRangeList()
|
||||
{
|
||||
_items = new List<T>();
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (_items)
|
||||
{
|
||||
int index = BinarySearch(item.Address);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = ~index;
|
||||
}
|
||||
|
||||
_items.Insert(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
lock (_items)
|
||||
{
|
||||
int index = BinarySearch(item.Address);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
while (index > 0 && _items[index - 1].Address == item.Address)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
while (index < _items.Count)
|
||||
{
|
||||
if (_items[index].Equals(item))
|
||||
{
|
||||
_items.RemoveAt(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_items[index].Address > item.Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public T FindFirstOverlap(T item)
|
||||
{
|
||||
return FindFirstOverlap(item.Address, item.Size);
|
||||
}
|
||||
|
||||
public T FindFirstOverlap(ulong address, ulong size)
|
||||
{
|
||||
lock (_items)
|
||||
{
|
||||
int index = BinarySearch(address, size);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
return _items[index];
|
||||
}
|
||||
}
|
||||
|
||||
public T[] FindOverlaps(T item)
|
||||
{
|
||||
return FindOverlaps(item.Address, item.Size);
|
||||
}
|
||||
|
||||
public T[] FindOverlaps(ulong address, ulong size)
|
||||
{
|
||||
List<T> overlapsList = new List<T>();
|
||||
|
||||
ulong endAddress = address + size;
|
||||
|
||||
lock (_items)
|
||||
{
|
||||
foreach (T item in _items)
|
||||
{
|
||||
if (item.Address >= endAddress)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (item.OverlapsWith(address, size))
|
||||
{
|
||||
overlapsList.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return overlapsList.ToArray();
|
||||
}
|
||||
|
||||
public T[] FindOverlaps(ulong address)
|
||||
{
|
||||
List<T> overlapsList = new List<T>();
|
||||
|
||||
lock (_items)
|
||||
{
|
||||
int index = BinarySearch(address);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
while (index > 0 && _items[index - 1].Address == address)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
while (index < _items.Count)
|
||||
{
|
||||
T overlap = _items[index++];
|
||||
|
||||
if (overlap.Address != address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
overlapsList.Add(overlap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return overlapsList.ToArray();
|
||||
}
|
||||
|
||||
private int BinarySearch(ulong address)
|
||||
{
|
||||
int left = 0;
|
||||
int right = _items.Count - 1;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
int range = right - left;
|
||||
|
||||
int middle = left + (range >> 1);
|
||||
|
||||
T item = _items[middle];
|
||||
|
||||
if (item.Address == address)
|
||||
{
|
||||
return middle;
|
||||
}
|
||||
|
||||
if (address < item.Address)
|
||||
{
|
||||
right = middle - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ~left;
|
||||
}
|
||||
|
||||
private int BinarySearch(ulong address, ulong size)
|
||||
{
|
||||
int left = 0;
|
||||
int right = _items.Count - 1;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
int range = right - left;
|
||||
|
||||
int middle = left + (range >> 1);
|
||||
|
||||
T item = _items[middle];
|
||||
|
||||
if (item.OverlapsWith(address, size))
|
||||
{
|
||||
return middle;
|
||||
}
|
||||
|
||||
if (address < item.Address)
|
||||
{
|
||||
right = middle - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ~left;
|
||||
}
|
||||
}
|
||||
}
|
94
Ryujinx.Graphics.Gpu/Window.cs
Normal file
94
Ryujinx.Graphics.Gpu/Window.cs
Normal file
|
@ -0,0 +1,94 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.GAL.Texture;
|
||||
using Ryujinx.Graphics.Gpu.Image;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
public class Window
|
||||
{
|
||||
private GpuContext _context;
|
||||
|
||||
private struct PresentationTexture
|
||||
{
|
||||
public TextureInfo Info { get; }
|
||||
public ImageCrop Crop { get; }
|
||||
public Action<object> Callback { get; }
|
||||
public object UserObj { get; }
|
||||
|
||||
public PresentationTexture(
|
||||
TextureInfo info,
|
||||
ImageCrop crop,
|
||||
Action<object> callback,
|
||||
object userObj)
|
||||
{
|
||||
Info = info;
|
||||
Crop = crop;
|
||||
Callback = callback;
|
||||
UserObj = userObj;
|
||||
}
|
||||
}
|
||||
|
||||
private ConcurrentQueue<PresentationTexture> _frameQueue;
|
||||
|
||||
public Window(GpuContext context)
|
||||
{
|
||||
_context = context;
|
||||
|
||||
_frameQueue = new ConcurrentQueue<PresentationTexture>();
|
||||
}
|
||||
|
||||
public void EnqueueFrameThreadSafe(
|
||||
ulong address,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
bool isLinear,
|
||||
int gobBlocksInY,
|
||||
Format format,
|
||||
int bytesPerPixel,
|
||||
ImageCrop crop,
|
||||
Action<object> callback,
|
||||
object userObj)
|
||||
{
|
||||
FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);
|
||||
|
||||
TextureInfo info = new TextureInfo(
|
||||
address,
|
||||
width,
|
||||
height,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
stride,
|
||||
isLinear,
|
||||
gobBlocksInY,
|
||||
1,
|
||||
1,
|
||||
Target.Texture2D,
|
||||
formatInfo);
|
||||
|
||||
_frameQueue.Enqueue(new PresentationTexture(info, crop, callback, userObj));
|
||||
}
|
||||
|
||||
public void Present(Action swapBuffersCallback)
|
||||
{
|
||||
_context.AdvanceSequence();
|
||||
|
||||
if (_frameQueue.TryDequeue(out PresentationTexture pt))
|
||||
{
|
||||
Image.Texture texture = _context.Methods.TextureManager.FindOrCreateTexture(pt.Info);
|
||||
|
||||
texture.SynchronizeMemory();
|
||||
|
||||
_context.Renderer.Window.Present(texture.HostTexture, pt.Crop);
|
||||
|
||||
swapBuffersCallback();
|
||||
|
||||
pt.Callback(pt.UserObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue