Small OpenGL Renderer refactoring (#177)
* Call OpenGL functions directly, remove the pfifo thread, some refactoring * Fix PerformanceStatistics calculating the wrong host fps, remove wait event on PFIFO as this wasn't exactly was causing the freezes (may replace with an exception later) * Organized the Gpu folder a bit more, renamed a few things, address PR feedback * Make PerformanceStatistics thread safe * Remove unused constant * Use unlimited update rate for better pref
This commit is contained in:
@ -1,7 +0,0 @@
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public static class GalConsts
|
||||
{
|
||||
public const string FlipUniformName = "flip";
|
||||
}
|
||||
}
|
22
Ryujinx.Graphics/Gal/IGalBlend.cs
Normal file
22
Ryujinx.Graphics/Gal/IGalBlend.cs
Normal file
@ -0,0 +1,22 @@
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public interface IGalBlend
|
||||
{
|
||||
void Enable();
|
||||
|
||||
void Disable();
|
||||
|
||||
void Set(
|
||||
GalBlendEquation Equation,
|
||||
GalBlendFactor FuncSrc,
|
||||
GalBlendFactor FuncDst);
|
||||
|
||||
void SetSeparate(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha);
|
||||
}
|
||||
}
|
27
Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
Normal file
27
Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public interface IGalFrameBuffer
|
||||
{
|
||||
void Create(long Key, int Width, int Height);
|
||||
|
||||
void Bind(long Key);
|
||||
|
||||
void BindTexture(long Key, int Index);
|
||||
|
||||
void Set(long Key);
|
||||
|
||||
void Set(byte[] Data, int Width, int Height);
|
||||
|
||||
void SetTransform(float SX, float SY, float Rotate, float TX, float TY);
|
||||
|
||||
void SetWindowSize(int Width, int Height);
|
||||
|
||||
void SetViewport(int X, int Y, int Width, int Height);
|
||||
|
||||
void Render();
|
||||
|
||||
void GetBufferData(long Key, Action<byte[]> Callback);
|
||||
}
|
||||
}
|
23
Ryujinx.Graphics/Gal/IGalRasterizer.cs
Normal file
23
Ryujinx.Graphics/Gal/IGalRasterizer.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public interface IGalRasterizer
|
||||
{
|
||||
void ClearBuffers(int RtIndex, GalClearBufferFlags Flags);
|
||||
|
||||
bool IsVboCached(long Key, long DataSize);
|
||||
|
||||
bool IsIboCached(long Key, long DataSize);
|
||||
|
||||
void CreateVbo(long Key, byte[] Buffer);
|
||||
|
||||
void CreateIbo(long Key, byte[] Buffer);
|
||||
|
||||
void SetVertexArray(int VbIndex, int Stride, long VboKey, GalVertexAttrib[] Attribs);
|
||||
|
||||
void SetIndexArray(long Key, int Size, GalIndexFormat Format);
|
||||
|
||||
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
|
||||
|
||||
void DrawElements(long IboKey, int First, GalPrimitiveType PrimType);
|
||||
}
|
||||
}
|
@ -1,90 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public unsafe interface IGalRenderer
|
||||
public interface IGalRenderer
|
||||
{
|
||||
void QueueAction(Action ActionMthd);
|
||||
|
||||
void RunActions();
|
||||
|
||||
void Render();
|
||||
IGalBlend Blend { get; }
|
||||
|
||||
void SetWindowSize(int Width, int Height);
|
||||
IGalFrameBuffer FrameBuffer { get; }
|
||||
|
||||
//Blend
|
||||
void SetBlendEnable(bool Enable);
|
||||
IGalRasterizer Rasterizer { get; }
|
||||
|
||||
void SetBlend(
|
||||
GalBlendEquation Equation,
|
||||
GalBlendFactor FuncSrc,
|
||||
GalBlendFactor FuncDst);
|
||||
IGalShader Shader { get; }
|
||||
|
||||
void SetBlendSeparate(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha);
|
||||
|
||||
//Frame Buffer
|
||||
void CreateFrameBuffer(long Tag, int Width, int Height);
|
||||
|
||||
void BindFrameBuffer(long Tag);
|
||||
|
||||
void BindFrameBufferTexture(long Tag, int Index, GalTextureSampler Sampler);
|
||||
|
||||
void SetFrameBuffer(long Tag);
|
||||
|
||||
void SetFrameBuffer(byte[] Data, int Width, int Height);
|
||||
|
||||
void SetFrameBufferTransform(float SX, float SY, float Rotate, float TX, float TY);
|
||||
|
||||
void SetViewport(int X, int Y, int Width, int Height);
|
||||
|
||||
void GetFrameBufferData(long Tag, Action<byte[]> Callback);
|
||||
|
||||
//Rasterizer
|
||||
void ClearBuffers(int RtIndex, GalClearBufferFlags Flags);
|
||||
|
||||
bool IsVboCached(long Tag, long DataSize);
|
||||
|
||||
bool IsIboCached(long Tag, long DataSize);
|
||||
|
||||
void CreateVbo(long Tag, byte[] Buffer);
|
||||
|
||||
void CreateIbo(long Tag, byte[] Buffer);
|
||||
|
||||
void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs);
|
||||
|
||||
void SetIndexArray(long Tag, int Size, GalIndexFormat Format);
|
||||
|
||||
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
|
||||
|
||||
void DrawElements(long IboTag, int First, GalPrimitiveType PrimType);
|
||||
|
||||
//Shader
|
||||
void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type);
|
||||
|
||||
IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag);
|
||||
|
||||
void SetConstBuffer(long Tag, int Cbuf, byte[] Data);
|
||||
|
||||
void SetUniform1(string UniformName, int Value);
|
||||
|
||||
void SetUniform2F(string UniformName, float X, float Y);
|
||||
|
||||
void BindShader(long Tag);
|
||||
|
||||
void BindProgram();
|
||||
|
||||
//Texture
|
||||
void SetTextureAndSampler(long Tag, byte[] Data, GalTexture Texture, GalTextureSampler Sampler);
|
||||
|
||||
bool TryGetCachedTexture(long Tag, long DataSize, out GalTexture Texture);
|
||||
|
||||
void BindTexture(long Tag, int Index);
|
||||
IGalTexture Texture { get; }
|
||||
}
|
||||
}
|
21
Ryujinx.Graphics/Gal/IGalShader.cs
Normal file
21
Ryujinx.Graphics/Gal/IGalShader.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public interface IGalShader
|
||||
{
|
||||
void Create(IGalMemory Memory, long Key, GalShaderType Type);
|
||||
|
||||
IEnumerable<ShaderDeclInfo> GetTextureUsage(long Key);
|
||||
|
||||
void SetConstBuffer(long Key, int Cbuf, byte[] Data);
|
||||
|
||||
void EnsureTextureBinding(string UniformName, int Value);
|
||||
|
||||
void SetFlip(float X, float Y);
|
||||
|
||||
void Bind(long Key);
|
||||
|
||||
void BindProgram();
|
||||
}
|
||||
}
|
13
Ryujinx.Graphics/Gal/IGalTexture.cs
Normal file
13
Ryujinx.Graphics/Gal/IGalTexture.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public interface IGalTexture
|
||||
{
|
||||
void Create(long Key, byte[] Data, GalTexture Texture);
|
||||
|
||||
bool TryGetCachedTexture(long Key, long DataSize, out GalTexture Texture);
|
||||
|
||||
void Bind(long Key, int Index);
|
||||
|
||||
void SetSampler(GalTextureSampler Sampler);
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
class OGLBlend
|
||||
public class OGLBlend : IGalBlend
|
||||
{
|
||||
public void Enable()
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
class OGLFrameBuffer
|
||||
public class OGLFrameBuffer : IGalFrameBuffer
|
||||
{
|
||||
private struct Rect
|
||||
{
|
||||
@ -16,9 +16,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
|
||||
public Rect(int X, int Y, int Width, int Height)
|
||||
{
|
||||
this.X = X;
|
||||
this.Y = Y;
|
||||
this.Width = Width;
|
||||
this.X = X;
|
||||
this.Y = Y;
|
||||
this.Width = Width;
|
||||
this.Height = Height;
|
||||
}
|
||||
}
|
||||
@ -76,14 +76,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
Shader = new ShaderProgram();
|
||||
}
|
||||
|
||||
public void Create(long Tag, int Width, int Height)
|
||||
public void Create(long Key, int Width, int Height)
|
||||
{
|
||||
//TODO: We should either use the original frame buffer size,
|
||||
//or just remove the Width/Height arguments.
|
||||
Width = Window.Width;
|
||||
Height = Window.Height;
|
||||
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
{
|
||||
if (Fb.Width != Width ||
|
||||
Fb.Height != Height)
|
||||
@ -127,12 +127,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
|
||||
GL.Viewport(0, 0, Width, Height);
|
||||
|
||||
Fbs.Add(Tag, Fb);
|
||||
Fbs.Add(Key, Fb);
|
||||
}
|
||||
|
||||
public void Bind(long Tag)
|
||||
public void Bind(long Key)
|
||||
{
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
{
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
|
||||
|
||||
@ -140,9 +140,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public void BindTexture(long Tag, int Index)
|
||||
public void BindTexture(long Key, int Index)
|
||||
{
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + Index);
|
||||
|
||||
@ -150,9 +150,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(long Tag)
|
||||
public void Set(long Key)
|
||||
{
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
{
|
||||
CurrTexHandle = Fb.TexHandle;
|
||||
}
|
||||
@ -185,10 +185,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
CurrTexHandle = RawFbTexHandle;
|
||||
}
|
||||
|
||||
public void SetTransform(Matrix2 Transform, Vector2 Offs)
|
||||
public void SetTransform(float SX, float SY, float Rotate, float TX, float TY)
|
||||
{
|
||||
EnsureInitialized();
|
||||
|
||||
Matrix2 Transform;
|
||||
|
||||
Transform = Matrix2.CreateScale(SX, SY);
|
||||
Transform *= Matrix2.CreateRotation(Rotate);
|
||||
|
||||
Vector2 Offs = new Vector2(TX, TY);
|
||||
|
||||
int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);
|
||||
|
||||
GL.UseProgram(Shader.Handle);
|
||||
@ -270,9 +277,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public void GetBufferData(long Tag, Action<byte[]> Callback)
|
||||
public void GetBufferData(long Key, Action<byte[]> Callback)
|
||||
{
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||
{
|
||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, Fb.Handle);
|
||||
|
||||
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
class OGLRasterizer
|
||||
public class OGLRasterizer : IGalRasterizer
|
||||
{
|
||||
private static Dictionary<GalVertexAttribSize, int> AttribElements =
|
||||
new Dictionary<GalVertexAttribSize, int>()
|
||||
@ -74,8 +74,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
ClearBufferMask Mask = 0;
|
||||
|
||||
//OpenGL doesn't support clearing just a single color channel,
|
||||
//so we can't just clear all channels...
|
||||
//TODO: Use glColorMask to clear just the specified channels.
|
||||
if (Flags.HasFlag(GalClearBufferFlags.ColorRed) &&
|
||||
Flags.HasFlag(GalClearBufferFlags.ColorGreen) &&
|
||||
Flags.HasFlag(GalClearBufferFlags.ColorBlue) &&
|
||||
@ -97,45 +96,43 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
GL.Clear(Mask);
|
||||
}
|
||||
|
||||
public bool IsVboCached(long Tag, long DataSize)
|
||||
public bool IsVboCached(long Key, long DataSize)
|
||||
{
|
||||
return VboCache.TryGetSize(Tag, out long Size) && Size == DataSize;
|
||||
return VboCache.TryGetSize(Key, out long Size) && Size == DataSize;
|
||||
}
|
||||
|
||||
public bool IsIboCached(long Tag, long DataSize)
|
||||
public bool IsIboCached(long Key, long DataSize)
|
||||
{
|
||||
return IboCache.TryGetSize(Tag, out long Size) && Size == DataSize;
|
||||
return IboCache.TryGetSize(Key, out long Size) && Size == DataSize;
|
||||
}
|
||||
|
||||
public void CreateVbo(long Tag, byte[] Buffer)
|
||||
public void CreateVbo(long Key, byte[] Buffer)
|
||||
{
|
||||
int Handle = GL.GenBuffer();
|
||||
|
||||
VboCache.AddOrUpdate(Tag, Handle, (uint)Buffer.Length);
|
||||
VboCache.AddOrUpdate(Key, Handle, (uint)Buffer.Length);
|
||||
|
||||
IntPtr Length = new IntPtr(Buffer.Length);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, Handle);
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||
}
|
||||
|
||||
public void CreateIbo(long Tag, byte[] Buffer)
|
||||
public void CreateIbo(long Key, byte[] Buffer)
|
||||
{
|
||||
int Handle = GL.GenBuffer();
|
||||
|
||||
IboCache.AddOrUpdate(Tag, Handle, (uint)Buffer.Length);
|
||||
IboCache.AddOrUpdate(Key, Handle, (uint)Buffer.Length);
|
||||
|
||||
IntPtr Length = new IntPtr(Buffer.Length);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
|
||||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
|
||||
}
|
||||
|
||||
public void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs)
|
||||
public void SetVertexArray(int VbIndex, int Stride, long VboKey, GalVertexAttrib[] Attribs)
|
||||
{
|
||||
if (!VboCache.TryGetValue(VboTag, out int VboHandle))
|
||||
if (!VboCache.TryGetValue(VboKey, out int VboHandle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -178,11 +175,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
|
||||
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Stride, Offset);
|
||||
}
|
||||
|
||||
GL.BindVertexArray(0);
|
||||
}
|
||||
|
||||
public void SetIndexArray(long Tag, int Size, GalIndexFormat Format)
|
||||
public void SetIndexArray(long Key, int Size, GalIndexFormat Format)
|
||||
{
|
||||
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
|
||||
|
||||
@ -201,9 +196,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
|
||||
}
|
||||
|
||||
public void DrawElements(long IboTag, int First, GalPrimitiveType PrimType)
|
||||
public void DrawElements(long IboKey, int First, GalPrimitiveType PrimType)
|
||||
{
|
||||
if (!IboCache.TryGetValue(IboTag, out int IboHandle))
|
||||
if (!IboCache.TryGetValue(IboKey, out int IboHandle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
50
Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
Normal file
50
Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
public class OGLRenderer : IGalRenderer
|
||||
{
|
||||
public IGalBlend Blend { get; private set; }
|
||||
|
||||
public IGalFrameBuffer FrameBuffer { get; private set; }
|
||||
|
||||
public IGalRasterizer Rasterizer { get; private set; }
|
||||
|
||||
public IGalShader Shader { get; private set; }
|
||||
|
||||
public IGalTexture Texture { get; private set; }
|
||||
|
||||
private ConcurrentQueue<Action> ActionsQueue;
|
||||
|
||||
public OGLRenderer()
|
||||
{
|
||||
Blend = new OGLBlend();
|
||||
|
||||
FrameBuffer = new OGLFrameBuffer();
|
||||
|
||||
Rasterizer = new OGLRasterizer();
|
||||
|
||||
Shader = new OGLShader();
|
||||
|
||||
Texture = new OGLTexture();
|
||||
|
||||
ActionsQueue = new ConcurrentQueue<Action>();
|
||||
}
|
||||
|
||||
public void QueueAction(Action ActionMthd)
|
||||
{
|
||||
ActionsQueue.Enqueue(ActionMthd);
|
||||
}
|
||||
|
||||
public void RunActions()
|
||||
{
|
||||
int Count = ActionsQueue.Count;
|
||||
|
||||
while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction))
|
||||
{
|
||||
RenderAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using System.Linq;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
class OGLShader
|
||||
public class OGLShader : IGalShader
|
||||
{
|
||||
private class ShaderStage : IDisposable
|
||||
{
|
||||
@ -84,9 +84,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
Programs = new Dictionary<ShaderProgram, int>();
|
||||
}
|
||||
|
||||
public void Create(IGalMemory Memory, long Tag, GalShaderType Type)
|
||||
public void Create(IGalMemory Memory, long Key, GalShaderType Type)
|
||||
{
|
||||
Stages.GetOrAdd(Tag, (Key) => ShaderStageFactory(Memory, Tag, Type));
|
||||
Stages.GetOrAdd(Key, (Stage) => ShaderStageFactory(Memory, Key, Type));
|
||||
}
|
||||
|
||||
private ShaderStage ShaderStageFactory(IGalMemory Memory, long Position, GalShaderType Type)
|
||||
@ -107,9 +107,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
return Decompiler.Decompile(Memory, Position + 0x50, Type);
|
||||
}
|
||||
|
||||
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag)
|
||||
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Key)
|
||||
{
|
||||
if (Stages.TryGetValue(Tag, out ShaderStage Stage))
|
||||
if (Stages.TryGetValue(Key, out ShaderStage Stage))
|
||||
{
|
||||
return Stage.TextureUsage;
|
||||
}
|
||||
@ -117,11 +117,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
return Enumerable.Empty<ShaderDeclInfo>();
|
||||
}
|
||||
|
||||
public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
|
||||
public void SetConstBuffer(long Key, int Cbuf, byte[] Data)
|
||||
{
|
||||
BindProgram();
|
||||
|
||||
if (Stages.TryGetValue(Tag, out ShaderStage Stage))
|
||||
if (Stages.TryGetValue(Key, out ShaderStage Stage))
|
||||
{
|
||||
foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage.Where(x => x.Cbuf == Cbuf))
|
||||
{
|
||||
@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public void SetUniform1(string UniformName, int Value)
|
||||
public void EnsureTextureBinding(string UniformName, int Value)
|
||||
{
|
||||
BindProgram();
|
||||
|
||||
@ -153,18 +153,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
GL.Uniform1(Location, Value);
|
||||
}
|
||||
|
||||
public void SetUniform2F(string UniformName, float X, float Y)
|
||||
public void SetFlip(float X, float Y)
|
||||
{
|
||||
BindProgram();
|
||||
|
||||
int Location = GL.GetUniformLocation(CurrentProgramHandle, UniformName);
|
||||
int Location = GL.GetUniformLocation(CurrentProgramHandle, GlslDecl.FlipUniformName);
|
||||
|
||||
GL.Uniform2(Location, X, Y);
|
||||
}
|
||||
|
||||
public void Bind(long Tag)
|
||||
public void Bind(long Key)
|
||||
{
|
||||
if (Stages.TryGetValue(Tag, out ShaderStage Stage))
|
||||
if (Stages.TryGetValue(Key, out ShaderStage Stage))
|
||||
{
|
||||
Bind(Stage);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
class OGLTexture
|
||||
public class OGLTexture : IGalTexture
|
||||
{
|
||||
private class TCE
|
||||
{
|
||||
@ -31,11 +31,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
GL.DeleteTexture(CachedTexture.Handle);
|
||||
}
|
||||
|
||||
public void Create(long Tag, byte[] Data, GalTexture Texture)
|
||||
public void Create(long Key, byte[] Data, GalTexture Texture)
|
||||
{
|
||||
int Handle = GL.GenTexture();
|
||||
|
||||
TextureCache.AddOrUpdate(Tag, new TCE(Handle, Texture), (uint)Data.Length);
|
||||
TextureCache.AddOrUpdate(Key, new TCE(Handle, Texture), (uint)Data.Length);
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, Handle);
|
||||
|
||||
@ -146,11 +146,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
throw new ArgumentException(nameof(Format));
|
||||
}
|
||||
|
||||
public bool TryGetCachedTexture(long Tag, long DataSize, out GalTexture Texture)
|
||||
public bool TryGetCachedTexture(long Key, long DataSize, out GalTexture Texture)
|
||||
{
|
||||
if (TextureCache.TryGetSize(Tag, out long Size) && Size == DataSize)
|
||||
if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize)
|
||||
{
|
||||
if (TextureCache.TryGetValue(Tag, out TCE CachedTexture))
|
||||
if (TextureCache.TryGetValue(Key, out TCE CachedTexture))
|
||||
{
|
||||
Texture = CachedTexture.Texture;
|
||||
|
||||
@ -163,9 +163,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Bind(long Tag, int Index)
|
||||
public void Bind(long Key, int Index)
|
||||
{
|
||||
if (TextureCache.TryGetValue(Tag, out TCE CachedTexture))
|
||||
if (TextureCache.TryGetValue(Key, out TCE CachedTexture))
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + Index);
|
||||
|
||||
@ -173,7 +173,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public static void Set(GalTextureSampler Sampler)
|
||||
public void SetSampler(GalTextureSampler Sampler)
|
||||
{
|
||||
int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
|
||||
int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
|
||||
|
@ -1,284 +0,0 @@
|
||||
using OpenTK;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
public class OpenGLRenderer : IGalRenderer
|
||||
{
|
||||
private OGLBlend Blend;
|
||||
|
||||
private OGLFrameBuffer FrameBuffer;
|
||||
|
||||
private OGLRasterizer Rasterizer;
|
||||
|
||||
private OGLShader Shader;
|
||||
|
||||
private OGLTexture Texture;
|
||||
|
||||
private ConcurrentQueue<Action> ActionsQueue;
|
||||
|
||||
public OpenGLRenderer()
|
||||
{
|
||||
Blend = new OGLBlend();
|
||||
|
||||
FrameBuffer = new OGLFrameBuffer();
|
||||
|
||||
Rasterizer = new OGLRasterizer();
|
||||
|
||||
Shader = new OGLShader();
|
||||
|
||||
Texture = new OGLTexture();
|
||||
|
||||
ActionsQueue = new ConcurrentQueue<Action>();
|
||||
}
|
||||
|
||||
public void QueueAction(Action ActionMthd)
|
||||
{
|
||||
ActionsQueue.Enqueue(ActionMthd);
|
||||
}
|
||||
|
||||
public void RunActions()
|
||||
{
|
||||
int Count = ActionsQueue.Count;
|
||||
|
||||
while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction))
|
||||
{
|
||||
RenderAction();
|
||||
}
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
FrameBuffer.Render();
|
||||
}
|
||||
|
||||
public void SetWindowSize(int Width, int Height)
|
||||
{
|
||||
FrameBuffer.SetWindowSize(Width, Height);
|
||||
}
|
||||
|
||||
public void SetBlendEnable(bool Enable)
|
||||
{
|
||||
if (Enable)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Blend.Enable());
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Blend.Disable());
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBlend(
|
||||
GalBlendEquation Equation,
|
||||
GalBlendFactor FuncSrc,
|
||||
GalBlendFactor FuncDst)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Blend.Set(Equation, FuncSrc, FuncDst));
|
||||
}
|
||||
|
||||
public void SetBlendSeparate(
|
||||
GalBlendEquation EquationRgb,
|
||||
GalBlendEquation EquationAlpha,
|
||||
GalBlendFactor FuncSrcRgb,
|
||||
GalBlendFactor FuncDstRgb,
|
||||
GalBlendFactor FuncSrcAlpha,
|
||||
GalBlendFactor FuncDstAlpha)
|
||||
{
|
||||
ActionsQueue.Enqueue(() =>
|
||||
{
|
||||
Blend.SetSeparate(
|
||||
EquationRgb,
|
||||
EquationAlpha,
|
||||
FuncSrcRgb,
|
||||
FuncDstRgb,
|
||||
FuncSrcAlpha,
|
||||
FuncDstAlpha);
|
||||
});
|
||||
}
|
||||
|
||||
public void CreateFrameBuffer(long Tag, int Width, int Height)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Create(Tag, Width, Height));
|
||||
}
|
||||
|
||||
public void BindFrameBuffer(long Tag)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Bind(Tag));
|
||||
}
|
||||
|
||||
public void BindFrameBufferTexture(long Tag, int Index, GalTextureSampler Sampler)
|
||||
{
|
||||
ActionsQueue.Enqueue(() =>
|
||||
{
|
||||
FrameBuffer.BindTexture(Tag, Index);
|
||||
|
||||
OGLTexture.Set(Sampler);
|
||||
});
|
||||
}
|
||||
|
||||
public void SetFrameBuffer(long Tag)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Set(Tag));
|
||||
}
|
||||
|
||||
public void SetFrameBuffer(byte[] Data, int Width, int Height)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Set(Data, Width, Height));
|
||||
}
|
||||
|
||||
public void SetFrameBufferTransform(float SX, float SY, float Rotate, float TX, float TY)
|
||||
{
|
||||
Matrix2 Transform;
|
||||
|
||||
Transform = Matrix2.CreateScale(SX, SY);
|
||||
Transform *= Matrix2.CreateRotation(Rotate);
|
||||
|
||||
Vector2 Offs = new Vector2(TX, TY);
|
||||
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.SetTransform(Transform, Offs));
|
||||
}
|
||||
|
||||
public void SetViewport(int X, int Y, int Width, int Height)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.SetViewport(X, Y, Width, Height));
|
||||
}
|
||||
|
||||
public void GetFrameBufferData(long Tag, Action<byte[]> Callback)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.GetBufferData(Tag, Callback));
|
||||
}
|
||||
|
||||
public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags));
|
||||
}
|
||||
|
||||
public bool IsVboCached(long Tag, long DataSize)
|
||||
{
|
||||
return Rasterizer.IsVboCached(Tag, DataSize);
|
||||
}
|
||||
|
||||
public bool IsIboCached(long Tag, long DataSize)
|
||||
{
|
||||
return Rasterizer.IsIboCached(Tag, DataSize);
|
||||
}
|
||||
|
||||
public void CreateVbo(long Tag, byte[] Buffer)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Rasterizer.CreateVbo(Tag, Buffer));
|
||||
}
|
||||
|
||||
public void CreateIbo(long Tag, byte[] Buffer)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Rasterizer.CreateIbo(Tag, Buffer));
|
||||
}
|
||||
|
||||
public void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs)
|
||||
{
|
||||
if ((uint)VbIndex > 31)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(VbIndex));
|
||||
}
|
||||
|
||||
if (Attribs == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Attribs));
|
||||
}
|
||||
|
||||
ActionsQueue.Enqueue(() => Rasterizer.SetVertexArray(VbIndex, Stride, VboTag, Attribs));
|
||||
}
|
||||
|
||||
public void SetIndexArray(long Tag, int Size, GalIndexFormat Format)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Tag, Size, Format));
|
||||
}
|
||||
|
||||
public void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(First, PrimCount, PrimType));
|
||||
}
|
||||
|
||||
public void DrawElements(long IboTag, int First, GalPrimitiveType PrimType)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Rasterizer.DrawElements(IboTag, First, PrimType));
|
||||
}
|
||||
|
||||
public void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type)
|
||||
{
|
||||
if (Memory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Memory));
|
||||
}
|
||||
|
||||
Shader.Create(Memory, Tag, Type);
|
||||
}
|
||||
|
||||
public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
|
||||
{
|
||||
if (Data == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Data));
|
||||
}
|
||||
|
||||
ActionsQueue.Enqueue(() => Shader.SetConstBuffer(Tag, Cbuf, Data));
|
||||
}
|
||||
|
||||
public void SetUniform1(string UniformName, int Value)
|
||||
{
|
||||
if (UniformName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(UniformName));
|
||||
}
|
||||
|
||||
ActionsQueue.Enqueue(() => Shader.SetUniform1(UniformName, Value));
|
||||
}
|
||||
|
||||
public void SetUniform2F(string UniformName, float X, float Y)
|
||||
{
|
||||
if (UniformName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(UniformName));
|
||||
}
|
||||
|
||||
ActionsQueue.Enqueue(() => Shader.SetUniform2F(UniformName, X, Y));
|
||||
}
|
||||
|
||||
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag)
|
||||
{
|
||||
return Shader.GetTextureUsage(Tag);
|
||||
}
|
||||
|
||||
public void BindShader(long Tag)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Shader.Bind(Tag));
|
||||
}
|
||||
|
||||
public void BindProgram()
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Shader.BindProgram());
|
||||
}
|
||||
|
||||
public void SetTextureAndSampler(long Tag, byte[] Data, GalTexture Texture, GalTextureSampler Sampler)
|
||||
{
|
||||
ActionsQueue.Enqueue(() =>
|
||||
{
|
||||
this.Texture.Create(Tag, Data, Texture);
|
||||
|
||||
OGLTexture.Set(Sampler);
|
||||
});
|
||||
}
|
||||
|
||||
public bool TryGetCachedTexture(long Tag, long DataSize, out GalTexture Texture)
|
||||
{
|
||||
return this.Texture.TryGetCachedTexture(Tag, DataSize, out Texture);
|
||||
}
|
||||
|
||||
public void BindTexture(long Tag, int Index)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Texture.Bind(Tag, Index));
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||
|
||||
public const string FragmentOutputName = "FragColor";
|
||||
|
||||
public const string FlipUniformName = "flip";
|
||||
|
||||
private string[] StagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" };
|
||||
|
||||
private string StagePrefix;
|
||||
|
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||
{
|
||||
if (Decl.ShaderType == GalShaderType.Vertex)
|
||||
{
|
||||
SB.AppendLine("uniform vec2 " + GalConsts.FlipUniformName + ";");
|
||||
SB.AppendLine("uniform vec2 " + GlslDecl.FlipUniformName + ";");
|
||||
}
|
||||
|
||||
foreach (ShaderDeclInfo DeclInfo in Decl.Uniforms.Values.OrderBy(DeclKeySelector))
|
||||
|
Reference in New Issue
Block a user