Renaming part 3
This commit is contained in:
parent
e697dbffc9
commit
6adbbc376d
16 changed files with 1069 additions and 1069 deletions
|
@ -1,4 +1,4 @@
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
delegate void DeleteValue<T>(T Value);
|
delegate void DeleteValue<T>(T value);
|
||||||
}
|
}
|
|
@ -18,10 +18,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
public bool HasDepth => ImageUtils.HasDepth(Image.Format);
|
public bool HasDepth => ImageUtils.HasDepth(Image.Format);
|
||||||
public bool HasStencil => ImageUtils.HasStencil(Image.Format);
|
public bool HasStencil => ImageUtils.HasStencil(Image.Format);
|
||||||
|
|
||||||
public ImageHandler(int Handle, GalImage Image)
|
public ImageHandler(int handle, GalImage image)
|
||||||
{
|
{
|
||||||
this.Handle = Handle;
|
Handle = handle;
|
||||||
this.Image = Image;
|
Image = image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLCachedResource<T>
|
class OglCachedResource<T>
|
||||||
{
|
{
|
||||||
public delegate void DeleteValue(T Value);
|
public delegate void DeleteValue(T value);
|
||||||
|
|
||||||
private const int MinTimeDelta = 5 * 60000;
|
private const int MinTimeDelta = 5 * 60000;
|
||||||
private const int MaxRemovalsPerRun = 10;
|
private const int MaxRemovalsPerRun = 10;
|
||||||
|
@ -21,171 +21,171 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public long Timestamp { get; private set; }
|
public long Timestamp { get; private set; }
|
||||||
|
|
||||||
public CacheBucket(T Value, long DataSize, LinkedListNode<long> Node)
|
public CacheBucket(T value, long dataSize, LinkedListNode<long> node)
|
||||||
{
|
{
|
||||||
this.Value = Value;
|
Value = value;
|
||||||
this.DataSize = DataSize;
|
DataSize = dataSize;
|
||||||
this.Node = Node;
|
Node = node;
|
||||||
|
|
||||||
Timestamp = PerformanceCounter.ElapsedMilliseconds;
|
Timestamp = PerformanceCounter.ElapsedMilliseconds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<long, CacheBucket> Cache;
|
private Dictionary<long, CacheBucket> _cache;
|
||||||
|
|
||||||
private LinkedList<long> SortedCache;
|
private LinkedList<long> _sortedCache;
|
||||||
|
|
||||||
private DeleteValue DeleteValueCallback;
|
private DeleteValue _deleteValueCallback;
|
||||||
|
|
||||||
private Queue<T> DeletePending;
|
private Queue<T> _deletePending;
|
||||||
|
|
||||||
private bool Locked;
|
private bool _locked;
|
||||||
|
|
||||||
private long MaxSize;
|
private long _maxSize;
|
||||||
private long TotalSize;
|
private long _totalSize;
|
||||||
|
|
||||||
public OGLCachedResource(DeleteValue DeleteValueCallback, long MaxSize)
|
public OglCachedResource(DeleteValue deleteValueCallback, long maxSize)
|
||||||
{
|
{
|
||||||
this.MaxSize = MaxSize;
|
_maxSize = maxSize;
|
||||||
|
|
||||||
if (DeleteValueCallback == null)
|
if (deleteValueCallback == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(DeleteValueCallback));
|
throw new ArgumentNullException(nameof(deleteValueCallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.DeleteValueCallback = DeleteValueCallback;
|
_deleteValueCallback = deleteValueCallback;
|
||||||
|
|
||||||
Cache = new Dictionary<long, CacheBucket>();
|
_cache = new Dictionary<long, CacheBucket>();
|
||||||
|
|
||||||
SortedCache = new LinkedList<long>();
|
_sortedCache = new LinkedList<long>();
|
||||||
|
|
||||||
DeletePending = new Queue<T>();
|
_deletePending = new Queue<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Lock()
|
public void Lock()
|
||||||
{
|
{
|
||||||
Locked = true;
|
_locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unlock()
|
public void Unlock()
|
||||||
{
|
{
|
||||||
Locked = false;
|
_locked = false;
|
||||||
|
|
||||||
while (DeletePending.TryDequeue(out T Value))
|
while (_deletePending.TryDequeue(out T value))
|
||||||
{
|
{
|
||||||
DeleteValueCallback(Value);
|
_deleteValueCallback(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearCacheIfNeeded();
|
ClearCacheIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddOrUpdate(long Key, T Value, long Size)
|
public void AddOrUpdate(long key, T value, long size)
|
||||||
{
|
{
|
||||||
if (!Locked)
|
if (!_locked)
|
||||||
{
|
{
|
||||||
ClearCacheIfNeeded();
|
ClearCacheIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedListNode<long> Node = SortedCache.AddLast(Key);
|
LinkedListNode<long> node = _sortedCache.AddLast(key);
|
||||||
|
|
||||||
CacheBucket NewBucket = new CacheBucket(Value, Size, Node);
|
CacheBucket newBucket = new CacheBucket(value, size, node);
|
||||||
|
|
||||||
if (Cache.TryGetValue(Key, out CacheBucket Bucket))
|
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
||||||
{
|
{
|
||||||
if (Locked)
|
if (_locked)
|
||||||
{
|
{
|
||||||
DeletePending.Enqueue(Bucket.Value);
|
_deletePending.Enqueue(bucket.Value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DeleteValueCallback(Bucket.Value);
|
_deleteValueCallback(bucket.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedCache.Remove(Bucket.Node);
|
_sortedCache.Remove(bucket.Node);
|
||||||
|
|
||||||
TotalSize -= Bucket.DataSize;
|
_totalSize -= bucket.DataSize;
|
||||||
|
|
||||||
Cache[Key] = NewBucket;
|
_cache[key] = newBucket;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Cache.Add(Key, NewBucket);
|
_cache.Add(key, newBucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
TotalSize += Size;
|
_totalSize += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(long Key, out T Value)
|
public bool TryGetValue(long key, out T value)
|
||||||
{
|
{
|
||||||
if (Cache.TryGetValue(Key, out CacheBucket Bucket))
|
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
||||||
{
|
{
|
||||||
Value = Bucket.Value;
|
value = bucket.Value;
|
||||||
|
|
||||||
SortedCache.Remove(Bucket.Node);
|
_sortedCache.Remove(bucket.Node);
|
||||||
|
|
||||||
LinkedListNode<long> Node = SortedCache.AddLast(Key);
|
LinkedListNode<long> node = _sortedCache.AddLast(key);
|
||||||
|
|
||||||
Cache[Key] = new CacheBucket(Value, Bucket.DataSize, Node);
|
_cache[key] = new CacheBucket(value, bucket.DataSize, node);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value = default(T);
|
value = default(T);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetSize(long Key, out long Size)
|
public bool TryGetSize(long key, out long size)
|
||||||
{
|
{
|
||||||
if (Cache.TryGetValue(Key, out CacheBucket Bucket))
|
if (_cache.TryGetValue(key, out CacheBucket bucket))
|
||||||
{
|
{
|
||||||
Size = Bucket.DataSize;
|
size = bucket.DataSize;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size = 0;
|
size = 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearCacheIfNeeded()
|
private void ClearCacheIfNeeded()
|
||||||
{
|
{
|
||||||
long Timestamp = PerformanceCounter.ElapsedMilliseconds;
|
long timestamp = PerformanceCounter.ElapsedMilliseconds;
|
||||||
|
|
||||||
int Count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while (Count++ < MaxRemovalsPerRun)
|
while (count++ < MaxRemovalsPerRun)
|
||||||
{
|
{
|
||||||
LinkedListNode<long> Node = SortedCache.First;
|
LinkedListNode<long> node = _sortedCache.First;
|
||||||
|
|
||||||
if (Node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CacheBucket Bucket = Cache[Node.Value];
|
CacheBucket bucket = _cache[node.Value];
|
||||||
|
|
||||||
long TimeDelta = Timestamp - Bucket.Timestamp;
|
long timeDelta = timestamp - bucket.Timestamp;
|
||||||
|
|
||||||
if (TimeDelta <= MinTimeDelta && !UnderMemoryPressure())
|
if (timeDelta <= MinTimeDelta && !UnderMemoryPressure())
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedCache.Remove(Node);
|
_sortedCache.Remove(node);
|
||||||
|
|
||||||
Cache.Remove(Node.Value);
|
_cache.Remove(node.Value);
|
||||||
|
|
||||||
DeleteValueCallback(Bucket.Value);
|
_deleteValueCallback(bucket.Value);
|
||||||
|
|
||||||
TotalSize -= Bucket.DataSize;
|
_totalSize -= bucket.DataSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UnderMemoryPressure()
|
private bool UnderMemoryPressure()
|
||||||
{
|
{
|
||||||
return TotalSize >= MaxSize;
|
return _totalSize >= _maxSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,72 +3,72 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLConstBuffer : IGalConstBuffer
|
class OglConstBuffer : IGalConstBuffer
|
||||||
{
|
{
|
||||||
private const long MaxConstBufferCacheSize = 64 * 1024 * 1024;
|
private const long MaxConstBufferCacheSize = 64 * 1024 * 1024;
|
||||||
|
|
||||||
private OGLCachedResource<OGLStreamBuffer> Cache;
|
private OglCachedResource<OglStreamBuffer> _cache;
|
||||||
|
|
||||||
public OGLConstBuffer()
|
public OglConstBuffer()
|
||||||
{
|
{
|
||||||
Cache = new OGLCachedResource<OGLStreamBuffer>(DeleteBuffer, MaxConstBufferCacheSize);
|
_cache = new OglCachedResource<OglStreamBuffer>(DeleteBuffer, MaxConstBufferCacheSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LockCache()
|
public void LockCache()
|
||||||
{
|
{
|
||||||
Cache.Lock();
|
_cache.Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnlockCache()
|
public void UnlockCache()
|
||||||
{
|
{
|
||||||
Cache.Unlock();
|
_cache.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(long Key, long Size)
|
public void Create(long key, long size)
|
||||||
{
|
{
|
||||||
OGLStreamBuffer Buffer = new OGLStreamBuffer(BufferTarget.UniformBuffer, Size);
|
OglStreamBuffer buffer = new OglStreamBuffer(BufferTarget.UniformBuffer, size);
|
||||||
|
|
||||||
Cache.AddOrUpdate(Key, Buffer, Size);
|
_cache.AddOrUpdate(key, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCached(long Key, long Size)
|
public bool IsCached(long key, long size)
|
||||||
{
|
{
|
||||||
return Cache.TryGetSize(Key, out long CachedSize) && CachedSize == Size;
|
return _cache.TryGetSize(key, out long cachedSize) && cachedSize == size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(long Key, long Size, IntPtr HostAddress)
|
public void SetData(long key, long size, IntPtr hostAddress)
|
||||||
{
|
{
|
||||||
if (Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
|
if (_cache.TryGetValue(key, out OglStreamBuffer buffer))
|
||||||
{
|
{
|
||||||
Buffer.SetData(Size, HostAddress);
|
buffer.SetData(size, hostAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(long Key, byte[] Data)
|
public void SetData(long key, byte[] data)
|
||||||
{
|
{
|
||||||
if (Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
|
if (_cache.TryGetValue(key, out OglStreamBuffer buffer))
|
||||||
{
|
{
|
||||||
Buffer.SetData(Data);
|
buffer.SetData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetUbo(long Key, out int UboHandle)
|
public bool TryGetUbo(long key, out int uboHandle)
|
||||||
{
|
{
|
||||||
if (Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
|
if (_cache.TryGetValue(key, out OglStreamBuffer buffer))
|
||||||
{
|
{
|
||||||
UboHandle = Buffer.Handle;
|
uboHandle = buffer.Handle;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
UboHandle = 0;
|
uboHandle = 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DeleteBuffer(OGLStreamBuffer Buffer)
|
private static void DeleteBuffer(OglStreamBuffer buffer)
|
||||||
{
|
{
|
||||||
Buffer.Dispose();
|
buffer.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,34 +3,34 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
static class OGLEnumConverter
|
static class OglEnumConverter
|
||||||
{
|
{
|
||||||
public static FrontFaceDirection GetFrontFace(GalFrontFace FrontFace)
|
public static FrontFaceDirection GetFrontFace(GalFrontFace frontFace)
|
||||||
{
|
{
|
||||||
switch (FrontFace)
|
switch (frontFace)
|
||||||
{
|
{
|
||||||
case GalFrontFace.CW: return FrontFaceDirection.Cw;
|
case GalFrontFace.CW: return FrontFaceDirection.Cw;
|
||||||
case GalFrontFace.CCW: return FrontFaceDirection.Ccw;
|
case GalFrontFace.CCW: return FrontFaceDirection.Ccw;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(FrontFace) + " \"" + FrontFace + "\" is not valid!");
|
throw new ArgumentException(nameof(frontFace) + " \"" + frontFace + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CullFaceMode GetCullFace(GalCullFace CullFace)
|
public static CullFaceMode GetCullFace(GalCullFace cullFace)
|
||||||
{
|
{
|
||||||
switch (CullFace)
|
switch (cullFace)
|
||||||
{
|
{
|
||||||
case GalCullFace.Front: return CullFaceMode.Front;
|
case GalCullFace.Front: return CullFaceMode.Front;
|
||||||
case GalCullFace.Back: return CullFaceMode.Back;
|
case GalCullFace.Back: return CullFaceMode.Back;
|
||||||
case GalCullFace.FrontAndBack: return CullFaceMode.FrontAndBack;
|
case GalCullFace.FrontAndBack: return CullFaceMode.FrontAndBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(CullFace) + " \"" + CullFace + "\" is not valid!");
|
throw new ArgumentException(nameof(cullFace) + " \"" + cullFace + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StencilOp GetStencilOp(GalStencilOp Op)
|
public static StencilOp GetStencilOp(GalStencilOp op)
|
||||||
{
|
{
|
||||||
switch (Op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case GalStencilOp.Keep: return StencilOp.Keep;
|
case GalStencilOp.Keep: return StencilOp.Keep;
|
||||||
case GalStencilOp.Zero: return StencilOp.Zero;
|
case GalStencilOp.Zero: return StencilOp.Zero;
|
||||||
|
@ -42,28 +42,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalStencilOp.DecrWrap: return StencilOp.DecrWrap;
|
case GalStencilOp.DecrWrap: return StencilOp.DecrWrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Op) + " \"" + Op + "\" is not valid!");
|
throw new ArgumentException(nameof(op) + " \"" + op + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DepthFunction GetDepthFunc(GalComparisonOp Func)
|
public static DepthFunction GetDepthFunc(GalComparisonOp func)
|
||||||
{
|
{
|
||||||
return (DepthFunction)GetFunc(Func);
|
return (DepthFunction)GetFunc(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StencilFunction GetStencilFunc(GalComparisonOp Func)
|
public static StencilFunction GetStencilFunc(GalComparisonOp func)
|
||||||
{
|
{
|
||||||
return (StencilFunction)GetFunc(Func);
|
return (StencilFunction)GetFunc(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static All GetFunc(GalComparisonOp Func)
|
private static All GetFunc(GalComparisonOp func)
|
||||||
{
|
{
|
||||||
if ((int)Func >= (int)All.Never &&
|
if ((int)func >= (int)All.Never &&
|
||||||
(int)Func <= (int)All.Always)
|
(int)func <= (int)All.Always)
|
||||||
{
|
{
|
||||||
return (All)Func;
|
return (All)func;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Func)
|
switch (func)
|
||||||
{
|
{
|
||||||
case GalComparisonOp.Never: return All.Never;
|
case GalComparisonOp.Never: return All.Never;
|
||||||
case GalComparisonOp.Less: return All.Less;
|
case GalComparisonOp.Less: return All.Less;
|
||||||
|
@ -75,24 +75,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalComparisonOp.Always: return All.Always;
|
case GalComparisonOp.Always: return All.Always;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Func) + " \"" + Func + "\" is not valid!");
|
throw new ArgumentException(nameof(func) + " \"" + func + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DrawElementsType GetDrawElementsType(GalIndexFormat Format)
|
public static DrawElementsType GetDrawElementsType(GalIndexFormat format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case GalIndexFormat.Byte: return DrawElementsType.UnsignedByte;
|
case GalIndexFormat.Byte: return DrawElementsType.UnsignedByte;
|
||||||
case GalIndexFormat.Int16: return DrawElementsType.UnsignedShort;
|
case GalIndexFormat.Int16: return DrawElementsType.UnsignedShort;
|
||||||
case GalIndexFormat.Int32: return DrawElementsType.UnsignedInt;
|
case GalIndexFormat.Int32: return DrawElementsType.UnsignedInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Format) + " \"" + Format + "\" is not valid!");
|
throw new ArgumentException(nameof(format) + " \"" + format + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PrimitiveType GetPrimitiveType(GalPrimitiveType Type)
|
public static PrimitiveType GetPrimitiveType(GalPrimitiveType type)
|
||||||
{
|
{
|
||||||
switch (Type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case GalPrimitiveType.Points: return PrimitiveType.Points;
|
case GalPrimitiveType.Points: return PrimitiveType.Points;
|
||||||
case GalPrimitiveType.Lines: return PrimitiveType.Lines;
|
case GalPrimitiveType.Lines: return PrimitiveType.Lines;
|
||||||
|
@ -109,12 +109,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalPrimitiveType.Patches: return PrimitiveType.Patches;
|
case GalPrimitiveType.Patches: return PrimitiveType.Patches;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Type) + " \"" + Type + "\" is not valid!");
|
throw new ArgumentException(nameof(type) + " \"" + type + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShaderType GetShaderType(GalShaderType Type)
|
public static ShaderType GetShaderType(GalShaderType type)
|
||||||
{
|
{
|
||||||
switch (Type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case GalShaderType.Vertex: return ShaderType.VertexShader;
|
case GalShaderType.Vertex: return ShaderType.VertexShader;
|
||||||
case GalShaderType.TessControl: return ShaderType.TessControlShader;
|
case GalShaderType.TessControl: return ShaderType.TessControlShader;
|
||||||
|
@ -123,12 +123,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalShaderType.Fragment: return ShaderType.FragmentShader;
|
case GalShaderType.Fragment: return ShaderType.FragmentShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Type) + " \"" + Type + "\" is not valid!");
|
throw new ArgumentException(nameof(type) + " \"" + type + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (PixelInternalFormat, PixelFormat, PixelType) GetImageFormat(GalImageFormat Format)
|
public static (PixelInternalFormat, PixelFormat, PixelType) GetImageFormat(GalImageFormat format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case GalImageFormat.RGBA32 | GalImageFormat.Float: return (PixelInternalFormat.Rgba32f, PixelFormat.Rgba, PixelType.Float);
|
case GalImageFormat.RGBA32 | GalImageFormat.Float: return (PixelInternalFormat.Rgba32f, PixelFormat.Rgba, PixelType.Float);
|
||||||
case GalImageFormat.RGBA32 | GalImageFormat.Sint: return (PixelInternalFormat.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int);
|
case GalImageFormat.RGBA32 | GalImageFormat.Sint: return (PixelInternalFormat.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int);
|
||||||
|
@ -186,12 +186,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalImageFormat.D32S8 | GalImageFormat.Float: return (PixelInternalFormat.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev);
|
case GalImageFormat.D32S8 | GalImageFormat.Float: return (PixelInternalFormat.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException($"{Format & GalImageFormat.FormatMask} {Format & GalImageFormat.TypeMask}");
|
throw new NotImplementedException($"{format & GalImageFormat.FormatMask} {format & GalImageFormat.TypeMask}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static All GetDepthCompareFunc(DepthCompareFunc DepthCompareFunc)
|
public static All GetDepthCompareFunc(DepthCompareFunc depthCompareFunc)
|
||||||
{
|
{
|
||||||
switch (DepthCompareFunc)
|
switch (depthCompareFunc)
|
||||||
{
|
{
|
||||||
case DepthCompareFunc.LEqual:
|
case DepthCompareFunc.LEqual:
|
||||||
return All.Lequal;
|
return All.Lequal;
|
||||||
|
@ -210,13 +210,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case DepthCompareFunc.Never:
|
case DepthCompareFunc.Never:
|
||||||
return All.Never;
|
return All.Never;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException(nameof(DepthCompareFunc) + " \"" + DepthCompareFunc + "\" is not valid!");
|
throw new ArgumentException(nameof(depthCompareFunc) + " \"" + depthCompareFunc + "\" is not valid!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InternalFormat GetCompressedImageFormat(GalImageFormat Format)
|
public static InternalFormat GetCompressedImageFormat(GalImageFormat format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case GalImageFormat.BptcSfloat | GalImageFormat.Float: return InternalFormat.CompressedRgbBptcSignedFloat;
|
case GalImageFormat.BptcSfloat | GalImageFormat.Float: return InternalFormat.CompressedRgbBptcSignedFloat;
|
||||||
case GalImageFormat.BptcUfloat | GalImageFormat.Float: return InternalFormat.CompressedRgbBptcUnsignedFloat;
|
case GalImageFormat.BptcUfloat | GalImageFormat.Float: return InternalFormat.CompressedRgbBptcUnsignedFloat;
|
||||||
|
@ -234,12 +234,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalImageFormat.BC5 | GalImageFormat.Unorm: return InternalFormat.CompressedRgRgtc2;
|
case GalImageFormat.BC5 | GalImageFormat.Unorm: return InternalFormat.CompressedRgRgtc2;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException($"{Format & GalImageFormat.FormatMask} {Format & GalImageFormat.TypeMask}");
|
throw new NotImplementedException($"{format & GalImageFormat.FormatMask} {format & GalImageFormat.TypeMask}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static All GetTextureSwizzle(GalTextureSource Source)
|
public static All GetTextureSwizzle(GalTextureSource source)
|
||||||
{
|
{
|
||||||
switch (Source)
|
switch (source)
|
||||||
{
|
{
|
||||||
case GalTextureSource.Zero: return All.Zero;
|
case GalTextureSource.Zero: return All.Zero;
|
||||||
case GalTextureSource.Red: return All.Red;
|
case GalTextureSource.Red: return All.Red;
|
||||||
|
@ -250,12 +250,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalTextureSource.OneFloat: return All.One;
|
case GalTextureSource.OneFloat: return All.One;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Source) + " \"" + Source + "\" is not valid!");
|
throw new ArgumentException(nameof(source) + " \"" + source + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextureWrapMode GetTextureWrapMode(GalTextureWrap Wrap)
|
public static TextureWrapMode GetTextureWrapMode(GalTextureWrap wrap)
|
||||||
{
|
{
|
||||||
switch (Wrap)
|
switch (wrap)
|
||||||
{
|
{
|
||||||
case GalTextureWrap.Repeat: return TextureWrapMode.Repeat;
|
case GalTextureWrap.Repeat: return TextureWrapMode.Repeat;
|
||||||
case GalTextureWrap.MirroredRepeat: return TextureWrapMode.MirroredRepeat;
|
case GalTextureWrap.MirroredRepeat: return TextureWrapMode.MirroredRepeat;
|
||||||
|
@ -264,9 +264,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
case GalTextureWrap.Clamp: return TextureWrapMode.Clamp;
|
case GalTextureWrap.Clamp: return TextureWrapMode.Clamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OGLExtension.TextureMirrorClamp)
|
if (OglExtension.TextureMirrorClamp)
|
||||||
{
|
{
|
||||||
switch (Wrap)
|
switch (wrap)
|
||||||
{
|
{
|
||||||
case GalTextureWrap.MirrorClampToEdge: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToEdgeExt;
|
case GalTextureWrap.MirrorClampToEdge: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToEdgeExt;
|
||||||
case GalTextureWrap.MirrorClampToBorder: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToBorderExt;
|
case GalTextureWrap.MirrorClampToBorder: return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToBorderExt;
|
||||||
|
@ -276,7 +276,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Fallback to non-mirrored clamps
|
//Fallback to non-mirrored clamps
|
||||||
switch (Wrap)
|
switch (wrap)
|
||||||
{
|
{
|
||||||
case GalTextureWrap.MirrorClampToEdge: return TextureWrapMode.ClampToEdge;
|
case GalTextureWrap.MirrorClampToEdge: return TextureWrapMode.ClampToEdge;
|
||||||
case GalTextureWrap.MirrorClampToBorder: return TextureWrapMode.ClampToBorder;
|
case GalTextureWrap.MirrorClampToBorder: return TextureWrapMode.ClampToBorder;
|
||||||
|
@ -284,37 +284,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Wrap) + " \"" + Wrap + "\" is not valid!");
|
throw new ArgumentException(nameof(wrap) + " \"" + wrap + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextureMinFilter GetTextureMinFilter(
|
public static TextureMinFilter GetTextureMinFilter(
|
||||||
GalTextureFilter MinFilter,
|
GalTextureFilter minFilter,
|
||||||
GalTextureMipFilter MipFilter)
|
GalTextureMipFilter mipFilter)
|
||||||
{
|
{
|
||||||
//TODO: Mip (needs mipmap support first).
|
//TODO: Mip (needs mipmap support first).
|
||||||
switch (MinFilter)
|
switch (minFilter)
|
||||||
{
|
{
|
||||||
case GalTextureFilter.Nearest: return TextureMinFilter.Nearest;
|
case GalTextureFilter.Nearest: return TextureMinFilter.Nearest;
|
||||||
case GalTextureFilter.Linear: return TextureMinFilter.Linear;
|
case GalTextureFilter.Linear: return TextureMinFilter.Linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(MinFilter) + " \"" + MinFilter + "\" is not valid!");
|
throw new ArgumentException(nameof(minFilter) + " \"" + minFilter + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextureMagFilter GetTextureMagFilter(GalTextureFilter Filter)
|
public static TextureMagFilter GetTextureMagFilter(GalTextureFilter filter)
|
||||||
{
|
{
|
||||||
switch (Filter)
|
switch (filter)
|
||||||
{
|
{
|
||||||
case GalTextureFilter.Nearest: return TextureMagFilter.Nearest;
|
case GalTextureFilter.Nearest: return TextureMagFilter.Nearest;
|
||||||
case GalTextureFilter.Linear: return TextureMagFilter.Linear;
|
case GalTextureFilter.Linear: return TextureMagFilter.Linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Filter) + " \"" + Filter + "\" is not valid!");
|
throw new ArgumentException(nameof(filter) + " \"" + filter + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlendEquationMode GetBlendEquation(GalBlendEquation BlendEquation)
|
public static BlendEquationMode GetBlendEquation(GalBlendEquation blendEquation)
|
||||||
{
|
{
|
||||||
switch (BlendEquation)
|
switch (blendEquation)
|
||||||
{
|
{
|
||||||
case GalBlendEquation.FuncAdd:
|
case GalBlendEquation.FuncAdd:
|
||||||
case GalBlendEquation.FuncAddGl:
|
case GalBlendEquation.FuncAddGl:
|
||||||
|
@ -337,12 +337,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return BlendEquationMode.Max;
|
return BlendEquationMode.Max;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(BlendEquation) + " \"" + BlendEquation + "\" is not valid!");
|
throw new ArgumentException(nameof(blendEquation) + " \"" + blendEquation + "\" is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlendingFactor GetBlendFactor(GalBlendFactor BlendFactor)
|
public static BlendingFactor GetBlendFactor(GalBlendFactor blendFactor)
|
||||||
{
|
{
|
||||||
switch (BlendFactor)
|
switch (blendFactor)
|
||||||
{
|
{
|
||||||
case GalBlendFactor.Zero:
|
case GalBlendFactor.Zero:
|
||||||
case GalBlendFactor.ZeroGl:
|
case GalBlendFactor.ZeroGl:
|
||||||
|
@ -421,7 +421,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return BlendingFactor.ConstantColor;
|
return BlendingFactor.ConstantColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(BlendFactor) + " \"" + BlendFactor + "\" is not valid!");
|
throw new ArgumentException(nameof(blendFactor) + " \"" + blendFactor + "\" is not valid!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
static class OGLExtension
|
static class OglExtension
|
||||||
{
|
{
|
||||||
private static Lazy<bool> _enhancedLayouts = new Lazy<bool>(() => HasExtension("GL_ARB_enhanced_layouts"));
|
private static Lazy<bool> _enhancedLayouts = new Lazy<bool>(() => HasExtension("GL_ARB_enhanced_layouts"));
|
||||||
private static Lazy<bool> _textureMirrorClamp = new Lazy<bool>(() => HasExtension("GL_EXT_texture_mirror_clamp"));
|
private static Lazy<bool> _textureMirrorClamp = new Lazy<bool>(() => HasExtension("GL_EXT_texture_mirror_clamp"));
|
||||||
|
@ -16,13 +16,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
public static bool ViewportArray => _viewportArray.Value;
|
public static bool ViewportArray => _viewportArray.Value;
|
||||||
public static bool NvidiaDriver => _nvidiaDriver.Value;
|
public static bool NvidiaDriver => _nvidiaDriver.Value;
|
||||||
|
|
||||||
private static bool HasExtension(string Name)
|
private static bool HasExtension(string name)
|
||||||
{
|
{
|
||||||
int NumExtensions = GL.GetInteger(GetPName.NumExtensions);
|
int numExtensions = GL.GetInteger(GetPName.NumExtensions);
|
||||||
|
|
||||||
for (int Extension = 0; Extension < NumExtensions; Extension++)
|
for (int extension = 0; extension < numExtensions; extension++)
|
||||||
{
|
{
|
||||||
if (GL.GetString(StringNameIndexed.Extensions, Extension) == Name)
|
if (GL.GetString(StringNameIndexed.Extensions, extension) == name)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
static class OGLLimit
|
static class OglLimit
|
||||||
{
|
{
|
||||||
private static Lazy<int> s_MaxUboSize = new Lazy<int>(() => GL.GetInteger(GetPName.MaxUniformBlockSize));
|
private static Lazy<int> _sMaxUboSize = new Lazy<int>(() => GL.GetInteger(GetPName.MaxUniformBlockSize));
|
||||||
|
|
||||||
public static int MaxUboSize => s_MaxUboSize.Value;
|
public static int MaxUboSize => _sMaxUboSize.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,9 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLPipeline : IGalPipeline
|
class OglPipeline : IGalPipeline
|
||||||
{
|
{
|
||||||
private static Dictionary<GalVertexAttribSize, int> AttribElements =
|
private static Dictionary<GalVertexAttribSize, int> _attribElements =
|
||||||
new Dictionary<GalVertexAttribSize, int>()
|
new Dictionary<GalVertexAttribSize, int>()
|
||||||
{
|
{
|
||||||
{ GalVertexAttribSize._32_32_32_32, 4 },
|
{ GalVertexAttribSize._32_32_32_32, 4 },
|
||||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{ GalVertexAttribSize._11_11_10, 3 }
|
{ GalVertexAttribSize._11_11_10, 3 }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> FloatAttribTypes =
|
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> _floatAttribTypes =
|
||||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||||
{
|
{
|
||||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Float },
|
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Float },
|
||||||
|
@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{ GalVertexAttribSize._16, VertexAttribPointerType.HalfFloat }
|
{ GalVertexAttribSize._16, VertexAttribPointerType.HalfFloat }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> SignedAttribTypes =
|
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> _signedAttribTypes =
|
||||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||||
{
|
{
|
||||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
|
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
|
||||||
|
@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int2101010Rev }
|
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int2101010Rev }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> UnsignedAttribTypes =
|
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> _unsignedAttribTypes =
|
||||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||||
{
|
{
|
||||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.UnsignedInt },
|
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.UnsignedInt },
|
||||||
|
@ -75,28 +75,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
|
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.UnsignedInt10F11F11FRev }
|
||||||
};
|
};
|
||||||
|
|
||||||
private GalPipelineState Old;
|
private GalPipelineState _old;
|
||||||
|
|
||||||
private OGLConstBuffer Buffer;
|
private OglConstBuffer _buffer;
|
||||||
private OGLRenderTarget RenderTarget;
|
private OglRenderTarget _renderTarget;
|
||||||
private OGLRasterizer Rasterizer;
|
private OglRasterizer _rasterizer;
|
||||||
private OGLShader Shader;
|
private OglShader _shader;
|
||||||
|
|
||||||
private int VaoHandle;
|
private int _vaoHandle;
|
||||||
|
|
||||||
public OGLPipeline(
|
public OglPipeline(
|
||||||
OGLConstBuffer Buffer,
|
OglConstBuffer buffer,
|
||||||
OGLRenderTarget RenderTarget,
|
OglRenderTarget renderTarget,
|
||||||
OGLRasterizer Rasterizer,
|
OglRasterizer rasterizer,
|
||||||
OGLShader Shader)
|
OglShader shader)
|
||||||
{
|
{
|
||||||
this.Buffer = Buffer;
|
_buffer = buffer;
|
||||||
this.RenderTarget = RenderTarget;
|
_renderTarget = renderTarget;
|
||||||
this.Rasterizer = Rasterizer;
|
_rasterizer = rasterizer;
|
||||||
this.Shader = Shader;
|
_shader = shader;
|
||||||
|
|
||||||
//These values match OpenGL's defaults
|
//These values match OpenGL's defaults
|
||||||
Old = new GalPipelineState
|
_old = new GalPipelineState
|
||||||
{
|
{
|
||||||
FrontFace = GalFrontFace.CCW,
|
FrontFace = GalFrontFace.CCW,
|
||||||
|
|
||||||
|
@ -133,11 +133,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
PrimitiveRestartIndex = 0
|
PrimitiveRestartIndex = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
|
||||||
{
|
{
|
||||||
Old.Blends[Index] = BlendState.Default;
|
_old.Blends[index] = BlendState.Default;
|
||||||
|
|
||||||
Old.ColorMasks[Index] = ColorMaskState.Default;
|
_old.ColorMasks[index] = ColorMaskState.Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,122 +147,122 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
BindVertexLayout(New);
|
BindVertexLayout(New);
|
||||||
|
|
||||||
if (New.FramebufferSrgb != Old.FramebufferSrgb)
|
if (New.FramebufferSrgb != _old.FramebufferSrgb)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
|
Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
|
||||||
|
|
||||||
RenderTarget.FramebufferSrgb = New.FramebufferSrgb;
|
_renderTarget.FramebufferSrgb = New.FramebufferSrgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance)
|
if (New.FlipX != _old.FlipX || New.FlipY != _old.FlipY || New.Instance != _old.Instance)
|
||||||
{
|
{
|
||||||
Shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
|
_shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FrontFace != Old.FrontFace)
|
if (New.FrontFace != _old.FrontFace)
|
||||||
{
|
{
|
||||||
GL.FrontFace(OGLEnumConverter.GetFrontFace(New.FrontFace));
|
GL.FrontFace(OglEnumConverter.GetFrontFace(New.FrontFace));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.CullFaceEnabled != Old.CullFaceEnabled)
|
if (New.CullFaceEnabled != _old.CullFaceEnabled)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.CullFace, New.CullFaceEnabled);
|
Enable(EnableCap.CullFace, New.CullFaceEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.CullFaceEnabled)
|
if (New.CullFaceEnabled)
|
||||||
{
|
{
|
||||||
if (New.CullFace != Old.CullFace)
|
if (New.CullFace != _old.CullFace)
|
||||||
{
|
{
|
||||||
GL.CullFace(OGLEnumConverter.GetCullFace(New.CullFace));
|
GL.CullFace(OglEnumConverter.GetCullFace(New.CullFace));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.DepthTestEnabled != Old.DepthTestEnabled)
|
if (New.DepthTestEnabled != _old.DepthTestEnabled)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.DepthTest, New.DepthTestEnabled);
|
Enable(EnableCap.DepthTest, New.DepthTestEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.DepthWriteEnabled != Old.DepthWriteEnabled)
|
if (New.DepthWriteEnabled != _old.DepthWriteEnabled)
|
||||||
{
|
{
|
||||||
GL.DepthMask(New.DepthWriteEnabled);
|
GL.DepthMask(New.DepthWriteEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.DepthTestEnabled)
|
if (New.DepthTestEnabled)
|
||||||
{
|
{
|
||||||
if (New.DepthFunc != Old.DepthFunc)
|
if (New.DepthFunc != _old.DepthFunc)
|
||||||
{
|
{
|
||||||
GL.DepthFunc(OGLEnumConverter.GetDepthFunc(New.DepthFunc));
|
GL.DepthFunc(OglEnumConverter.GetDepthFunc(New.DepthFunc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.DepthRangeNear != Old.DepthRangeNear ||
|
if (New.DepthRangeNear != _old.DepthRangeNear ||
|
||||||
New.DepthRangeFar != Old.DepthRangeFar)
|
New.DepthRangeFar != _old.DepthRangeFar)
|
||||||
{
|
{
|
||||||
GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar);
|
GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilTestEnabled != Old.StencilTestEnabled)
|
if (New.StencilTestEnabled != _old.StencilTestEnabled)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.StencilTest, New.StencilTestEnabled);
|
Enable(EnableCap.StencilTest, New.StencilTestEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilTwoSideEnabled != Old.StencilTwoSideEnabled)
|
if (New.StencilTwoSideEnabled != _old.StencilTwoSideEnabled)
|
||||||
{
|
{
|
||||||
Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
|
Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilTestEnabled)
|
if (New.StencilTestEnabled)
|
||||||
{
|
{
|
||||||
if (New.StencilBackFuncFunc != Old.StencilBackFuncFunc ||
|
if (New.StencilBackFuncFunc != _old.StencilBackFuncFunc ||
|
||||||
New.StencilBackFuncRef != Old.StencilBackFuncRef ||
|
New.StencilBackFuncRef != _old.StencilBackFuncRef ||
|
||||||
New.StencilBackFuncMask != Old.StencilBackFuncMask)
|
New.StencilBackFuncMask != _old.StencilBackFuncMask)
|
||||||
{
|
{
|
||||||
GL.StencilFuncSeparate(
|
GL.StencilFuncSeparate(
|
||||||
StencilFace.Back,
|
StencilFace.Back,
|
||||||
OGLEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
|
OglEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
|
||||||
New.StencilBackFuncRef,
|
New.StencilBackFuncRef,
|
||||||
New.StencilBackFuncMask);
|
New.StencilBackFuncMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilBackOpFail != Old.StencilBackOpFail ||
|
if (New.StencilBackOpFail != _old.StencilBackOpFail ||
|
||||||
New.StencilBackOpZFail != Old.StencilBackOpZFail ||
|
New.StencilBackOpZFail != _old.StencilBackOpZFail ||
|
||||||
New.StencilBackOpZPass != Old.StencilBackOpZPass)
|
New.StencilBackOpZPass != _old.StencilBackOpZPass)
|
||||||
{
|
{
|
||||||
GL.StencilOpSeparate(
|
GL.StencilOpSeparate(
|
||||||
StencilFace.Back,
|
StencilFace.Back,
|
||||||
OGLEnumConverter.GetStencilOp(New.StencilBackOpFail),
|
OglEnumConverter.GetStencilOp(New.StencilBackOpFail),
|
||||||
OGLEnumConverter.GetStencilOp(New.StencilBackOpZFail),
|
OglEnumConverter.GetStencilOp(New.StencilBackOpZFail),
|
||||||
OGLEnumConverter.GetStencilOp(New.StencilBackOpZPass));
|
OglEnumConverter.GetStencilOp(New.StencilBackOpZPass));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilBackMask != Old.StencilBackMask)
|
if (New.StencilBackMask != _old.StencilBackMask)
|
||||||
{
|
{
|
||||||
GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
|
GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilFrontFuncFunc != Old.StencilFrontFuncFunc ||
|
if (New.StencilFrontFuncFunc != _old.StencilFrontFuncFunc ||
|
||||||
New.StencilFrontFuncRef != Old.StencilFrontFuncRef ||
|
New.StencilFrontFuncRef != _old.StencilFrontFuncRef ||
|
||||||
New.StencilFrontFuncMask != Old.StencilFrontFuncMask)
|
New.StencilFrontFuncMask != _old.StencilFrontFuncMask)
|
||||||
{
|
{
|
||||||
GL.StencilFuncSeparate(
|
GL.StencilFuncSeparate(
|
||||||
StencilFace.Front,
|
StencilFace.Front,
|
||||||
OGLEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
|
OglEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
|
||||||
New.StencilFrontFuncRef,
|
New.StencilFrontFuncRef,
|
||||||
New.StencilFrontFuncMask);
|
New.StencilFrontFuncMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilFrontOpFail != Old.StencilFrontOpFail ||
|
if (New.StencilFrontOpFail != _old.StencilFrontOpFail ||
|
||||||
New.StencilFrontOpZFail != Old.StencilFrontOpZFail ||
|
New.StencilFrontOpZFail != _old.StencilFrontOpZFail ||
|
||||||
New.StencilFrontOpZPass != Old.StencilFrontOpZPass)
|
New.StencilFrontOpZPass != _old.StencilFrontOpZPass)
|
||||||
{
|
{
|
||||||
GL.StencilOpSeparate(
|
GL.StencilOpSeparate(
|
||||||
StencilFace.Front,
|
StencilFace.Front,
|
||||||
OGLEnumConverter.GetStencilOp(New.StencilFrontOpFail),
|
OglEnumConverter.GetStencilOp(New.StencilFrontOpFail),
|
||||||
OGLEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
|
OglEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
|
||||||
OGLEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
|
OglEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.StencilFrontMask != Old.StencilFrontMask)
|
if (New.StencilFrontMask != _old.StencilFrontMask)
|
||||||
{
|
{
|
||||||
GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
|
GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
|
||||||
}
|
}
|
||||||
|
@ -272,11 +272,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
// Scissor Test
|
// Scissor Test
|
||||||
bool forceUpdate;
|
bool forceUpdate;
|
||||||
|
|
||||||
for (int Index = 0; Index < New.ScissorTestCount; Index++)
|
for (int index = 0; index < New.ScissorTestCount; index++)
|
||||||
{
|
{
|
||||||
forceUpdate = false;
|
forceUpdate = false;
|
||||||
|
|
||||||
if (New.ScissorTestEnabled[Index])
|
if (New.ScissorTestEnabled[index])
|
||||||
{
|
{
|
||||||
// If there is only 1 scissor test, geometry shaders are disabled so the scissor test applies to all viewports
|
// If there is only 1 scissor test, geometry shaders are disabled so the scissor test applies to all viewports
|
||||||
if (New.ScissorTestCount == 1)
|
if (New.ScissorTestCount == 1)
|
||||||
|
@ -285,32 +285,32 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.Enable(IndexedEnableCap.ScissorTest, Index);
|
GL.Enable(IndexedEnableCap.ScissorTest, index);
|
||||||
}
|
}
|
||||||
forceUpdate = true;
|
forceUpdate = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.Disable(IndexedEnableCap.ScissorTest, Index);
|
GL.Disable(IndexedEnableCap.ScissorTest, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.ScissorTestEnabled[Index] &&
|
if (New.ScissorTestEnabled[index] &&
|
||||||
(New.ScissorTestX[Index] != Old.ScissorTestX[Index] ||
|
(New.ScissorTestX[index] != _old.ScissorTestX[index] ||
|
||||||
New.ScissorTestY[Index] != Old.ScissorTestY[Index] ||
|
New.ScissorTestY[index] != _old.ScissorTestY[index] ||
|
||||||
New.ScissorTestWidth[Index] != Old.ScissorTestWidth[Index] ||
|
New.ScissorTestWidth[index] != _old.ScissorTestWidth[index] ||
|
||||||
New.ScissorTestHeight[Index] != Old.ScissorTestHeight[Index] ||
|
New.ScissorTestHeight[index] != _old.ScissorTestHeight[index] ||
|
||||||
forceUpdate)) // Force update intentionally last to reduce if comparisons
|
forceUpdate)) // Force update intentionally last to reduce if comparisons
|
||||||
{
|
{
|
||||||
// If there is only 1 scissor test geometry shaders are disables so the scissor test applies to all viewports
|
// If there is only 1 scissor test geometry shaders are disables so the scissor test applies to all viewports
|
||||||
if (New.ScissorTestCount == 1)
|
if (New.ScissorTestCount == 1)
|
||||||
{
|
{
|
||||||
GL.Scissor(New.ScissorTestX[Index], New.ScissorTestY[Index],
|
GL.Scissor(New.ScissorTestX[index], New.ScissorTestY[index],
|
||||||
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
New.ScissorTestWidth[index], New.ScissorTestHeight[index]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.ScissorIndexed(Index, New.ScissorTestX[Index], New.ScissorTestY[Index],
|
GL.ScissorIndexed(index, New.ScissorTestX[index], New.ScissorTestY[index],
|
||||||
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
New.ScissorTestWidth[index], New.ScissorTestHeight[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,26 +318,26 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
if (New.BlendIndependent)
|
if (New.BlendIndependent)
|
||||||
{
|
{
|
||||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
|
||||||
{
|
{
|
||||||
SetBlendState(Index, New.Blends[Index], Old.Blends[Index]);
|
SetBlendState(index, New.Blends[index], _old.Blends[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (New.BlendIndependent != Old.BlendIndependent)
|
if (New.BlendIndependent != _old.BlendIndependent)
|
||||||
{
|
{
|
||||||
SetAllBlendState(New.Blends[0]);
|
SetAllBlendState(New.Blends[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetBlendState(New.Blends[0], Old.Blends[0]);
|
SetBlendState(New.Blends[0], _old.Blends[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.ColorMaskCommon)
|
if (New.ColorMaskCommon)
|
||||||
{
|
{
|
||||||
if (New.ColorMaskCommon != Old.ColorMaskCommon || !New.ColorMasks[0].Equals(Old.ColorMasks[0]))
|
if (New.ColorMaskCommon != _old.ColorMaskCommon || !New.ColorMasks[0].Equals(_old.ColorMasks[0]))
|
||||||
{
|
{
|
||||||
GL.ColorMask(
|
GL.ColorMask(
|
||||||
New.ColorMasks[0].Red,
|
New.ColorMasks[0].Red,
|
||||||
|
@ -348,34 +348,34 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
|
||||||
{
|
{
|
||||||
if (!New.ColorMasks[Index].Equals(Old.ColorMasks[Index]))
|
if (!New.ColorMasks[index].Equals(_old.ColorMasks[index]))
|
||||||
{
|
{
|
||||||
GL.ColorMask(
|
GL.ColorMask(
|
||||||
Index,
|
index,
|
||||||
New.ColorMasks[Index].Red,
|
New.ColorMasks[index].Red,
|
||||||
New.ColorMasks[Index].Green,
|
New.ColorMasks[index].Green,
|
||||||
New.ColorMasks[Index].Blue,
|
New.ColorMasks[index].Blue,
|
||||||
New.ColorMasks[Index].Alpha);
|
New.ColorMasks[index].Alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.PrimitiveRestartEnabled != Old.PrimitiveRestartEnabled)
|
if (New.PrimitiveRestartEnabled != _old.PrimitiveRestartEnabled)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
|
Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.PrimitiveRestartEnabled)
|
if (New.PrimitiveRestartEnabled)
|
||||||
{
|
{
|
||||||
if (New.PrimitiveRestartIndex != Old.PrimitiveRestartIndex)
|
if (New.PrimitiveRestartIndex != _old.PrimitiveRestartIndex)
|
||||||
{
|
{
|
||||||
GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
|
GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Old = New;
|
_old = New;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetAllBlendState(BlendState New)
|
private void SetAllBlendState(BlendState New)
|
||||||
|
@ -387,29 +387,29 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
if (New.SeparateAlpha)
|
if (New.SeparateAlpha)
|
||||||
{
|
{
|
||||||
GL.BlendEquationSeparate(
|
GL.BlendEquationSeparate(
|
||||||
OGLEnumConverter.GetBlendEquation(New.EquationRgb),
|
OglEnumConverter.GetBlendEquation(New.EquationRgb),
|
||||||
OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
|
OglEnumConverter.GetBlendEquation(New.EquationAlpha));
|
||||||
|
|
||||||
GL.BlendFuncSeparate(
|
GL.BlendFuncSeparate(
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.EquationRgb));
|
GL.BlendEquation(OglEnumConverter.GetBlendEquation(New.EquationRgb));
|
||||||
|
|
||||||
GL.BlendFunc(
|
GL.BlendFunc(
|
||||||
OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBlendState(BlendState New, BlendState Old)
|
private void SetBlendState(BlendState New, BlendState old)
|
||||||
{
|
{
|
||||||
if (New.Enabled != Old.Enabled)
|
if (New.Enabled != old.Enabled)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.Blend, New.Enabled);
|
Enable(EnableCap.Blend, New.Enabled);
|
||||||
}
|
}
|
||||||
|
@ -418,91 +418,91 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
if (New.SeparateAlpha)
|
if (New.SeparateAlpha)
|
||||||
{
|
{
|
||||||
if (New.EquationRgb != Old.EquationRgb ||
|
if (New.EquationRgb != old.EquationRgb ||
|
||||||
New.EquationAlpha != Old.EquationAlpha)
|
New.EquationAlpha != old.EquationAlpha)
|
||||||
{
|
{
|
||||||
GL.BlendEquationSeparate(
|
GL.BlendEquationSeparate(
|
||||||
OGLEnumConverter.GetBlendEquation(New.EquationRgb),
|
OglEnumConverter.GetBlendEquation(New.EquationRgb),
|
||||||
OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
|
OglEnumConverter.GetBlendEquation(New.EquationAlpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
if (New.FuncSrcRgb != old.FuncSrcRgb ||
|
||||||
New.FuncDstRgb != Old.FuncDstRgb ||
|
New.FuncDstRgb != old.FuncDstRgb ||
|
||||||
New.FuncSrcAlpha != Old.FuncSrcAlpha ||
|
New.FuncSrcAlpha != old.FuncSrcAlpha ||
|
||||||
New.FuncDstAlpha != Old.FuncDstAlpha)
|
New.FuncDstAlpha != old.FuncDstAlpha)
|
||||||
{
|
{
|
||||||
GL.BlendFuncSeparate(
|
GL.BlendFuncSeparate(
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (New.EquationRgb != Old.EquationRgb)
|
if (New.EquationRgb != old.EquationRgb)
|
||||||
{
|
{
|
||||||
GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.EquationRgb));
|
GL.BlendEquation(OglEnumConverter.GetBlendEquation(New.EquationRgb));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
if (New.FuncSrcRgb != old.FuncSrcRgb ||
|
||||||
New.FuncDstRgb != Old.FuncDstRgb)
|
New.FuncDstRgb != old.FuncDstRgb)
|
||||||
{
|
{
|
||||||
GL.BlendFunc(
|
GL.BlendFunc(
|
||||||
OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBlendState(int Index, BlendState New, BlendState Old)
|
private void SetBlendState(int index, BlendState New, BlendState old)
|
||||||
{
|
{
|
||||||
if (New.Enabled != Old.Enabled)
|
if (New.Enabled != old.Enabled)
|
||||||
{
|
{
|
||||||
Enable(IndexedEnableCap.Blend, Index, New.Enabled);
|
Enable(IndexedEnableCap.Blend, index, New.Enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.Enabled)
|
if (New.Enabled)
|
||||||
{
|
{
|
||||||
if (New.SeparateAlpha)
|
if (New.SeparateAlpha)
|
||||||
{
|
{
|
||||||
if (New.EquationRgb != Old.EquationRgb ||
|
if (New.EquationRgb != old.EquationRgb ||
|
||||||
New.EquationAlpha != Old.EquationAlpha)
|
New.EquationAlpha != old.EquationAlpha)
|
||||||
{
|
{
|
||||||
GL.BlendEquationSeparate(
|
GL.BlendEquationSeparate(
|
||||||
Index,
|
index,
|
||||||
OGLEnumConverter.GetBlendEquation(New.EquationRgb),
|
OglEnumConverter.GetBlendEquation(New.EquationRgb),
|
||||||
OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
|
OglEnumConverter.GetBlendEquation(New.EquationAlpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
if (New.FuncSrcRgb != old.FuncSrcRgb ||
|
||||||
New.FuncDstRgb != Old.FuncDstRgb ||
|
New.FuncDstRgb != old.FuncDstRgb ||
|
||||||
New.FuncSrcAlpha != Old.FuncSrcAlpha ||
|
New.FuncSrcAlpha != old.FuncSrcAlpha ||
|
||||||
New.FuncDstAlpha != Old.FuncDstAlpha)
|
New.FuncDstAlpha != old.FuncDstAlpha)
|
||||||
{
|
{
|
||||||
GL.BlendFuncSeparate(
|
GL.BlendFuncSeparate(
|
||||||
Index,
|
index,
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (New.EquationRgb != Old.EquationRgb)
|
if (New.EquationRgb != old.EquationRgb)
|
||||||
{
|
{
|
||||||
GL.BlendEquation(Index, OGLEnumConverter.GetBlendEquation(New.EquationRgb));
|
GL.BlendEquation(index, OglEnumConverter.GetBlendEquation(New.EquationRgb));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FuncSrcRgb != Old.FuncSrcRgb ||
|
if (New.FuncSrcRgb != old.FuncSrcRgb ||
|
||||||
New.FuncDstRgb != Old.FuncDstRgb)
|
New.FuncDstRgb != old.FuncDstRgb)
|
||||||
{
|
{
|
||||||
GL.BlendFunc(
|
GL.BlendFunc(
|
||||||
Index,
|
index,
|
||||||
(BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
(BlendingFactorSrc) OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
|
||||||
(BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
(BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,310 +510,310 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private void BindConstBuffers(GalPipelineState New)
|
private void BindConstBuffers(GalPipelineState New)
|
||||||
{
|
{
|
||||||
int FreeBinding = OGLShader.ReservedCbufCount;
|
int freeBinding = OglShader.ReservedCbufCount;
|
||||||
|
|
||||||
void BindIfNotNull(OGLShaderStage Stage)
|
void BindIfNotNull(OglShaderStage stage)
|
||||||
{
|
{
|
||||||
if (Stage != null)
|
if (stage != null)
|
||||||
{
|
{
|
||||||
foreach (ShaderDeclInfo DeclInfo in Stage.ConstBufferUsage)
|
foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage)
|
||||||
{
|
{
|
||||||
long Key = New.ConstBufferKeys[(int)Stage.Type][DeclInfo.Cbuf];
|
long key = New.ConstBufferKeys[(int)stage.Type][declInfo.Cbuf];
|
||||||
|
|
||||||
if (Key != 0 && Buffer.TryGetUbo(Key, out int UboHandle))
|
if (key != 0 && _buffer.TryGetUbo(key, out int uboHandle))
|
||||||
{
|
{
|
||||||
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, FreeBinding, UboHandle);
|
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, freeBinding, uboHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeBinding++;
|
freeBinding++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BindIfNotNull(Shader.Current.Vertex);
|
BindIfNotNull(_shader.Current.Vertex);
|
||||||
BindIfNotNull(Shader.Current.TessControl);
|
BindIfNotNull(_shader.Current.TessControl);
|
||||||
BindIfNotNull(Shader.Current.TessEvaluation);
|
BindIfNotNull(_shader.Current.TessEvaluation);
|
||||||
BindIfNotNull(Shader.Current.Geometry);
|
BindIfNotNull(_shader.Current.Geometry);
|
||||||
BindIfNotNull(Shader.Current.Fragment);
|
BindIfNotNull(_shader.Current.Fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindVertexLayout(GalPipelineState New)
|
private void BindVertexLayout(GalPipelineState New)
|
||||||
{
|
{
|
||||||
foreach (GalVertexBinding Binding in New.VertexBindings)
|
foreach (GalVertexBinding binding in New.VertexBindings)
|
||||||
{
|
{
|
||||||
if (!Binding.Enabled || !Rasterizer.TryGetVbo(Binding.VboKey, out int VboHandle))
|
if (!binding.Enabled || !_rasterizer.TryGetVbo(binding.VboKey, out int vboHandle))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VaoHandle == 0)
|
if (_vaoHandle == 0)
|
||||||
{
|
{
|
||||||
VaoHandle = GL.GenVertexArray();
|
_vaoHandle = GL.GenVertexArray();
|
||||||
|
|
||||||
//Vertex arrays shouldn't be used anywhere else in OpenGL's backend
|
//Vertex arrays shouldn't be used anywhere else in OpenGL's backend
|
||||||
//if you want to use it, move this line out of the if
|
//if you want to use it, move this line out of the if
|
||||||
GL.BindVertexArray(VaoHandle);
|
GL.BindVertexArray(_vaoHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (GalVertexAttrib Attrib in Binding.Attribs)
|
foreach (GalVertexAttrib attrib in binding.Attribs)
|
||||||
{
|
{
|
||||||
//Skip uninitialized attributes.
|
//Skip uninitialized attributes.
|
||||||
if (Attrib.Size == 0)
|
if (attrib.Size == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
GL.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
|
||||||
|
|
||||||
bool Unsigned =
|
bool unsigned =
|
||||||
Attrib.Type == GalVertexAttribType.Unorm ||
|
attrib.Type == GalVertexAttribType.Unorm ||
|
||||||
Attrib.Type == GalVertexAttribType.Uint ||
|
attrib.Type == GalVertexAttribType.Uint ||
|
||||||
Attrib.Type == GalVertexAttribType.Uscaled;
|
attrib.Type == GalVertexAttribType.Uscaled;
|
||||||
|
|
||||||
bool Normalize =
|
bool normalize =
|
||||||
Attrib.Type == GalVertexAttribType.Snorm ||
|
attrib.Type == GalVertexAttribType.Snorm ||
|
||||||
Attrib.Type == GalVertexAttribType.Unorm;
|
attrib.Type == GalVertexAttribType.Unorm;
|
||||||
|
|
||||||
VertexAttribPointerType Type = 0;
|
VertexAttribPointerType type = 0;
|
||||||
|
|
||||||
if (Attrib.Type == GalVertexAttribType.Float)
|
if (attrib.Type == GalVertexAttribType.Float)
|
||||||
{
|
{
|
||||||
Type = GetType(FloatAttribTypes, Attrib);
|
type = GetType(_floatAttribTypes, attrib);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Unsigned)
|
if (unsigned)
|
||||||
{
|
{
|
||||||
Type = GetType(UnsignedAttribTypes, Attrib);
|
type = GetType(_unsignedAttribTypes, attrib);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Type = GetType(SignedAttribTypes, Attrib);
|
type = GetType(_signedAttribTypes, attrib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AttribElements.TryGetValue(Attrib.Size, out int Size))
|
if (!_attribElements.TryGetValue(attrib.Size, out int size))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid attribute size \"" + Attrib.Size + "\"!");
|
throw new InvalidOperationException("Invalid attribute size \"" + attrib.Size + "\"!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int Offset = Attrib.Offset;
|
int offset = attrib.Offset;
|
||||||
|
|
||||||
if (Binding.Stride != 0)
|
if (binding.Stride != 0)
|
||||||
{
|
{
|
||||||
GL.EnableVertexAttribArray(Attrib.Index);
|
GL.EnableVertexAttribArray(attrib.Index);
|
||||||
|
|
||||||
if (Attrib.Type == GalVertexAttribType.Sint ||
|
if (attrib.Type == GalVertexAttribType.Sint ||
|
||||||
Attrib.Type == GalVertexAttribType.Uint)
|
attrib.Type == GalVertexAttribType.Uint)
|
||||||
{
|
{
|
||||||
IntPtr Pointer = new IntPtr(Offset);
|
IntPtr pointer = new IntPtr(offset);
|
||||||
|
|
||||||
VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
|
VertexAttribIntegerType iType = (VertexAttribIntegerType)type;
|
||||||
|
|
||||||
GL.VertexAttribIPointer(Attrib.Index, Size, IType, Binding.Stride, Pointer);
|
GL.VertexAttribIPointer(attrib.Index, size, iType, binding.Stride, pointer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
|
GL.VertexAttribPointer(attrib.Index, size, type, normalize, binding.Stride, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.DisableVertexAttribArray(Attrib.Index);
|
GL.DisableVertexAttribArray(attrib.Index);
|
||||||
|
|
||||||
SetConstAttrib(Attrib);
|
SetConstAttrib(attrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Binding.Instanced && Binding.Divisor != 0)
|
if (binding.Instanced && binding.Divisor != 0)
|
||||||
{
|
{
|
||||||
GL.VertexAttribDivisor(Attrib.Index, 1);
|
GL.VertexAttribDivisor(attrib.Index, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.VertexAttribDivisor(Attrib.Index, 0);
|
GL.VertexAttribDivisor(attrib.Index, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VertexAttribPointerType GetType(Dictionary<GalVertexAttribSize, VertexAttribPointerType> Dict, GalVertexAttrib Attrib)
|
private static VertexAttribPointerType GetType(Dictionary<GalVertexAttribSize, VertexAttribPointerType> dict, GalVertexAttrib attrib)
|
||||||
{
|
{
|
||||||
if (!Dict.TryGetValue(Attrib.Size, out VertexAttribPointerType Type))
|
if (!dict.TryGetValue(attrib.Size, out VertexAttribPointerType type))
|
||||||
{
|
{
|
||||||
ThrowUnsupportedAttrib(Attrib);
|
ThrowUnsupportedAttrib(attrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe static void SetConstAttrib(GalVertexAttrib Attrib)
|
private unsafe static void SetConstAttrib(GalVertexAttrib attrib)
|
||||||
{
|
{
|
||||||
if (Attrib.Size == GalVertexAttribSize._10_10_10_2 ||
|
if (attrib.Size == GalVertexAttribSize._10_10_10_2 ||
|
||||||
Attrib.Size == GalVertexAttribSize._11_11_10)
|
attrib.Size == GalVertexAttribSize._11_11_10)
|
||||||
{
|
{
|
||||||
ThrowUnsupportedAttrib(Attrib);
|
ThrowUnsupportedAttrib(attrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed (byte* Ptr = Attrib.Data)
|
fixed (byte* ptr = attrib.Data)
|
||||||
{
|
{
|
||||||
if (Attrib.Type == GalVertexAttribType.Unorm)
|
if (attrib.Type == GalVertexAttribType.Unorm)
|
||||||
{
|
{
|
||||||
switch (Attrib.Size)
|
switch (attrib.Size)
|
||||||
{
|
{
|
||||||
case GalVertexAttribSize._8:
|
case GalVertexAttribSize._8:
|
||||||
case GalVertexAttribSize._8_8:
|
case GalVertexAttribSize._8_8:
|
||||||
case GalVertexAttribSize._8_8_8:
|
case GalVertexAttribSize._8_8_8:
|
||||||
case GalVertexAttribSize._8_8_8_8:
|
case GalVertexAttribSize._8_8_8_8:
|
||||||
GL.VertexAttrib4N((uint)Attrib.Index, Ptr);
|
GL.VertexAttrib4N((uint)attrib.Index, ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._16:
|
case GalVertexAttribSize._16:
|
||||||
case GalVertexAttribSize._16_16:
|
case GalVertexAttribSize._16_16:
|
||||||
case GalVertexAttribSize._16_16_16:
|
case GalVertexAttribSize._16_16_16:
|
||||||
case GalVertexAttribSize._16_16_16_16:
|
case GalVertexAttribSize._16_16_16_16:
|
||||||
GL.VertexAttrib4N((uint)Attrib.Index, (ushort*)Ptr);
|
GL.VertexAttrib4N((uint)attrib.Index, (ushort*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._32:
|
case GalVertexAttribSize._32:
|
||||||
case GalVertexAttribSize._32_32:
|
case GalVertexAttribSize._32_32:
|
||||||
case GalVertexAttribSize._32_32_32:
|
case GalVertexAttribSize._32_32_32:
|
||||||
case GalVertexAttribSize._32_32_32_32:
|
case GalVertexAttribSize._32_32_32_32:
|
||||||
GL.VertexAttrib4N((uint)Attrib.Index, (uint*)Ptr);
|
GL.VertexAttrib4N((uint)attrib.Index, (uint*)ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Attrib.Type == GalVertexAttribType.Snorm)
|
else if (attrib.Type == GalVertexAttribType.Snorm)
|
||||||
{
|
{
|
||||||
switch (Attrib.Size)
|
switch (attrib.Size)
|
||||||
{
|
{
|
||||||
case GalVertexAttribSize._8:
|
case GalVertexAttribSize._8:
|
||||||
case GalVertexAttribSize._8_8:
|
case GalVertexAttribSize._8_8:
|
||||||
case GalVertexAttribSize._8_8_8:
|
case GalVertexAttribSize._8_8_8:
|
||||||
case GalVertexAttribSize._8_8_8_8:
|
case GalVertexAttribSize._8_8_8_8:
|
||||||
GL.VertexAttrib4N((uint)Attrib.Index, (sbyte*)Ptr);
|
GL.VertexAttrib4N((uint)attrib.Index, (sbyte*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._16:
|
case GalVertexAttribSize._16:
|
||||||
case GalVertexAttribSize._16_16:
|
case GalVertexAttribSize._16_16:
|
||||||
case GalVertexAttribSize._16_16_16:
|
case GalVertexAttribSize._16_16_16:
|
||||||
case GalVertexAttribSize._16_16_16_16:
|
case GalVertexAttribSize._16_16_16_16:
|
||||||
GL.VertexAttrib4N((uint)Attrib.Index, (short*)Ptr);
|
GL.VertexAttrib4N((uint)attrib.Index, (short*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._32:
|
case GalVertexAttribSize._32:
|
||||||
case GalVertexAttribSize._32_32:
|
case GalVertexAttribSize._32_32:
|
||||||
case GalVertexAttribSize._32_32_32:
|
case GalVertexAttribSize._32_32_32:
|
||||||
case GalVertexAttribSize._32_32_32_32:
|
case GalVertexAttribSize._32_32_32_32:
|
||||||
GL.VertexAttrib4N((uint)Attrib.Index, (int*)Ptr);
|
GL.VertexAttrib4N((uint)attrib.Index, (int*)ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Attrib.Type == GalVertexAttribType.Uint)
|
else if (attrib.Type == GalVertexAttribType.Uint)
|
||||||
{
|
{
|
||||||
switch (Attrib.Size)
|
switch (attrib.Size)
|
||||||
{
|
{
|
||||||
case GalVertexAttribSize._8:
|
case GalVertexAttribSize._8:
|
||||||
case GalVertexAttribSize._8_8:
|
case GalVertexAttribSize._8_8:
|
||||||
case GalVertexAttribSize._8_8_8:
|
case GalVertexAttribSize._8_8_8:
|
||||||
case GalVertexAttribSize._8_8_8_8:
|
case GalVertexAttribSize._8_8_8_8:
|
||||||
GL.VertexAttribI4((uint)Attrib.Index, Ptr);
|
GL.VertexAttribI4((uint)attrib.Index, ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._16:
|
case GalVertexAttribSize._16:
|
||||||
case GalVertexAttribSize._16_16:
|
case GalVertexAttribSize._16_16:
|
||||||
case GalVertexAttribSize._16_16_16:
|
case GalVertexAttribSize._16_16_16:
|
||||||
case GalVertexAttribSize._16_16_16_16:
|
case GalVertexAttribSize._16_16_16_16:
|
||||||
GL.VertexAttribI4((uint)Attrib.Index, (ushort*)Ptr);
|
GL.VertexAttribI4((uint)attrib.Index, (ushort*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._32:
|
case GalVertexAttribSize._32:
|
||||||
case GalVertexAttribSize._32_32:
|
case GalVertexAttribSize._32_32:
|
||||||
case GalVertexAttribSize._32_32_32:
|
case GalVertexAttribSize._32_32_32:
|
||||||
case GalVertexAttribSize._32_32_32_32:
|
case GalVertexAttribSize._32_32_32_32:
|
||||||
GL.VertexAttribI4((uint)Attrib.Index, (uint*)Ptr);
|
GL.VertexAttribI4((uint)attrib.Index, (uint*)ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Attrib.Type == GalVertexAttribType.Sint)
|
else if (attrib.Type == GalVertexAttribType.Sint)
|
||||||
{
|
{
|
||||||
switch (Attrib.Size)
|
switch (attrib.Size)
|
||||||
{
|
{
|
||||||
case GalVertexAttribSize._8:
|
case GalVertexAttribSize._8:
|
||||||
case GalVertexAttribSize._8_8:
|
case GalVertexAttribSize._8_8:
|
||||||
case GalVertexAttribSize._8_8_8:
|
case GalVertexAttribSize._8_8_8:
|
||||||
case GalVertexAttribSize._8_8_8_8:
|
case GalVertexAttribSize._8_8_8_8:
|
||||||
GL.VertexAttribI4((uint)Attrib.Index, (sbyte*)Ptr);
|
GL.VertexAttribI4((uint)attrib.Index, (sbyte*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._16:
|
case GalVertexAttribSize._16:
|
||||||
case GalVertexAttribSize._16_16:
|
case GalVertexAttribSize._16_16:
|
||||||
case GalVertexAttribSize._16_16_16:
|
case GalVertexAttribSize._16_16_16:
|
||||||
case GalVertexAttribSize._16_16_16_16:
|
case GalVertexAttribSize._16_16_16_16:
|
||||||
GL.VertexAttribI4((uint)Attrib.Index, (short*)Ptr);
|
GL.VertexAttribI4((uint)attrib.Index, (short*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GalVertexAttribSize._32:
|
case GalVertexAttribSize._32:
|
||||||
case GalVertexAttribSize._32_32:
|
case GalVertexAttribSize._32_32:
|
||||||
case GalVertexAttribSize._32_32_32:
|
case GalVertexAttribSize._32_32_32:
|
||||||
case GalVertexAttribSize._32_32_32_32:
|
case GalVertexAttribSize._32_32_32_32:
|
||||||
GL.VertexAttribI4((uint)Attrib.Index, (int*)Ptr);
|
GL.VertexAttribI4((uint)attrib.Index, (int*)ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Attrib.Type == GalVertexAttribType.Float)
|
else if (attrib.Type == GalVertexAttribType.Float)
|
||||||
{
|
{
|
||||||
switch (Attrib.Size)
|
switch (attrib.Size)
|
||||||
{
|
{
|
||||||
case GalVertexAttribSize._32:
|
case GalVertexAttribSize._32:
|
||||||
case GalVertexAttribSize._32_32:
|
case GalVertexAttribSize._32_32:
|
||||||
case GalVertexAttribSize._32_32_32:
|
case GalVertexAttribSize._32_32_32:
|
||||||
case GalVertexAttribSize._32_32_32_32:
|
case GalVertexAttribSize._32_32_32_32:
|
||||||
GL.VertexAttrib4(Attrib.Index, (float*)Ptr);
|
GL.VertexAttrib4(attrib.Index, (float*)ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: ThrowUnsupportedAttrib(Attrib); break;
|
default: ThrowUnsupportedAttrib(attrib); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ThrowUnsupportedAttrib(GalVertexAttrib Attrib)
|
private static void ThrowUnsupportedAttrib(GalVertexAttrib attrib)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Unsupported size \"" + Attrib.Size + "\" on type \"" + Attrib.Type + "\"!");
|
throw new NotImplementedException("Unsupported size \"" + attrib.Size + "\" on type \"" + attrib.Type + "\"!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Enable(EnableCap Cap, bool Enabled)
|
private void Enable(EnableCap cap, bool enabled)
|
||||||
{
|
{
|
||||||
if (Enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
GL.Enable(Cap);
|
GL.Enable(cap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.Disable(Cap);
|
GL.Disable(cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Enable(IndexedEnableCap Cap, int Index, bool Enabled)
|
private void Enable(IndexedEnableCap cap, int index, bool enabled)
|
||||||
{
|
{
|
||||||
if (Enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
GL.Enable(Cap, Index);
|
GL.Enable(cap, index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.Disable(Cap, Index);
|
GL.Disable(cap, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetDepthMask()
|
public void ResetDepthMask()
|
||||||
{
|
{
|
||||||
Old.DepthWriteEnabled = true;
|
_old.DepthWriteEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetColorMask(int Index)
|
public void ResetColorMask(int index)
|
||||||
{
|
{
|
||||||
Old.ColorMasks[Index] = ColorMaskState.Default;
|
_old.ColorMasks[index] = ColorMaskState.Default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,15 +3,15 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLRasterizer : IGalRasterizer
|
class OglRasterizer : IGalRasterizer
|
||||||
{
|
{
|
||||||
private const long MaxVertexBufferCacheSize = 128 * 1024 * 1024;
|
private const long MaxVertexBufferCacheSize = 128 * 1024 * 1024;
|
||||||
private const long MaxIndexBufferCacheSize = 64 * 1024 * 1024;
|
private const long MaxIndexBufferCacheSize = 64 * 1024 * 1024;
|
||||||
|
|
||||||
private int[] VertexBuffers;
|
private int[] _vertexBuffers;
|
||||||
|
|
||||||
private OGLCachedResource<int> VboCache;
|
private OglCachedResource<int> _vboCache;
|
||||||
private OGLCachedResource<int> IboCache;
|
private OglCachedResource<int> _iboCache;
|
||||||
|
|
||||||
private struct IbInfo
|
private struct IbInfo
|
||||||
{
|
{
|
||||||
|
@ -21,187 +21,187 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
public DrawElementsType Type;
|
public DrawElementsType Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IbInfo IndexBuffer;
|
private IbInfo _indexBuffer;
|
||||||
|
|
||||||
public OGLRasterizer()
|
public OglRasterizer()
|
||||||
{
|
{
|
||||||
VertexBuffers = new int[32];
|
_vertexBuffers = new int[32];
|
||||||
|
|
||||||
VboCache = new OGLCachedResource<int>(GL.DeleteBuffer, MaxVertexBufferCacheSize);
|
_vboCache = new OglCachedResource<int>(GL.DeleteBuffer, MaxVertexBufferCacheSize);
|
||||||
IboCache = new OGLCachedResource<int>(GL.DeleteBuffer, MaxIndexBufferCacheSize);
|
_iboCache = new OglCachedResource<int>(GL.DeleteBuffer, MaxIndexBufferCacheSize);
|
||||||
|
|
||||||
IndexBuffer = new IbInfo();
|
_indexBuffer = new IbInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LockCaches()
|
public void LockCaches()
|
||||||
{
|
{
|
||||||
VboCache.Lock();
|
_vboCache.Lock();
|
||||||
IboCache.Lock();
|
_iboCache.Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnlockCaches()
|
public void UnlockCaches()
|
||||||
{
|
{
|
||||||
VboCache.Unlock();
|
_vboCache.Unlock();
|
||||||
IboCache.Unlock();
|
_iboCache.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearBuffers(
|
public void ClearBuffers(
|
||||||
GalClearBufferFlags Flags,
|
GalClearBufferFlags flags,
|
||||||
int Attachment,
|
int attachment,
|
||||||
float Red,
|
float red,
|
||||||
float Green,
|
float green,
|
||||||
float Blue,
|
float blue,
|
||||||
float Alpha,
|
float alpha,
|
||||||
float Depth,
|
float depth,
|
||||||
int Stencil)
|
int stencil)
|
||||||
{
|
{
|
||||||
GL.ColorMask(
|
GL.ColorMask(
|
||||||
Attachment,
|
attachment,
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorRed),
|
flags.HasFlag(GalClearBufferFlags.ColorRed),
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorGreen),
|
flags.HasFlag(GalClearBufferFlags.ColorGreen),
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorBlue),
|
flags.HasFlag(GalClearBufferFlags.ColorBlue),
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorAlpha));
|
flags.HasFlag(GalClearBufferFlags.ColorAlpha));
|
||||||
|
|
||||||
GL.ClearBuffer(ClearBuffer.Color, Attachment, new float[] { Red, Green, Blue, Alpha });
|
GL.ClearBuffer(ClearBuffer.Color, attachment, new float[] { red, green, blue, alpha });
|
||||||
|
|
||||||
GL.ColorMask(Attachment, true, true, true, true);
|
GL.ColorMask(attachment, true, true, true, true);
|
||||||
GL.DepthMask(true);
|
GL.DepthMask(true);
|
||||||
|
|
||||||
if (Flags.HasFlag(GalClearBufferFlags.Depth))
|
if (flags.HasFlag(GalClearBufferFlags.Depth))
|
||||||
{
|
{
|
||||||
GL.ClearBuffer(ClearBuffer.Depth, 0, ref Depth);
|
GL.ClearBuffer(ClearBuffer.Depth, 0, ref depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags.HasFlag(GalClearBufferFlags.Stencil))
|
if (flags.HasFlag(GalClearBufferFlags.Stencil))
|
||||||
{
|
{
|
||||||
GL.ClearBuffer(ClearBuffer.Stencil, 0, ref Stencil);
|
GL.ClearBuffer(ClearBuffer.Stencil, 0, ref stencil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsVboCached(long Key, long DataSize)
|
public bool IsVboCached(long key, long dataSize)
|
||||||
{
|
{
|
||||||
return VboCache.TryGetSize(Key, out long Size) && Size == DataSize;
|
return _vboCache.TryGetSize(key, out long size) && size == dataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsIboCached(long Key, long DataSize)
|
public bool IsIboCached(long key, long dataSize)
|
||||||
{
|
{
|
||||||
return IboCache.TryGetSize(Key, out long Size) && Size == DataSize;
|
return _iboCache.TryGetSize(key, out long size) && size == dataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateVbo(long Key, int DataSize, IntPtr HostAddress)
|
public void CreateVbo(long key, int dataSize, IntPtr hostAddress)
|
||||||
{
|
{
|
||||||
int Handle = GL.GenBuffer();
|
int handle = GL.GenBuffer();
|
||||||
|
|
||||||
VboCache.AddOrUpdate(Key, Handle, DataSize);
|
_vboCache.AddOrUpdate(key, handle, dataSize);
|
||||||
|
|
||||||
IntPtr Length = new IntPtr(DataSize);
|
IntPtr length = new IntPtr(dataSize);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, Handle);
|
GL.BindBuffer(BufferTarget.ArrayBuffer, handle);
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.ArrayBuffer, length, hostAddress, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateVbo(long Key, byte[] Data)
|
public void CreateVbo(long key, byte[] data)
|
||||||
{
|
{
|
||||||
int Handle = GL.GenBuffer();
|
int handle = GL.GenBuffer();
|
||||||
|
|
||||||
VboCache.AddOrUpdate(Key, Handle, Data.Length);
|
_vboCache.AddOrUpdate(key, handle, data.Length);
|
||||||
|
|
||||||
IntPtr Length = new IntPtr(Data.Length);
|
IntPtr length = new IntPtr(data.Length);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, Handle);
|
GL.BindBuffer(BufferTarget.ArrayBuffer, handle);
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, Length, Data, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.ArrayBuffer, length, data, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateIbo(long Key, int DataSize, IntPtr HostAddress)
|
public void CreateIbo(long key, int dataSize, IntPtr hostAddress)
|
||||||
{
|
{
|
||||||
int Handle = GL.GenBuffer();
|
int handle = GL.GenBuffer();
|
||||||
|
|
||||||
IboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
|
_iboCache.AddOrUpdate(key, handle, (uint)dataSize);
|
||||||
|
|
||||||
IntPtr Length = new IntPtr(DataSize);
|
IntPtr length = new IntPtr(dataSize);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, handle);
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.ElementArrayBuffer, length, hostAddress, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateIbo(long Key, int DataSize, byte[] Buffer)
|
public void CreateIbo(long key, int dataSize, byte[] buffer)
|
||||||
{
|
{
|
||||||
int Handle = GL.GenBuffer();
|
int handle = GL.GenBuffer();
|
||||||
|
|
||||||
IboCache.AddOrUpdate(Key, Handle, DataSize);
|
_iboCache.AddOrUpdate(key, handle, dataSize);
|
||||||
|
|
||||||
IntPtr Length = new IntPtr(Buffer.Length);
|
IntPtr length = new IntPtr(buffer.Length);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, handle);
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.ElementArrayBuffer, length, buffer, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetIndexArray(int Size, GalIndexFormat Format)
|
public void SetIndexArray(int size, GalIndexFormat format)
|
||||||
{
|
{
|
||||||
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
|
_indexBuffer.Type = OglEnumConverter.GetDrawElementsType(format);
|
||||||
|
|
||||||
IndexBuffer.Count = Size >> (int)Format;
|
_indexBuffer.Count = size >> (int)format;
|
||||||
|
|
||||||
IndexBuffer.ElemSizeLog2 = (int)Format;
|
_indexBuffer.ElemSizeLog2 = (int)format;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawArrays(int First, int Count, GalPrimitiveType PrimType)
|
public void DrawArrays(int first, int count, GalPrimitiveType primType)
|
||||||
{
|
{
|
||||||
if (Count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrimType == GalPrimitiveType.Quads)
|
if (primType == GalPrimitiveType.Quads)
|
||||||
{
|
{
|
||||||
for (int Offset = 0; Offset < Count; Offset += 4)
|
for (int offset = 0; offset < count; offset += 4)
|
||||||
{
|
{
|
||||||
GL.DrawArrays(PrimitiveType.TriangleFan, First + Offset, 4);
|
GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (PrimType == GalPrimitiveType.QuadStrip)
|
else if (primType == GalPrimitiveType.QuadStrip)
|
||||||
{
|
{
|
||||||
GL.DrawArrays(PrimitiveType.TriangleFan, First, 4);
|
GL.DrawArrays(PrimitiveType.TriangleFan, first, 4);
|
||||||
|
|
||||||
for (int Offset = 2; Offset < Count; Offset += 2)
|
for (int offset = 2; offset < count; offset += 2)
|
||||||
{
|
{
|
||||||
GL.DrawArrays(PrimitiveType.TriangleFan, First + Offset, 4);
|
GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count);
|
GL.DrawArrays(OglEnumConverter.GetPrimitiveType(primType), first, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType)
|
public void DrawElements(long iboKey, int first, int vertexBase, GalPrimitiveType primType)
|
||||||
{
|
{
|
||||||
if (!IboCache.TryGetValue(IboKey, out int IboHandle))
|
if (!_iboCache.TryGetValue(iboKey, out int iboHandle))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
|
PrimitiveType mode = OglEnumConverter.GetPrimitiveType(primType);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboHandle);
|
||||||
|
|
||||||
First <<= IndexBuffer.ElemSizeLog2;
|
first <<= _indexBuffer.ElemSizeLog2;
|
||||||
|
|
||||||
if (VertexBase != 0)
|
if (vertexBase != 0)
|
||||||
{
|
{
|
||||||
IntPtr Indices = new IntPtr(First);
|
IntPtr indices = new IntPtr(first);
|
||||||
|
|
||||||
GL.DrawElementsBaseVertex(Mode, IndexBuffer.Count, IndexBuffer.Type, Indices, VertexBase);
|
GL.DrawElementsBaseVertex(mode, _indexBuffer.Count, _indexBuffer.Type, indices, vertexBase);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
|
GL.DrawElements(mode, _indexBuffer.Count, _indexBuffer.Type, first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetVbo(long VboKey, out int VboHandle)
|
public bool TryGetVbo(long vboKey, out int vboHandle)
|
||||||
{
|
{
|
||||||
return VboCache.TryGetValue(VboKey, out VboHandle);
|
return _vboCache.TryGetValue(vboKey, out vboHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLRenderTarget : IGalRenderTarget
|
class OglRenderTarget : IGalRenderTarget
|
||||||
{
|
{
|
||||||
private const int NativeWidth = 1280;
|
private const int NativeWidth = 1280;
|
||||||
private const int NativeHeight = 720;
|
private const int NativeHeight = 720;
|
||||||
|
@ -18,12 +18,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
public int Width { get; private set; }
|
public int Width { get; private set; }
|
||||||
public int Height { get; private set; }
|
public int Height { get; private set; }
|
||||||
|
|
||||||
public Rect(int X, int Y, int Width, int Height)
|
public Rect(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
this.X = X;
|
X = x;
|
||||||
this.Y = Y;
|
Y = y;
|
||||||
this.Width = Width;
|
Width = width;
|
||||||
this.Height = Height;
|
Height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,141 +44,141 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Map = new DrawBuffersEnum[RenderTargetsCount];
|
Map = new DrawBuffersEnum[RenderTargetsCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(FrameBufferAttachments Source)
|
public void Update(FrameBufferAttachments source)
|
||||||
{
|
{
|
||||||
for (int Index = 0; Index < RenderTargetsCount; Index++)
|
for (int index = 0; index < RenderTargetsCount; index++)
|
||||||
{
|
{
|
||||||
Map[Index] = Source.Map[Index];
|
Map[index] = source.Map[index];
|
||||||
|
|
||||||
Colors[Index] = Source.Colors[Index];
|
Colors[index] = source.Colors[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
MapCount = Source.MapCount;
|
MapCount = source.MapCount;
|
||||||
Zeta = Source.Zeta;
|
Zeta = source.Zeta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] ColorHandles;
|
private int[] _colorHandles;
|
||||||
private int ZetaHandle;
|
private int _zetaHandle;
|
||||||
|
|
||||||
private OGLTexture Texture;
|
private OglTexture _texture;
|
||||||
|
|
||||||
private ImageHandler ReadTex;
|
private ImageHandler _readTex;
|
||||||
|
|
||||||
private Rect Window;
|
private Rect _window;
|
||||||
|
|
||||||
private float[] Viewports;
|
private float[] _viewports;
|
||||||
|
|
||||||
private bool FlipX;
|
private bool _flipX;
|
||||||
private bool FlipY;
|
private bool _flipY;
|
||||||
|
|
||||||
private int CropTop;
|
private int _cropTop;
|
||||||
private int CropLeft;
|
private int _cropLeft;
|
||||||
private int CropRight;
|
private int _cropRight;
|
||||||
private int CropBottom;
|
private int _cropBottom;
|
||||||
|
|
||||||
//This framebuffer is used to attach guest rendertargets,
|
//This framebuffer is used to attach guest rendertargets,
|
||||||
//think of it as a dummy OpenGL VAO
|
//think of it as a dummy OpenGL VAO
|
||||||
private int DummyFrameBuffer;
|
private int _dummyFrameBuffer;
|
||||||
|
|
||||||
//These framebuffers are used to blit images
|
//These framebuffers are used to blit images
|
||||||
private int SrcFb;
|
private int _srcFb;
|
||||||
private int DstFb;
|
private int _dstFb;
|
||||||
|
|
||||||
private FrameBufferAttachments Attachments;
|
private FrameBufferAttachments _attachments;
|
||||||
private FrameBufferAttachments OldAttachments;
|
private FrameBufferAttachments _oldAttachments;
|
||||||
|
|
||||||
private int CopyPBO;
|
private int _copyPbo;
|
||||||
|
|
||||||
public bool FramebufferSrgb { get; set; }
|
public bool FramebufferSrgb { get; set; }
|
||||||
|
|
||||||
public OGLRenderTarget(OGLTexture Texture)
|
public OglRenderTarget(OglTexture texture)
|
||||||
{
|
{
|
||||||
Attachments = new FrameBufferAttachments();
|
_attachments = new FrameBufferAttachments();
|
||||||
|
|
||||||
OldAttachments = new FrameBufferAttachments();
|
_oldAttachments = new FrameBufferAttachments();
|
||||||
|
|
||||||
ColorHandles = new int[RenderTargetsCount];
|
_colorHandles = new int[RenderTargetsCount];
|
||||||
|
|
||||||
Viewports = new float[RenderTargetsCount * 4];
|
_viewports = new float[RenderTargetsCount * 4];
|
||||||
|
|
||||||
this.Texture = Texture;
|
_texture = texture;
|
||||||
|
|
||||||
Texture.TextureDeleted += TextureDeletionHandler;
|
texture.TextureDeleted += TextureDeletionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TextureDeletionHandler(object Sender, int Handle)
|
private void TextureDeletionHandler(object sender, int handle)
|
||||||
{
|
{
|
||||||
//Texture was deleted, the handle is no longer valid, so
|
//Texture was deleted, the handle is no longer valid, so
|
||||||
//reset all uses of this handle on a render target.
|
//reset all uses of this handle on a render target.
|
||||||
for (int Attachment = 0; Attachment < RenderTargetsCount; Attachment++)
|
for (int attachment = 0; attachment < RenderTargetsCount; attachment++)
|
||||||
{
|
{
|
||||||
if (ColorHandles[Attachment] == Handle)
|
if (_colorHandles[attachment] == handle)
|
||||||
{
|
{
|
||||||
ColorHandles[Attachment] = 0;
|
_colorHandles[attachment] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ZetaHandle == Handle)
|
if (_zetaHandle == handle)
|
||||||
{
|
{
|
||||||
ZetaHandle = 0;
|
_zetaHandle = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind()
|
public void Bind()
|
||||||
{
|
{
|
||||||
if (DummyFrameBuffer == 0)
|
if (_dummyFrameBuffer == 0)
|
||||||
{
|
{
|
||||||
DummyFrameBuffer = GL.GenFramebuffer();
|
_dummyFrameBuffer = GL.GenFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _dummyFrameBuffer);
|
||||||
|
|
||||||
ImageHandler CachedImage;
|
ImageHandler cachedImage;
|
||||||
|
|
||||||
for (int Attachment = 0; Attachment < RenderTargetsCount; Attachment++)
|
for (int attachment = 0; attachment < RenderTargetsCount; attachment++)
|
||||||
{
|
{
|
||||||
long Key = Attachments.Colors[Attachment];
|
long key = _attachments.Colors[attachment];
|
||||||
|
|
||||||
int Handle = 0;
|
int handle = 0;
|
||||||
|
|
||||||
if (Key != 0 && Texture.TryGetImageHandler(Key, out CachedImage))
|
if (key != 0 && _texture.TryGetImageHandler(key, out cachedImage))
|
||||||
{
|
{
|
||||||
Handle = CachedImage.Handle;
|
handle = cachedImage.Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Handle == ColorHandles[Attachment])
|
if (handle == _colorHandles[attachment])
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.ColorAttachment0 + Attachment,
|
FramebufferAttachment.ColorAttachment0 + attachment,
|
||||||
Handle,
|
handle,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
ColorHandles[Attachment] = Handle;
|
_colorHandles[attachment] = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Attachments.Zeta != 0 && Texture.TryGetImageHandler(Attachments.Zeta, out CachedImage))
|
if (_attachments.Zeta != 0 && _texture.TryGetImageHandler(_attachments.Zeta, out cachedImage))
|
||||||
{
|
{
|
||||||
if (CachedImage.Handle != ZetaHandle)
|
if (cachedImage.Handle != _zetaHandle)
|
||||||
{
|
{
|
||||||
if (CachedImage.HasDepth && CachedImage.HasStencil)
|
if (cachedImage.HasDepth && cachedImage.HasStencil)
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.DepthStencilAttachment,
|
FramebufferAttachment.DepthStencilAttachment,
|
||||||
CachedImage.Handle,
|
cachedImage.Handle,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
else if (CachedImage.HasDepth)
|
else if (cachedImage.HasDepth)
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.DepthAttachment,
|
FramebufferAttachment.DepthAttachment,
|
||||||
CachedImage.Handle,
|
cachedImage.Handle,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
|
@ -189,13 +189,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid image format \"" + CachedImage.Format + "\" used as Zeta!");
|
throw new InvalidOperationException("Invalid image format \"" + cachedImage.Format + "\" used as Zeta!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ZetaHandle = CachedImage.Handle;
|
_zetaHandle = cachedImage.Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ZetaHandle != 0)
|
else if (_zetaHandle != 0)
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
|
@ -203,163 +203,163 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
ZetaHandle = 0;
|
_zetaHandle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OGLExtension.ViewportArray)
|
if (OglExtension.ViewportArray)
|
||||||
{
|
{
|
||||||
GL.ViewportArray(0, RenderTargetsCount, Viewports);
|
GL.ViewportArray(0, RenderTargetsCount, _viewports);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.Viewport(
|
GL.Viewport(
|
||||||
(int)Viewports[0],
|
(int)_viewports[0],
|
||||||
(int)Viewports[1],
|
(int)_viewports[1],
|
||||||
(int)Viewports[2],
|
(int)_viewports[2],
|
||||||
(int)Viewports[3]);
|
(int)_viewports[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Attachments.MapCount > 1)
|
if (_attachments.MapCount > 1)
|
||||||
{
|
{
|
||||||
GL.DrawBuffers(Attachments.MapCount, Attachments.Map);
|
GL.DrawBuffers(_attachments.MapCount, _attachments.Map);
|
||||||
}
|
}
|
||||||
else if (Attachments.MapCount == 1)
|
else if (_attachments.MapCount == 1)
|
||||||
{
|
{
|
||||||
GL.DrawBuffer((DrawBufferMode)Attachments.Map[0]);
|
GL.DrawBuffer((DrawBufferMode)_attachments.Map[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.DrawBuffer(DrawBufferMode.None);
|
GL.DrawBuffer(DrawBufferMode.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
OldAttachments.Update(Attachments);
|
_oldAttachments.Update(_attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindColor(long Key, int Attachment)
|
public void BindColor(long key, int attachment)
|
||||||
{
|
{
|
||||||
Attachments.Colors[Attachment] = Key;
|
_attachments.Colors[attachment] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnbindColor(int Attachment)
|
public void UnbindColor(int attachment)
|
||||||
{
|
{
|
||||||
Attachments.Colors[Attachment] = 0;
|
_attachments.Colors[attachment] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindZeta(long Key)
|
public void BindZeta(long key)
|
||||||
{
|
{
|
||||||
Attachments.Zeta = Key;
|
_attachments.Zeta = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnbindZeta()
|
public void UnbindZeta()
|
||||||
{
|
{
|
||||||
Attachments.Zeta = 0;
|
_attachments.Zeta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Present(long Key)
|
public void Present(long key)
|
||||||
{
|
{
|
||||||
Texture.TryGetImageHandler(Key, out ReadTex);
|
_texture.TryGetImageHandler(key, out _readTex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetMap(int[] Map)
|
public void SetMap(int[] map)
|
||||||
{
|
{
|
||||||
if (Map != null)
|
if (map != null)
|
||||||
{
|
{
|
||||||
Attachments.MapCount = Map.Length;
|
_attachments.MapCount = map.Length;
|
||||||
|
|
||||||
for (int Attachment = 0; Attachment < Attachments.MapCount; Attachment++)
|
for (int attachment = 0; attachment < _attachments.MapCount; attachment++)
|
||||||
{
|
{
|
||||||
Attachments.Map[Attachment] = DrawBuffersEnum.ColorAttachment0 + Map[Attachment];
|
_attachments.Map[attachment] = DrawBuffersEnum.ColorAttachment0 + map[attachment];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Attachments.MapCount = 0;
|
_attachments.MapCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom)
|
public void SetTransform(bool flipX, bool flipY, int top, int left, int right, int bottom)
|
||||||
{
|
{
|
||||||
this.FlipX = FlipX;
|
_flipX = flipX;
|
||||||
this.FlipY = FlipY;
|
_flipY = flipY;
|
||||||
|
|
||||||
CropTop = Top;
|
_cropTop = top;
|
||||||
CropLeft = Left;
|
_cropLeft = left;
|
||||||
CropRight = Right;
|
_cropRight = right;
|
||||||
CropBottom = Bottom;
|
_cropBottom = bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWindowSize(int Width, int Height)
|
public void SetWindowSize(int width, int height)
|
||||||
{
|
{
|
||||||
Window = new Rect(0, 0, Width, Height);
|
_window = new Rect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetViewport(int Attachment, int X, int Y, int Width, int Height)
|
public void SetViewport(int attachment, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int Offset = Attachment * 4;
|
int offset = attachment * 4;
|
||||||
|
|
||||||
Viewports[Offset + 0] = X;
|
_viewports[offset + 0] = x;
|
||||||
Viewports[Offset + 1] = Y;
|
_viewports[offset + 1] = y;
|
||||||
Viewports[Offset + 2] = Width;
|
_viewports[offset + 2] = width;
|
||||||
Viewports[Offset + 3] = Height;
|
_viewports[offset + 3] = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
{
|
{
|
||||||
if (ReadTex == null)
|
if (_readTex == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrcX0, SrcX1, SrcY0, SrcY1;
|
int srcX0, srcX1, srcY0, srcY1;
|
||||||
|
|
||||||
if (CropLeft == 0 && CropRight == 0)
|
if (_cropLeft == 0 && _cropRight == 0)
|
||||||
{
|
{
|
||||||
SrcX0 = 0;
|
srcX0 = 0;
|
||||||
SrcX1 = ReadTex.Width;
|
srcX1 = _readTex.Width;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SrcX0 = CropLeft;
|
srcX0 = _cropLeft;
|
||||||
SrcX1 = CropRight;
|
srcX1 = _cropRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CropTop == 0 && CropBottom == 0)
|
if (_cropTop == 0 && _cropBottom == 0)
|
||||||
{
|
{
|
||||||
SrcY0 = 0;
|
srcY0 = 0;
|
||||||
SrcY1 = ReadTex.Height;
|
srcY1 = _readTex.Height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SrcY0 = CropTop;
|
srcY0 = _cropTop;
|
||||||
SrcY1 = CropBottom;
|
srcY1 = _cropBottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
float RatioX = MathF.Min(1f, (Window.Height * (float)NativeWidth) / ((float)NativeHeight * Window.Width));
|
float ratioX = MathF.Min(1f, (_window.Height * (float)NativeWidth) / ((float)NativeHeight * _window.Width));
|
||||||
float RatioY = MathF.Min(1f, (Window.Width * (float)NativeHeight) / ((float)NativeWidth * Window.Height));
|
float ratioY = MathF.Min(1f, (_window.Width * (float)NativeHeight) / ((float)NativeWidth * _window.Height));
|
||||||
|
|
||||||
int DstWidth = (int)(Window.Width * RatioX);
|
int dstWidth = (int)(_window.Width * ratioX);
|
||||||
int DstHeight = (int)(Window.Height * RatioY);
|
int dstHeight = (int)(_window.Height * ratioY);
|
||||||
|
|
||||||
int DstPaddingX = (Window.Width - DstWidth) / 2;
|
int dstPaddingX = (_window.Width - dstWidth) / 2;
|
||||||
int DstPaddingY = (Window.Height - DstHeight) / 2;
|
int dstPaddingY = (_window.Height - dstHeight) / 2;
|
||||||
|
|
||||||
int DstX0 = FlipX ? Window.Width - DstPaddingX : DstPaddingX;
|
int dstX0 = _flipX ? _window.Width - dstPaddingX : dstPaddingX;
|
||||||
int DstX1 = FlipX ? DstPaddingX : Window.Width - DstPaddingX;
|
int dstX1 = _flipX ? dstPaddingX : _window.Width - dstPaddingX;
|
||||||
|
|
||||||
int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
|
int dstY0 = _flipY ? dstPaddingY : _window.Height - dstPaddingY;
|
||||||
int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
|
int dstY1 = _flipY ? _window.Height - dstPaddingY : dstPaddingY;
|
||||||
|
|
||||||
GL.Viewport(0, 0, Window.Width, Window.Height);
|
GL.Viewport(0, 0, _window.Width, _window.Height);
|
||||||
|
|
||||||
if (SrcFb == 0)
|
if (_srcFb == 0)
|
||||||
{
|
{
|
||||||
SrcFb = GL.GenFramebuffer();
|
_srcFb = GL.GenFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _srcFb);
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
|
||||||
|
|
||||||
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0);
|
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, _readTex.Handle, 0);
|
||||||
|
|
||||||
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
||||||
|
|
||||||
|
@ -371,14 +371,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.Disable(EnableCap.ScissorTest);
|
GL.Disable(EnableCap.ScissorTest);
|
||||||
|
|
||||||
GL.BlitFramebuffer(
|
GL.BlitFramebuffer(
|
||||||
SrcX0,
|
srcX0,
|
||||||
SrcY0,
|
srcY0,
|
||||||
SrcX1,
|
srcX1,
|
||||||
SrcY1,
|
srcY1,
|
||||||
DstX0,
|
dstX0,
|
||||||
DstY0,
|
dstY0,
|
||||||
DstX1,
|
dstX1,
|
||||||
DstY1,
|
dstY1,
|
||||||
ClearBufferMask.ColorBufferBit,
|
ClearBufferMask.ColorBufferBit,
|
||||||
BlitFramebufferFilter.Linear);
|
BlitFramebufferFilter.Linear);
|
||||||
|
|
||||||
|
@ -389,150 +389,150 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Copy(
|
public void Copy(
|
||||||
GalImage SrcImage,
|
GalImage srcImage,
|
||||||
GalImage DstImage,
|
GalImage dstImage,
|
||||||
long SrcKey,
|
long srcKey,
|
||||||
long DstKey,
|
long dstKey,
|
||||||
int SrcLayer,
|
int srcLayer,
|
||||||
int DstLayer,
|
int dstLayer,
|
||||||
int SrcX0,
|
int srcX0,
|
||||||
int SrcY0,
|
int srcY0,
|
||||||
int SrcX1,
|
int srcX1,
|
||||||
int SrcY1,
|
int srcY1,
|
||||||
int DstX0,
|
int dstX0,
|
||||||
int DstY0,
|
int dstY0,
|
||||||
int DstX1,
|
int dstX1,
|
||||||
int DstY1)
|
int dstY1)
|
||||||
{
|
{
|
||||||
if (Texture.TryGetImageHandler(SrcKey, out ImageHandler SrcTex) &&
|
if (_texture.TryGetImageHandler(srcKey, out ImageHandler srcTex) &&
|
||||||
Texture.TryGetImageHandler(DstKey, out ImageHandler DstTex))
|
_texture.TryGetImageHandler(dstKey, out ImageHandler dstTex))
|
||||||
{
|
{
|
||||||
if (SrcTex.HasColor != DstTex.HasColor ||
|
if (srcTex.HasColor != dstTex.HasColor ||
|
||||||
SrcTex.HasDepth != DstTex.HasDepth ||
|
srcTex.HasDepth != dstTex.HasDepth ||
|
||||||
SrcTex.HasStencil != DstTex.HasStencil)
|
srcTex.HasStencil != dstTex.HasStencil)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SrcFb == 0)
|
if (_srcFb == 0)
|
||||||
{
|
{
|
||||||
SrcFb = GL.GenFramebuffer();
|
_srcFb = GL.GenFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DstFb == 0)
|
if (_dstFb == 0)
|
||||||
{
|
{
|
||||||
DstFb = GL.GenFramebuffer();
|
_dstFb = GL.GenFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _srcFb);
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _dstFb);
|
||||||
|
|
||||||
FramebufferAttachment Attachment = GetAttachment(SrcTex);
|
FramebufferAttachment attachment = GetAttachment(srcTex);
|
||||||
|
|
||||||
if (ImageUtils.IsArray(SrcImage.TextureTarget) && SrcLayer > 0)
|
if (ImageUtils.IsArray(srcImage.TextureTarget) && srcLayer > 0)
|
||||||
{
|
{
|
||||||
GL.FramebufferTextureLayer(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0, SrcLayer);
|
GL.FramebufferTextureLayer(FramebufferTarget.ReadFramebuffer, attachment, srcTex.Handle, 0, srcLayer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0);
|
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, attachment, srcTex.Handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImageUtils.IsArray(DstImage.TextureTarget) && DstLayer > 0)
|
if (ImageUtils.IsArray(dstImage.TextureTarget) && dstLayer > 0)
|
||||||
{
|
{
|
||||||
GL.FramebufferTextureLayer(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0, DstLayer);
|
GL.FramebufferTextureLayer(FramebufferTarget.DrawFramebuffer, attachment, dstTex.Handle, 0, dstLayer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0);
|
GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, attachment, dstTex.Handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BlitFramebufferFilter Filter = BlitFramebufferFilter.Nearest;
|
BlitFramebufferFilter filter = BlitFramebufferFilter.Nearest;
|
||||||
|
|
||||||
if (SrcTex.HasColor)
|
if (srcTex.HasColor)
|
||||||
{
|
{
|
||||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
||||||
|
|
||||||
Filter = BlitFramebufferFilter.Linear;
|
filter = BlitFramebufferFilter.Linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearBufferMask Mask = GetClearMask(SrcTex);
|
ClearBufferMask mask = GetClearMask(srcTex);
|
||||||
|
|
||||||
GL.BlitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter);
|
GL.BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reinterpret(long Key, GalImage NewImage)
|
public void Reinterpret(long key, GalImage newImage)
|
||||||
{
|
{
|
||||||
if (!Texture.TryGetImage(Key, out GalImage OldImage))
|
if (!_texture.TryGetImage(key, out GalImage oldImage))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewImage.Format == OldImage.Format &&
|
if (newImage.Format == oldImage.Format &&
|
||||||
NewImage.Width == OldImage.Width &&
|
newImage.Width == oldImage.Width &&
|
||||||
NewImage.Height == OldImage.Height &&
|
newImage.Height == oldImage.Height &&
|
||||||
NewImage.Depth == OldImage.Depth &&
|
newImage.Depth == oldImage.Depth &&
|
||||||
NewImage.LayerCount == OldImage.LayerCount &&
|
newImage.LayerCount == oldImage.LayerCount &&
|
||||||
NewImage.TextureTarget == OldImage.TextureTarget)
|
newImage.TextureTarget == oldImage.TextureTarget)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CopyPBO == 0)
|
if (_copyPbo == 0)
|
||||||
{
|
{
|
||||||
CopyPBO = GL.GenBuffer();
|
_copyPbo = GL.GenBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyPBO);
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo);
|
||||||
|
|
||||||
//The buffer should be large enough to hold the largest texture.
|
//The buffer should be large enough to hold the largest texture.
|
||||||
int BufferSize = Math.Max(ImageUtils.GetSize(OldImage),
|
int bufferSize = Math.Max(ImageUtils.GetSize(oldImage),
|
||||||
ImageUtils.GetSize(NewImage));
|
ImageUtils.GetSize(newImage));
|
||||||
|
|
||||||
GL.BufferData(BufferTarget.PixelPackBuffer, BufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
|
GL.BufferData(BufferTarget.PixelPackBuffer, bufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
|
||||||
|
|
||||||
if (!Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
|
if (!_texture.TryGetImageHandler(key, out ImageHandler cachedImage))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);
|
(_, PixelFormat format, PixelType type) = OglEnumConverter.GetImageFormat(cachedImage.Format);
|
||||||
|
|
||||||
TextureTarget Target = ImageUtils.GetTextureTarget(NewImage.TextureTarget);
|
TextureTarget target = ImageUtils.GetTextureTarget(newImage.TextureTarget);
|
||||||
|
|
||||||
GL.BindTexture(Target, CachedImage.Handle);
|
GL.BindTexture(target, cachedImage.Handle);
|
||||||
|
|
||||||
GL.GetTexImage(Target, 0, Format, Type, IntPtr.Zero);
|
GL.GetTexImage(target, 0, format, type, IntPtr.Zero);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
||||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPbo);
|
||||||
|
|
||||||
GL.PixelStore(PixelStoreParameter.UnpackRowLength, OldImage.Width);
|
GL.PixelStore(PixelStoreParameter.UnpackRowLength, oldImage.Width);
|
||||||
|
|
||||||
Texture.Create(Key, ImageUtils.GetSize(NewImage), NewImage);
|
_texture.Create(key, ImageUtils.GetSize(newImage), newImage);
|
||||||
|
|
||||||
GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
|
GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FramebufferAttachment GetAttachment(ImageHandler CachedImage)
|
private static FramebufferAttachment GetAttachment(ImageHandler cachedImage)
|
||||||
{
|
{
|
||||||
if (CachedImage.HasColor)
|
if (cachedImage.HasColor)
|
||||||
{
|
{
|
||||||
return FramebufferAttachment.ColorAttachment0;
|
return FramebufferAttachment.ColorAttachment0;
|
||||||
}
|
}
|
||||||
else if (CachedImage.HasDepth && CachedImage.HasStencil)
|
else if (cachedImage.HasDepth && cachedImage.HasStencil)
|
||||||
{
|
{
|
||||||
return FramebufferAttachment.DepthStencilAttachment;
|
return FramebufferAttachment.DepthStencilAttachment;
|
||||||
}
|
}
|
||||||
else if (CachedImage.HasDepth)
|
else if (cachedImage.HasDepth)
|
||||||
{
|
{
|
||||||
return FramebufferAttachment.DepthAttachment;
|
return FramebufferAttachment.DepthAttachment;
|
||||||
}
|
}
|
||||||
else if (CachedImage.HasStencil)
|
else if (cachedImage.HasStencil)
|
||||||
{
|
{
|
||||||
return FramebufferAttachment.StencilAttachment;
|
return FramebufferAttachment.StencilAttachment;
|
||||||
}
|
}
|
||||||
|
@ -542,11 +542,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClearBufferMask GetClearMask(ImageHandler CachedImage)
|
private static ClearBufferMask GetClearMask(ImageHandler cachedImage)
|
||||||
{
|
{
|
||||||
return (CachedImage.HasColor ? ClearBufferMask.ColorBufferBit : 0) |
|
return (cachedImage.HasColor ? ClearBufferMask.ColorBufferBit : 0) |
|
||||||
(CachedImage.HasDepth ? ClearBufferMask.DepthBufferBit : 0) |
|
(cachedImage.HasDepth ? ClearBufferMask.DepthBufferBit : 0) |
|
||||||
(CachedImage.HasStencil ? ClearBufferMask.StencilBufferBit : 0);
|
(cachedImage.HasStencil ? ClearBufferMask.StencilBufferBit : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
public class OGLRenderer : IGalRenderer
|
public class OglRenderer : IGalRenderer
|
||||||
{
|
{
|
||||||
public IGalConstBuffer Buffer { get; private set; }
|
public IGalConstBuffer Buffer { get; private set; }
|
||||||
|
|
||||||
|
@ -17,41 +17,41 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public IGalTexture Texture { get; private set; }
|
public IGalTexture Texture { get; private set; }
|
||||||
|
|
||||||
private ConcurrentQueue<Action> ActionsQueue;
|
private ConcurrentQueue<Action> _actionsQueue;
|
||||||
|
|
||||||
public OGLRenderer()
|
public OglRenderer()
|
||||||
{
|
{
|
||||||
Buffer = new OGLConstBuffer();
|
Buffer = new OglConstBuffer();
|
||||||
|
|
||||||
Texture = new OGLTexture();
|
Texture = new OglTexture();
|
||||||
|
|
||||||
RenderTarget = new OGLRenderTarget(Texture as OGLTexture);
|
RenderTarget = new OglRenderTarget(Texture as OglTexture);
|
||||||
|
|
||||||
Rasterizer = new OGLRasterizer();
|
Rasterizer = new OglRasterizer();
|
||||||
|
|
||||||
Shader = new OGLShader(Buffer as OGLConstBuffer);
|
Shader = new OglShader(Buffer as OglConstBuffer);
|
||||||
|
|
||||||
Pipeline = new OGLPipeline(
|
Pipeline = new OglPipeline(
|
||||||
Buffer as OGLConstBuffer,
|
Buffer as OglConstBuffer,
|
||||||
RenderTarget as OGLRenderTarget,
|
RenderTarget as OglRenderTarget,
|
||||||
Rasterizer as OGLRasterizer,
|
Rasterizer as OglRasterizer,
|
||||||
Shader as OGLShader);
|
Shader as OglShader);
|
||||||
|
|
||||||
ActionsQueue = new ConcurrentQueue<Action>();
|
_actionsQueue = new ConcurrentQueue<Action>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueAction(Action ActionMthd)
|
public void QueueAction(Action actionMthd)
|
||||||
{
|
{
|
||||||
ActionsQueue.Enqueue(ActionMthd);
|
_actionsQueue.Enqueue(actionMthd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RunActions()
|
public void RunActions()
|
||||||
{
|
{
|
||||||
int Count = ActionsQueue.Count;
|
int count = _actionsQueue.Count;
|
||||||
|
|
||||||
while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction))
|
while (count-- > 0 && _actionsQueue.TryDequeue(out Action renderAction))
|
||||||
{
|
{
|
||||||
RenderAction();
|
renderAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,152 +7,152 @@ using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLShader : IGalShader
|
class OglShader : IGalShader
|
||||||
{
|
{
|
||||||
public const int ReservedCbufCount = 1;
|
public const int ReservedCbufCount = 1;
|
||||||
|
|
||||||
private const int ExtraDataSize = 4;
|
private const int ExtraDataSize = 4;
|
||||||
|
|
||||||
public OGLShaderProgram Current;
|
public OglShaderProgram Current;
|
||||||
|
|
||||||
private ConcurrentDictionary<long, OGLShaderStage> Stages;
|
private ConcurrentDictionary<long, OglShaderStage> _stages;
|
||||||
|
|
||||||
private Dictionary<OGLShaderProgram, int> Programs;
|
private Dictionary<OglShaderProgram, int> _programs;
|
||||||
|
|
||||||
public int CurrentProgramHandle { get; private set; }
|
public int CurrentProgramHandle { get; private set; }
|
||||||
|
|
||||||
private OGLConstBuffer Buffer;
|
private OglConstBuffer _buffer;
|
||||||
|
|
||||||
private int ExtraUboHandle;
|
private int _extraUboHandle;
|
||||||
|
|
||||||
public OGLShader(OGLConstBuffer Buffer)
|
public OglShader(OglConstBuffer buffer)
|
||||||
{
|
{
|
||||||
this.Buffer = Buffer;
|
_buffer = buffer;
|
||||||
|
|
||||||
Stages = new ConcurrentDictionary<long, OGLShaderStage>();
|
_stages = new ConcurrentDictionary<long, OglShaderStage>();
|
||||||
|
|
||||||
Programs = new Dictionary<OGLShaderProgram, int>();
|
_programs = new Dictionary<OglShaderProgram, int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(IGalMemory Memory, long Key, GalShaderType Type)
|
public void Create(IGalMemory memory, long key, GalShaderType type)
|
||||||
{
|
{
|
||||||
Stages.GetOrAdd(Key, (Stage) => ShaderStageFactory(Memory, Key, 0, false, Type));
|
_stages.GetOrAdd(key, (stage) => ShaderStageFactory(memory, key, 0, false, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(IGalMemory Memory, long VpAPos, long Key, GalShaderType Type)
|
public void Create(IGalMemory memory, long vpAPos, long key, GalShaderType type)
|
||||||
{
|
{
|
||||||
Stages.GetOrAdd(Key, (Stage) => ShaderStageFactory(Memory, VpAPos, Key, true, Type));
|
_stages.GetOrAdd(key, (stage) => ShaderStageFactory(memory, vpAPos, key, true, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private OGLShaderStage ShaderStageFactory(
|
private OglShaderStage ShaderStageFactory(
|
||||||
IGalMemory Memory,
|
IGalMemory memory,
|
||||||
long Position,
|
long position,
|
||||||
long PositionB,
|
long positionB,
|
||||||
bool IsDualVp,
|
bool isDualVp,
|
||||||
GalShaderType Type)
|
GalShaderType type)
|
||||||
{
|
{
|
||||||
GlslProgram Program;
|
GlslProgram program;
|
||||||
|
|
||||||
GlslDecompiler Decompiler = new GlslDecompiler(OGLLimit.MaxUboSize, OGLExtension.NvidiaDriver);
|
GlslDecompiler decompiler = new GlslDecompiler(OglLimit.MaxUboSize, OglExtension.NvidiaDriver);
|
||||||
|
|
||||||
int ShaderDumpIndex = ShaderDumper.DumpIndex;
|
int shaderDumpIndex = ShaderDumper.DumpIndex;
|
||||||
|
|
||||||
if (IsDualVp)
|
if (isDualVp)
|
||||||
{
|
{
|
||||||
ShaderDumper.Dump(Memory, Position, Type, "a");
|
ShaderDumper.Dump(memory, position, type, "a");
|
||||||
ShaderDumper.Dump(Memory, PositionB, Type, "b");
|
ShaderDumper.Dump(memory, positionB, type, "b");
|
||||||
|
|
||||||
Program = Decompiler.Decompile(Memory, Position, PositionB, Type);
|
program = decompiler.Decompile(memory, position, positionB, type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ShaderDumper.Dump(Memory, Position, Type);
|
ShaderDumper.Dump(memory, position, type);
|
||||||
|
|
||||||
Program = Decompiler.Decompile(Memory, Position, Type);
|
program = decompiler.Decompile(memory, position, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
string Code = Program.Code;
|
string code = program.Code;
|
||||||
|
|
||||||
if (ShaderDumper.IsDumpEnabled())
|
if (ShaderDumper.IsDumpEnabled())
|
||||||
{
|
{
|
||||||
Code = "//Shader " + ShaderDumpIndex + Environment.NewLine + Code;
|
code = "//Shader " + shaderDumpIndex + Environment.NewLine + code;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OGLShaderStage(Type, Code, Program.Uniforms, Program.Textures);
|
return new OglShaderStage(type, code, program.Uniforms, program.Textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ShaderDeclInfo> GetConstBufferUsage(long Key)
|
public IEnumerable<ShaderDeclInfo> GetConstBufferUsage(long key)
|
||||||
{
|
{
|
||||||
if (Stages.TryGetValue(Key, out OGLShaderStage Stage))
|
if (_stages.TryGetValue(key, out OglShaderStage stage))
|
||||||
{
|
{
|
||||||
return Stage.ConstBufferUsage;
|
return stage.ConstBufferUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Enumerable.Empty<ShaderDeclInfo>();
|
return Enumerable.Empty<ShaderDeclInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Key)
|
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long key)
|
||||||
{
|
{
|
||||||
if (Stages.TryGetValue(Key, out OGLShaderStage Stage))
|
if (_stages.TryGetValue(key, out OglShaderStage stage))
|
||||||
{
|
{
|
||||||
return Stage.TextureUsage;
|
return stage.TextureUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Enumerable.Empty<ShaderDeclInfo>();
|
return Enumerable.Empty<ShaderDeclInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void SetExtraData(float FlipX, float FlipY, int Instance)
|
public unsafe void SetExtraData(float flipX, float flipY, int instance)
|
||||||
{
|
{
|
||||||
BindProgram();
|
BindProgram();
|
||||||
|
|
||||||
EnsureExtraBlock();
|
EnsureExtraBlock();
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.UniformBuffer, ExtraUboHandle);
|
GL.BindBuffer(BufferTarget.UniformBuffer, _extraUboHandle);
|
||||||
|
|
||||||
float* Data = stackalloc float[ExtraDataSize];
|
float* data = stackalloc float[ExtraDataSize];
|
||||||
Data[0] = FlipX;
|
data[0] = flipX;
|
||||||
Data[1] = FlipY;
|
data[1] = flipY;
|
||||||
Data[2] = BitConverter.Int32BitsToSingle(Instance);
|
data[2] = BitConverter.Int32BitsToSingle(instance);
|
||||||
|
|
||||||
//Invalidate buffer
|
//Invalidate buffer
|
||||||
GL.BufferData(BufferTarget.UniformBuffer, ExtraDataSize * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.UniformBuffer, ExtraDataSize * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
|
||||||
|
|
||||||
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, ExtraDataSize * sizeof(float), (IntPtr)Data);
|
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, ExtraDataSize * sizeof(float), (IntPtr)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind(long Key)
|
public void Bind(long key)
|
||||||
{
|
{
|
||||||
if (Stages.TryGetValue(Key, out OGLShaderStage Stage))
|
if (_stages.TryGetValue(key, out OglShaderStage stage))
|
||||||
{
|
{
|
||||||
Bind(Stage);
|
Bind(stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Bind(OGLShaderStage Stage)
|
private void Bind(OglShaderStage stage)
|
||||||
{
|
{
|
||||||
if (Stage.Type == GalShaderType.Geometry)
|
if (stage.Type == GalShaderType.Geometry)
|
||||||
{
|
{
|
||||||
//Enhanced layouts are required for Geometry shaders
|
//Enhanced layouts are required for Geometry shaders
|
||||||
//skip this stage if current driver has no ARB_enhanced_layouts
|
//skip this stage if current driver has no ARB_enhanced_layouts
|
||||||
if (!OGLExtension.EnhancedLayouts)
|
if (!OglExtension.EnhancedLayouts)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Stage.Type)
|
switch (stage.Type)
|
||||||
{
|
{
|
||||||
case GalShaderType.Vertex: Current.Vertex = Stage; break;
|
case GalShaderType.Vertex: Current.Vertex = stage; break;
|
||||||
case GalShaderType.TessControl: Current.TessControl = Stage; break;
|
case GalShaderType.TessControl: Current.TessControl = stage; break;
|
||||||
case GalShaderType.TessEvaluation: Current.TessEvaluation = Stage; break;
|
case GalShaderType.TessEvaluation: Current.TessEvaluation = stage; break;
|
||||||
case GalShaderType.Geometry: Current.Geometry = Stage; break;
|
case GalShaderType.Geometry: Current.Geometry = stage; break;
|
||||||
case GalShaderType.Fragment: Current.Fragment = Stage; break;
|
case GalShaderType.Fragment: Current.Fragment = stage; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unbind(GalShaderType Type)
|
public void Unbind(GalShaderType type)
|
||||||
{
|
{
|
||||||
switch (Type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case GalShaderType.Vertex: Current.Vertex = null; break;
|
case GalShaderType.Vertex: Current.Vertex = null; break;
|
||||||
case GalShaderType.TessControl: Current.TessControl = null; break;
|
case GalShaderType.TessControl: Current.TessControl = null; break;
|
||||||
|
@ -170,80 +170,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Programs.TryGetValue(Current, out int Handle))
|
if (!_programs.TryGetValue(Current, out int handle))
|
||||||
{
|
{
|
||||||
Handle = GL.CreateProgram();
|
handle = GL.CreateProgram();
|
||||||
|
|
||||||
AttachIfNotNull(Handle, Current.Vertex);
|
AttachIfNotNull(handle, Current.Vertex);
|
||||||
AttachIfNotNull(Handle, Current.TessControl);
|
AttachIfNotNull(handle, Current.TessControl);
|
||||||
AttachIfNotNull(Handle, Current.TessEvaluation);
|
AttachIfNotNull(handle, Current.TessEvaluation);
|
||||||
AttachIfNotNull(Handle, Current.Geometry);
|
AttachIfNotNull(handle, Current.Geometry);
|
||||||
AttachIfNotNull(Handle, Current.Fragment);
|
AttachIfNotNull(handle, Current.Fragment);
|
||||||
|
|
||||||
GL.LinkProgram(Handle);
|
GL.LinkProgram(handle);
|
||||||
|
|
||||||
CheckProgramLink(Handle);
|
CheckProgramLink(handle);
|
||||||
|
|
||||||
BindUniformBlocks(Handle);
|
BindUniformBlocks(handle);
|
||||||
BindTextureLocations(Handle);
|
BindTextureLocations(handle);
|
||||||
|
|
||||||
Programs.Add(Current, Handle);
|
_programs.Add(Current, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.UseProgram(Handle);
|
GL.UseProgram(handle);
|
||||||
|
|
||||||
CurrentProgramHandle = Handle;
|
CurrentProgramHandle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureExtraBlock()
|
private void EnsureExtraBlock()
|
||||||
{
|
{
|
||||||
if (ExtraUboHandle == 0)
|
if (_extraUboHandle == 0)
|
||||||
{
|
{
|
||||||
ExtraUboHandle = GL.GenBuffer();
|
_extraUboHandle = GL.GenBuffer();
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.UniformBuffer, ExtraUboHandle);
|
GL.BindBuffer(BufferTarget.UniformBuffer, _extraUboHandle);
|
||||||
|
|
||||||
GL.BufferData(BufferTarget.UniformBuffer, ExtraDataSize * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.UniformBuffer, ExtraDataSize * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
|
||||||
|
|
||||||
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, ExtraUboHandle);
|
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, _extraUboHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AttachIfNotNull(int ProgramHandle, OGLShaderStage Stage)
|
private void AttachIfNotNull(int programHandle, OglShaderStage stage)
|
||||||
{
|
{
|
||||||
if (Stage != null)
|
if (stage != null)
|
||||||
{
|
{
|
||||||
Stage.Compile();
|
stage.Compile();
|
||||||
|
|
||||||
GL.AttachShader(ProgramHandle, Stage.Handle);
|
GL.AttachShader(programHandle, stage.Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindUniformBlocks(int ProgramHandle)
|
private void BindUniformBlocks(int programHandle)
|
||||||
{
|
{
|
||||||
int ExtraBlockindex = GL.GetUniformBlockIndex(ProgramHandle, GlslDecl.ExtraUniformBlockName);
|
int extraBlockindex = GL.GetUniformBlockIndex(programHandle, GlslDecl.ExtraUniformBlockName);
|
||||||
|
|
||||||
GL.UniformBlockBinding(ProgramHandle, ExtraBlockindex, 0);
|
GL.UniformBlockBinding(programHandle, extraBlockindex, 0);
|
||||||
|
|
||||||
int FreeBinding = ReservedCbufCount;
|
int freeBinding = ReservedCbufCount;
|
||||||
|
|
||||||
void BindUniformBlocksIfNotNull(OGLShaderStage Stage)
|
void BindUniformBlocksIfNotNull(OglShaderStage stage)
|
||||||
{
|
{
|
||||||
if (Stage != null)
|
if (stage != null)
|
||||||
{
|
{
|
||||||
foreach (ShaderDeclInfo DeclInfo in Stage.ConstBufferUsage)
|
foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage)
|
||||||
{
|
{
|
||||||
int BlockIndex = GL.GetUniformBlockIndex(ProgramHandle, DeclInfo.Name);
|
int blockIndex = GL.GetUniformBlockIndex(programHandle, declInfo.Name);
|
||||||
|
|
||||||
if (BlockIndex < 0)
|
if (blockIndex < 0)
|
||||||
{
|
{
|
||||||
//It is expected that its found, if it's not then driver might be in a malfunction
|
//It is expected that its found, if it's not then driver might be in a malfunction
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.UniformBlockBinding(ProgramHandle, BlockIndex, FreeBinding);
|
GL.UniformBlockBinding(programHandle, blockIndex, freeBinding);
|
||||||
|
|
||||||
FreeBinding++;
|
freeBinding++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,26 +255,26 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
BindUniformBlocksIfNotNull(Current.Fragment);
|
BindUniformBlocksIfNotNull(Current.Fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindTextureLocations(int ProgramHandle)
|
private void BindTextureLocations(int programHandle)
|
||||||
{
|
{
|
||||||
int Index = 0;
|
int index = 0;
|
||||||
|
|
||||||
void BindTexturesIfNotNull(OGLShaderStage Stage)
|
void BindTexturesIfNotNull(OglShaderStage stage)
|
||||||
{
|
{
|
||||||
if (Stage != null)
|
if (stage != null)
|
||||||
{
|
{
|
||||||
foreach (ShaderDeclInfo Decl in Stage.TextureUsage)
|
foreach (ShaderDeclInfo decl in stage.TextureUsage)
|
||||||
{
|
{
|
||||||
int Location = GL.GetUniformLocation(ProgramHandle, Decl.Name);
|
int location = GL.GetUniformLocation(programHandle, decl.Name);
|
||||||
|
|
||||||
GL.Uniform1(Location, Index);
|
GL.Uniform1(location, index);
|
||||||
|
|
||||||
Index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.UseProgram(ProgramHandle);
|
GL.UseProgram(programHandle);
|
||||||
|
|
||||||
BindTexturesIfNotNull(Current.Vertex);
|
BindTexturesIfNotNull(Current.Vertex);
|
||||||
BindTexturesIfNotNull(Current.TessControl);
|
BindTexturesIfNotNull(Current.TessControl);
|
||||||
|
@ -283,15 +283,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
BindTexturesIfNotNull(Current.Fragment);
|
BindTexturesIfNotNull(Current.Fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckProgramLink(int Handle)
|
private static void CheckProgramLink(int handle)
|
||||||
{
|
{
|
||||||
int Status = 0;
|
int status = 0;
|
||||||
|
|
||||||
GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out Status);
|
GL.GetProgram(handle, GetProgramParameterName.LinkStatus, out status);
|
||||||
|
|
||||||
if (Status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
throw new ShaderException(GL.GetProgramInfoLog(Handle));
|
throw new ShaderException(GL.GetProgramInfoLog(handle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,16 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
struct OGLShaderProgram
|
struct OglShaderProgram
|
||||||
{
|
{
|
||||||
public OGLShaderStage Vertex;
|
public OglShaderStage Vertex;
|
||||||
public OGLShaderStage TessControl;
|
public OglShaderStage TessControl;
|
||||||
public OGLShaderStage TessEvaluation;
|
public OglShaderStage TessEvaluation;
|
||||||
public OGLShaderStage Geometry;
|
public OglShaderStage Geometry;
|
||||||
public OGLShaderStage Fragment;
|
public OglShaderStage Fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
class OGLShaderStage : IDisposable
|
class OglShaderStage : IDisposable
|
||||||
{
|
{
|
||||||
public int Handle { get; private set; }
|
public int Handle { get; private set; }
|
||||||
|
|
||||||
|
@ -26,23 +26,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
public IEnumerable<ShaderDeclInfo> ConstBufferUsage { get; private set; }
|
public IEnumerable<ShaderDeclInfo> ConstBufferUsage { get; private set; }
|
||||||
public IEnumerable<ShaderDeclInfo> TextureUsage { get; private set; }
|
public IEnumerable<ShaderDeclInfo> TextureUsage { get; private set; }
|
||||||
|
|
||||||
public OGLShaderStage(
|
public OglShaderStage(
|
||||||
GalShaderType Type,
|
GalShaderType type,
|
||||||
string Code,
|
string code,
|
||||||
IEnumerable<ShaderDeclInfo> ConstBufferUsage,
|
IEnumerable<ShaderDeclInfo> constBufferUsage,
|
||||||
IEnumerable<ShaderDeclInfo> TextureUsage)
|
IEnumerable<ShaderDeclInfo> textureUsage)
|
||||||
{
|
{
|
||||||
this.Type = Type;
|
Type = type;
|
||||||
this.Code = Code;
|
Code = code;
|
||||||
this.ConstBufferUsage = ConstBufferUsage;
|
ConstBufferUsage = constBufferUsage;
|
||||||
this.TextureUsage = TextureUsage;
|
TextureUsage = textureUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Compile()
|
public void Compile()
|
||||||
{
|
{
|
||||||
if (Handle == 0)
|
if (Handle == 0)
|
||||||
{
|
{
|
||||||
Handle = GL.CreateShader(OGLEnumConverter.GetShaderType(Type));
|
Handle = GL.CreateShader(OglEnumConverter.GetShaderType(Type));
|
||||||
|
|
||||||
CompileAndCheck(Handle, Code);
|
CompileAndCheck(Handle, Code);
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool Disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (Disposing && Handle != 0)
|
if (disposing && Handle != 0)
|
||||||
{
|
{
|
||||||
GL.DeleteShader(Handle);
|
GL.DeleteShader(Handle);
|
||||||
|
|
||||||
|
@ -63,23 +63,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CompileAndCheck(int Handle, string Code)
|
public static void CompileAndCheck(int handle, string code)
|
||||||
{
|
{
|
||||||
GL.ShaderSource(Handle, Code);
|
GL.ShaderSource(handle, code);
|
||||||
GL.CompileShader(Handle);
|
GL.CompileShader(handle);
|
||||||
|
|
||||||
CheckCompilation(Handle);
|
CheckCompilation(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckCompilation(int Handle)
|
private static void CheckCompilation(int handle)
|
||||||
{
|
{
|
||||||
int Status = 0;
|
int status = 0;
|
||||||
|
|
||||||
GL.GetShader(Handle, ShaderParameter.CompileStatus, out Status);
|
GL.GetShader(handle, ShaderParameter.CompileStatus, out status);
|
||||||
|
|
||||||
if (Status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
throw new ShaderException(GL.GetShaderInfoLog(Handle));
|
throw new ShaderException(GL.GetShaderInfoLog(handle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLStreamBuffer : IDisposable
|
class OglStreamBuffer : IDisposable
|
||||||
{
|
{
|
||||||
public int Handle { get; protected set; }
|
public int Handle { get; protected set; }
|
||||||
|
|
||||||
|
@ -11,30 +11,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
protected BufferTarget Target { get; private set; }
|
protected BufferTarget Target { get; private set; }
|
||||||
|
|
||||||
public OGLStreamBuffer(BufferTarget Target, long Size)
|
public OglStreamBuffer(BufferTarget target, long size)
|
||||||
{
|
{
|
||||||
this.Target = Target;
|
Target = target;
|
||||||
this.Size = Size;
|
Size = size;
|
||||||
|
|
||||||
Handle = GL.GenBuffer();
|
Handle = GL.GenBuffer();
|
||||||
|
|
||||||
GL.BindBuffer(Target, Handle);
|
GL.BindBuffer(target, Handle);
|
||||||
|
|
||||||
GL.BufferData(Target, (IntPtr)Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
|
GL.BufferData(target, (IntPtr)size, IntPtr.Zero, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(long Size, IntPtr HostAddress)
|
public void SetData(long size, IntPtr hostAddress)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(Target, Handle);
|
GL.BindBuffer(Target, Handle);
|
||||||
|
|
||||||
GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)Size, HostAddress);
|
GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)size, hostAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(byte[] Data)
|
public void SetData(byte[] data)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(Target, Handle);
|
GL.BindBuffer(Target, Handle);
|
||||||
|
|
||||||
GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)Data.Length, Data);
|
GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)data.Length, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -42,9 +42,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool Disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (Disposing && Handle != 0)
|
if (disposing && Handle != 0)
|
||||||
{
|
{
|
||||||
GL.DeleteBuffer(Handle);
|
GL.DeleteBuffer(Handle);
|
||||||
|
|
||||||
|
|
|
@ -4,377 +4,377 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLTexture : IGalTexture
|
class OglTexture : IGalTexture
|
||||||
{
|
{
|
||||||
private const long MaxTextureCacheSize = 768 * 1024 * 1024;
|
private const long MaxTextureCacheSize = 768 * 1024 * 1024;
|
||||||
|
|
||||||
private OGLCachedResource<ImageHandler> TextureCache;
|
private OglCachedResource<ImageHandler> _textureCache;
|
||||||
|
|
||||||
public EventHandler<int> TextureDeleted { get; set; }
|
public EventHandler<int> TextureDeleted { get; set; }
|
||||||
|
|
||||||
public OGLTexture()
|
public OglTexture()
|
||||||
{
|
{
|
||||||
TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture, MaxTextureCacheSize);
|
_textureCache = new OglCachedResource<ImageHandler>(DeleteTexture, MaxTextureCacheSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LockCache()
|
public void LockCache()
|
||||||
{
|
{
|
||||||
TextureCache.Lock();
|
_textureCache.Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnlockCache()
|
public void UnlockCache()
|
||||||
{
|
{
|
||||||
TextureCache.Unlock();
|
_textureCache.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteTexture(ImageHandler CachedImage)
|
private void DeleteTexture(ImageHandler cachedImage)
|
||||||
{
|
{
|
||||||
TextureDeleted?.Invoke(this, CachedImage.Handle);
|
TextureDeleted?.Invoke(this, cachedImage.Handle);
|
||||||
|
|
||||||
GL.DeleteTexture(CachedImage.Handle);
|
GL.DeleteTexture(cachedImage.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(long Key, int Size, GalImage Image)
|
public void Create(long key, int size, GalImage image)
|
||||||
{
|
{
|
||||||
int Handle = GL.GenTexture();
|
int handle = GL.GenTexture();
|
||||||
|
|
||||||
TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureTarget);
|
TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);
|
||||||
|
|
||||||
GL.BindTexture(Target, Handle);
|
GL.BindTexture(target, handle);
|
||||||
|
|
||||||
const int Level = 0; //TODO: Support mipmap textures.
|
const int level = 0; //TODO: Support mipmap textures.
|
||||||
const int Border = 0;
|
const int border = 0;
|
||||||
|
|
||||||
TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);
|
_textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)size);
|
||||||
|
|
||||||
if (ImageUtils.IsCompressed(Image.Format))
|
if (ImageUtils.IsCompressed(image.Format))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
|
throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
|
||||||
}
|
}
|
||||||
|
|
||||||
(PixelInternalFormat InternalFmt,
|
(PixelInternalFormat internalFmt,
|
||||||
PixelFormat Format,
|
PixelFormat format,
|
||||||
PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
|
PixelType type) = OglEnumConverter.GetImageFormat(image.Format);
|
||||||
|
|
||||||
switch (Target)
|
switch (target)
|
||||||
{
|
{
|
||||||
case TextureTarget.Texture1D:
|
case TextureTarget.Texture1D:
|
||||||
GL.TexImage1D(
|
GL.TexImage1D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
IntPtr.Zero);
|
IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureTarget.Texture2D:
|
case TextureTarget.Texture2D:
|
||||||
GL.TexImage2D(
|
GL.TexImage2D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
IntPtr.Zero);
|
IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture3D:
|
case TextureTarget.Texture3D:
|
||||||
GL.TexImage3D(
|
GL.TexImage3D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.Depth,
|
image.Depth,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
IntPtr.Zero);
|
IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture2DArray:
|
case TextureTarget.Texture2DArray:
|
||||||
GL.TexImage3D(
|
GL.TexImage3D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.LayerCount,
|
image.LayerCount,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
IntPtr.Zero);
|
IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"Unsupported texture target type: {Target}");
|
throw new NotImplementedException($"Unsupported texture target type: {target}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(long Key, byte[] Data, GalImage Image)
|
public void Create(long key, byte[] data, GalImage image)
|
||||||
{
|
{
|
||||||
int Handle = GL.GenTexture();
|
int handle = GL.GenTexture();
|
||||||
|
|
||||||
TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureTarget);
|
TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);
|
||||||
|
|
||||||
GL.BindTexture(Target, Handle);
|
GL.BindTexture(target, handle);
|
||||||
|
|
||||||
const int Level = 0; //TODO: Support mipmap textures.
|
const int level = 0; //TODO: Support mipmap textures.
|
||||||
const int Border = 0;
|
const int border = 0;
|
||||||
|
|
||||||
TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
|
_textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)data.Length);
|
||||||
|
|
||||||
if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format))
|
if (ImageUtils.IsCompressed(image.Format) && !IsAstc(image.Format))
|
||||||
{
|
{
|
||||||
InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
|
InternalFormat internalFmt = OglEnumConverter.GetCompressedImageFormat(image.Format);
|
||||||
|
|
||||||
switch (Target)
|
switch (target)
|
||||||
{
|
{
|
||||||
case TextureTarget.Texture1D:
|
case TextureTarget.Texture1D:
|
||||||
GL.CompressedTexImage1D(
|
GL.CompressedTexImage1D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Border,
|
border,
|
||||||
Data.Length,
|
data.Length,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture2D:
|
case TextureTarget.Texture2D:
|
||||||
GL.CompressedTexImage2D(
|
GL.CompressedTexImage2D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Border,
|
border,
|
||||||
Data.Length,
|
data.Length,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture3D:
|
case TextureTarget.Texture3D:
|
||||||
GL.CompressedTexImage3D(
|
GL.CompressedTexImage3D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.Depth,
|
image.Depth,
|
||||||
Border,
|
border,
|
||||||
Data.Length,
|
data.Length,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture2DArray:
|
case TextureTarget.Texture2DArray:
|
||||||
GL.CompressedTexImage3D(
|
GL.CompressedTexImage3D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.LayerCount,
|
image.LayerCount,
|
||||||
Border,
|
border,
|
||||||
Data.Length,
|
data.Length,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"Unsupported texture target type: {Target}");
|
throw new NotImplementedException($"Unsupported texture target type: {target}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO: Use KHR_texture_compression_astc_hdr when available
|
//TODO: Use KHR_texture_compression_astc_hdr when available
|
||||||
if (IsAstc(Image.Format))
|
if (IsAstc(image.Format))
|
||||||
{
|
{
|
||||||
int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format);
|
int textureBlockWidth = ImageUtils.GetBlockWidth(image.Format);
|
||||||
int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format);
|
int textureBlockHeight = ImageUtils.GetBlockHeight(image.Format);
|
||||||
int TextureBlockDepth = ImageUtils.GetBlockDepth(Image.Format);
|
int textureBlockDepth = ImageUtils.GetBlockDepth(image.Format);
|
||||||
|
|
||||||
Data = ASTCDecoder.DecodeToRGBA8888(
|
data = ASTCDecoder.DecodeToRGBA8888(
|
||||||
Data,
|
data,
|
||||||
TextureBlockWidth,
|
textureBlockWidth,
|
||||||
TextureBlockHeight,
|
textureBlockHeight,
|
||||||
TextureBlockDepth,
|
textureBlockDepth,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.Depth);
|
image.Depth);
|
||||||
|
|
||||||
Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask);
|
image.Format = GalImageFormat.RGBA8 | (image.Format & GalImageFormat.TypeMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
(PixelInternalFormat InternalFmt,
|
(PixelInternalFormat internalFmt,
|
||||||
PixelFormat Format,
|
PixelFormat format,
|
||||||
PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
|
PixelType type) = OglEnumConverter.GetImageFormat(image.Format);
|
||||||
|
|
||||||
|
|
||||||
switch (Target)
|
switch (target)
|
||||||
{
|
{
|
||||||
case TextureTarget.Texture1D:
|
case TextureTarget.Texture1D:
|
||||||
GL.TexImage1D(
|
GL.TexImage1D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture2D:
|
case TextureTarget.Texture2D:
|
||||||
GL.TexImage2D(
|
GL.TexImage2D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture3D:
|
case TextureTarget.Texture3D:
|
||||||
GL.TexImage3D(
|
GL.TexImage3D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.Depth,
|
image.Depth,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.Texture2DArray:
|
case TextureTarget.Texture2DArray:
|
||||||
GL.TexImage3D(
|
GL.TexImage3D(
|
||||||
Target,
|
target,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Image.LayerCount,
|
image.LayerCount,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
Data);
|
data);
|
||||||
break;
|
break;
|
||||||
case TextureTarget.TextureCubeMap:
|
case TextureTarget.TextureCubeMap:
|
||||||
Span<byte> Array = new Span<byte>(Data);
|
Span<byte> array = new Span<byte>(data);
|
||||||
|
|
||||||
int FaceSize = ImageUtils.GetSize(Image) / 6;
|
int faceSize = ImageUtils.GetSize(image) / 6;
|
||||||
|
|
||||||
for (int Face = 0; Face < 6; Face++)
|
for (int face = 0; face < 6; face++)
|
||||||
{
|
{
|
||||||
GL.TexImage2D(
|
GL.TexImage2D(
|
||||||
TextureTarget.TextureCubeMapPositiveX + Face,
|
TextureTarget.TextureCubeMapPositiveX + face,
|
||||||
Level,
|
level,
|
||||||
InternalFmt,
|
internalFmt,
|
||||||
Image.Width,
|
image.Width,
|
||||||
Image.Height,
|
image.Height,
|
||||||
Border,
|
border,
|
||||||
Format,
|
format,
|
||||||
Type,
|
type,
|
||||||
Array.Slice(Face * FaceSize, FaceSize).ToArray());
|
array.Slice(face * faceSize, faceSize).ToArray());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"Unsupported texture target type: {Target}");
|
throw new NotImplementedException($"Unsupported texture target type: {target}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsAstc(GalImageFormat Format)
|
private static bool IsAstc(GalImageFormat format)
|
||||||
{
|
{
|
||||||
Format &= GalImageFormat.FormatMask;
|
format &= GalImageFormat.FormatMask;
|
||||||
|
|
||||||
return Format > GalImageFormat.Astc2DStart && Format < GalImageFormat.Astc2DEnd;
|
return format > GalImageFormat.Astc2DStart && format < GalImageFormat.Astc2DEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetImage(long Key, out GalImage Image)
|
public bool TryGetImage(long key, out GalImage image)
|
||||||
{
|
{
|
||||||
if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
|
if (_textureCache.TryGetValue(key, out ImageHandler cachedImage))
|
||||||
{
|
{
|
||||||
Image = CachedImage.Image;
|
image = cachedImage.Image;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image = default(GalImage);
|
image = default(GalImage);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetImageHandler(long Key, out ImageHandler CachedImage)
|
public bool TryGetImageHandler(long key, out ImageHandler cachedImage)
|
||||||
{
|
{
|
||||||
if (TextureCache.TryGetValue(Key, out CachedImage))
|
if (_textureCache.TryGetValue(key, out cachedImage))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedImage = null;
|
cachedImage = null;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind(long Key, int Index, GalImage Image)
|
public void Bind(long key, int index, GalImage image)
|
||||||
{
|
{
|
||||||
if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
|
if (_textureCache.TryGetValue(key, out ImageHandler cachedImage))
|
||||||
{
|
{
|
||||||
GL.ActiveTexture(TextureUnit.Texture0 + Index);
|
GL.ActiveTexture(TextureUnit.Texture0 + index);
|
||||||
|
|
||||||
TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureTarget);
|
TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);
|
||||||
|
|
||||||
GL.BindTexture(Target, CachedImage.Handle);
|
GL.BindTexture(target, cachedImage.Handle);
|
||||||
|
|
||||||
int[] SwizzleRgba = new int[]
|
int[] swizzleRgba = new int[]
|
||||||
{
|
{
|
||||||
(int)OGLEnumConverter.GetTextureSwizzle(Image.XSource),
|
(int)OglEnumConverter.GetTextureSwizzle(image.XSource),
|
||||||
(int)OGLEnumConverter.GetTextureSwizzle(Image.YSource),
|
(int)OglEnumConverter.GetTextureSwizzle(image.YSource),
|
||||||
(int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource),
|
(int)OglEnumConverter.GetTextureSwizzle(image.ZSource),
|
||||||
(int)OGLEnumConverter.GetTextureSwizzle(Image.WSource)
|
(int)OglEnumConverter.GetTextureSwizzle(image.WSource)
|
||||||
};
|
};
|
||||||
|
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureSwizzleRgba, SwizzleRgba);
|
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSampler(GalImage Image, GalTextureSampler Sampler)
|
public void SetSampler(GalImage image, GalTextureSampler sampler)
|
||||||
{
|
{
|
||||||
int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
|
int wrapS = (int)OglEnumConverter.GetTextureWrapMode(sampler.AddressU);
|
||||||
int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
|
int wrapT = (int)OglEnumConverter.GetTextureWrapMode(sampler.AddressV);
|
||||||
int WrapR = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressP);
|
int wrapR = (int)OglEnumConverter.GetTextureWrapMode(sampler.AddressP);
|
||||||
|
|
||||||
int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
|
int minFilter = (int)OglEnumConverter.GetTextureMinFilter(sampler.MinFilter, sampler.MipFilter);
|
||||||
int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
|
int magFilter = (int)OglEnumConverter.GetTextureMagFilter(sampler.MagFilter);
|
||||||
|
|
||||||
TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureTarget);
|
TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);
|
||||||
|
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureWrapS, WrapS);
|
GL.TexParameter(target, TextureParameterName.TextureWrapS, wrapS);
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureWrapT, WrapT);
|
GL.TexParameter(target, TextureParameterName.TextureWrapT, wrapT);
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureWrapR, WrapR);
|
GL.TexParameter(target, TextureParameterName.TextureWrapR, wrapR);
|
||||||
|
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter);
|
GL.TexParameter(target, TextureParameterName.TextureMinFilter, minFilter);
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter);
|
GL.TexParameter(target, TextureParameterName.TextureMagFilter, magFilter);
|
||||||
|
|
||||||
float[] Color = new float[]
|
float[] color = new float[]
|
||||||
{
|
{
|
||||||
Sampler.BorderColor.Red,
|
sampler.BorderColor.Red,
|
||||||
Sampler.BorderColor.Green,
|
sampler.BorderColor.Green,
|
||||||
Sampler.BorderColor.Blue,
|
sampler.BorderColor.Blue,
|
||||||
Sampler.BorderColor.Alpha
|
sampler.BorderColor.Alpha
|
||||||
};
|
};
|
||||||
|
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureBorderColor, Color);
|
GL.TexParameter(target, TextureParameterName.TextureBorderColor, color);
|
||||||
|
|
||||||
if (Sampler.DepthCompare)
|
if (sampler.DepthCompare)
|
||||||
{
|
{
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureCompareMode, (int)All.CompareRToTexture);
|
GL.TexParameter(target, TextureParameterName.TextureCompareMode, (int)All.CompareRToTexture);
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureCompareFunc, (int)OGLEnumConverter.GetDepthCompareFunc(Sampler.DepthCompareFunc));
|
GL.TexParameter(target, TextureParameterName.TextureCompareFunc, (int)OglEnumConverter.GetDepthCompareFunc(sampler.DepthCompareFunc));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureCompareMode, (int)All.None);
|
GL.TexParameter(target, TextureParameterName.TextureCompareMode, (int)All.None);
|
||||||
GL.TexParameter(Target, TextureParameterName.TextureCompareFunc, (int)All.Never);
|
GL.TexParameter(target, TextureParameterName.TextureCompareFunc, (int)All.Never);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx
|
||||||
{
|
{
|
||||||
Console.Title = "Ryujinx Console";
|
Console.Title = "Ryujinx Console";
|
||||||
|
|
||||||
IGalRenderer renderer = new OGLRenderer();
|
IGalRenderer renderer = new OglRenderer();
|
||||||
|
|
||||||
IAalOutput audioOut = InitializeAudioEngine();
|
IAalOutput audioOut = InitializeAudioEngine();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue