Improved and simplified window texture presentation

This commit is contained in:
gdk 2019-11-23 23:24:03 -03:00 committed by Thog
parent b2b2e04669
commit 16d88c21fc
11 changed files with 137 additions and 497 deletions

View file

@ -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

View file

@ -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();

View file

@ -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;
}

View file

@ -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)

View file

@ -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;
}
}
}

View 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);
}
}
}
}