aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-04-13 15:12:58 -0300
committerGitHub <noreply@github.com>2018-04-13 15:12:58 -0300
commitc8c86a3854fb3c96e65eca6b59d6058270a21a17 (patch)
tree0f280e0b595d953ca081e493eda41d884fb34ef6
parent262b5b80541d23ed248d5b4f2220a479a35d5969 (diff)
Fix for current framebuffer issues (#78)
[GPU] Fix some of the current framebuffer issues
-rw-r--r--Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Nv/NvMap.cs1
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs119
-rw-r--r--Ryujinx.Graphics/Gal/GalBlendEquation.cs10
-rw-r--r--Ryujinx.Graphics/Gal/GalBlendFactor.cs38
-rw-r--r--Ryujinx.Graphics/Gal/IGalRenderer.cs29
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs250
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs61
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs203
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs20
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs89
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs2
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs21
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs4
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs5
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs366
-rw-r--r--Ryujinx.Graphics/Gpu/NsGpu.cs6
-rw-r--r--Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs103
-rw-r--r--Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs8
-rw-r--r--Ryujinx.Graphics/Gpu/Texture.cs20
-rw-r--r--Ryujinx.Graphics/Gpu/TextureReader.cs2
-rw-r--r--Ryujinx.Graphics/Gpu/TextureSwizzle.cs2
-rw-r--r--Ryujinx/Ui/GLScreen.cs2
23 files changed, 477 insertions, 886 deletions
diff --git a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
index e41f03a4..abda5b86 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
@@ -244,6 +244,8 @@ namespace Ryujinx.Core.OsHle.Services.Nv
Context.Memory.WriteInt64(Position + 0x20, Offset);
+ Map.GpuAddress = Offset;
+
return 0;
}
diff --git a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs
index 9ef70319..f3dd1f47 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/NvMap.cs
@@ -8,5 +8,6 @@ namespace Ryujinx.Core.OsHle.Services.Nv
public int Align;
public int Kind;
public long CpuAddress;
+ public long GpuAddress;
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
index 45b99ead..4ab64e2a 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
@@ -2,6 +2,7 @@ using ChocolArm64.Memory;
using Ryujinx.Core.OsHle.Handles;
using Ryujinx.Core.OsHle.Services.Nv;
using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Gpu;
using System;
using System.Collections.Generic;
using System.IO;
@@ -63,13 +64,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
private ManualResetEvent WaitBufferFree;
- private object RenderQueueLock;
-
- private int RenderQueueCount;
-
- private bool NvFlingerDisposed;
-
- private bool KeepRunning;
+ private bool Disposed;
public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent)
{
@@ -92,10 +87,6 @@ namespace Ryujinx.Core.OsHle.Services.Android
BufferQueue = new BufferEntry[0x40];
WaitBufferFree = new ManualResetEvent(false);
-
- RenderQueueLock = new object();
-
- KeepRunning = true;
}
public long ProcessParcelRequest(ServiceCtx Context, byte[] ParcelData, int Code)
@@ -285,35 +276,24 @@ namespace Ryujinx.Core.OsHle.Services.Android
return 0;
}
- private unsafe void SendFrameBuffer(ServiceCtx Context, int Slot)
+ private void SendFrameBuffer(ServiceCtx Context, int Slot)
{
- int FbWidth = BufferQueue[Slot].Data.Width;
- int FbHeight = BufferQueue[Slot].Data.Height;
-
- long FbSize = (uint)FbWidth * FbHeight * 4;
+ int FbWidth = 1280;
+ int FbHeight = 720;
NvMap Map = GetNvMap(Context, Slot);
NvMapFb MapFb = (NvMapFb)INvDrvServices.NvMapsFb.GetData(Context.Process, 0);
- long Address = Map.CpuAddress;
+ long CpuAddr = Map.CpuAddress;
+ long GpuAddr = Map.GpuAddress;
if (MapFb.HasBufferOffset(Slot))
{
- Address += MapFb.GetBufferOffset(Slot);
- }
-
- if ((ulong)(Address + FbSize) > AMemoryMgr.AddrSize)
- {
- Logging.Error($"Frame buffer address {Address:x16} is invalid!");
-
- BufferQueue[Slot].State = BufferState.Free;
+ CpuAddr += MapFb.GetBufferOffset(Slot);
- ReleaseEvent.Handle.Set();
-
- WaitBufferFree.Set();
-
- return;
+ //TODO: Enable once the frame buffers problems are fixed.
+ //GpuAddr += MapFb.GetBufferOffset(Slot);
}
BufferQueue[Slot].State = BufferState.Acquired;
@@ -367,41 +347,28 @@ namespace Ryujinx.Core.OsHle.Services.Android
Rotate = -MathF.PI * 0.5f;
}
- lock (RenderQueueLock)
- {
- if (NvFlingerDisposed)
- {
- return;
- }
+ Renderer.SetFrameBufferTransform(ScaleX, ScaleY, Rotate, OffsX, OffsY);
- Interlocked.Increment(ref RenderQueueCount);
+ //TODO: Support double buffering here aswell, it is broken for GPU
+ //frame buffers because it seems to be completely out of sync.
+ if (Context.Ns.Gpu.Engine3d.IsFrameBufferPosition(GpuAddr))
+ {
+ //Frame buffer is rendered to by the GPU, we can just
+ //bind the frame buffer texture, it's not necessary to read anything.
+ Renderer.SetFrameBuffer(GpuAddr);
}
-
- byte* Fb = (byte*)Context.Memory.Ram + Address;
-
- Context.Ns.Gpu.Renderer.QueueAction(delegate()
+ else
{
- Context.Ns.Gpu.Renderer.SetFrameBuffer(
- Fb,
- FbWidth,
- FbHeight,
- ScaleX,
- ScaleY,
- OffsX,
- OffsY,
- Rotate);
-
- BufferQueue[Slot].State = BufferState.Free;
+ //Frame buffer is not set on the GPU registers, in this case
+ //assume that the app is manually writing to it.
+ Texture Texture = new Texture(CpuAddr, FbWidth, FbHeight);
- Interlocked.Decrement(ref RenderQueueCount);
+ byte[] Data = TextureReader.Read(Context.Memory, Texture);
- ReleaseEvent.Handle.Set();
+ Renderer.SetFrameBuffer(Data, FbWidth, FbHeight);
+ }
- lock (WaitBufferFree)
- {
- WaitBufferFree.Set();
- }
- });
+ Context.Ns.Gpu.Renderer.QueueAction(() => ReleaseBuffer(Slot));
}
private NvMap GetNvMap(ServiceCtx Context, int Slot)
@@ -420,6 +387,18 @@ namespace Ryujinx.Core.OsHle.Services.Android
return INvDrvServices.NvMaps.GetData<NvMap>(Context.Process, NvMapHandle);
}
+ private void ReleaseBuffer(int Slot)
+ {
+ BufferQueue[Slot].State = BufferState.Free;
+
+ ReleaseEvent.Handle.Set();
+
+ lock (WaitBufferFree)
+ {
+ WaitBufferFree.Set();
+ }
+ }
+
private int GetFreeSlotBlocking(int Width, int Height)
{
int Slot;
@@ -435,7 +414,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
Logging.Debug("Waiting for a free BufferQueue slot...");
- if (!KeepRunning)
+ if (Disposed)
{
break;
}
@@ -445,7 +424,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
WaitBufferFree.WaitOne();
}
- while (KeepRunning);
+ while (!Disposed);
Logging.Debug($"Found free BufferQueue slot {Slot}!");
@@ -485,26 +464,12 @@ namespace Ryujinx.Core.OsHle.Services.Android
protected virtual void Dispose(bool Disposing)
{
- if (Disposing && !NvFlingerDisposed)
+ if (Disposing && !Disposed)
{
- lock (RenderQueueLock)
- {
- NvFlingerDisposed = true;
- }
-
- //Ensure that all pending actions was sent before
- //we can safely assume that the class was disposed.
- while (RenderQueueCount > 0)
- {
- Thread.Yield();
- }
-
- Renderer.ResetFrameBuffer();
+ Disposed = true;
lock (WaitBufferFree)
{
- KeepRunning = false;
-
WaitBufferFree.Set();
}
diff --git a/Ryujinx.Graphics/Gal/GalBlendEquation.cs b/Ryujinx.Graphics/Gal/GalBlendEquation.cs
index d9f8e799..7fd4ba5f 100644
--- a/Ryujinx.Graphics/Gal/GalBlendEquation.cs
+++ b/Ryujinx.Graphics/Gal/GalBlendEquation.cs
@@ -2,10 +2,10 @@ namespace Ryujinx.Graphics.Gal
{
public enum GalBlendEquation
{
- FuncAdd = 0x8006,
- Min = 0x8007,
- Max = 0x8008,
- FuncSubtract = 0x800a,
- FuncReverseSubtract = 0x800b
+ FuncAdd = 1,
+ FuncSubtract = 2,
+ FuncReverseSubtract = 3,
+ Min = 4,
+ Max = 5
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalBlendFactor.cs b/Ryujinx.Graphics/Gal/GalBlendFactor.cs
index de7d45fd..7237c4ed 100644
--- a/Ryujinx.Graphics/Gal/GalBlendFactor.cs
+++ b/Ryujinx.Graphics/Gal/GalBlendFactor.cs
@@ -2,24 +2,24 @@ namespace Ryujinx.Graphics.Gal
{
public enum GalBlendFactor
{
- Zero = 0x4000,
- One = 0x4001,
- SrcColor = 0x4300,
- OneMinusSrcColor = 0x4301,
- SrcAlpha = 0x4302,
- OneMinusSrcAlpha = 0x4303,
- DstAlpha = 0x4304,
- OneMinusDstAlpha = 0x4305,
- DstColor = 0x4306,
- OneMinusDstColor = 0x4307,
- SrcAlphaSaturate = 0x4308,
- ConstantColor = 0xc001,
- OneMinusConstantColor = 0xc002,
- ConstantAlpha = 0xc003,
- OneMinusConstantAlpha = 0xc004,
- Src1Color = 0xc900,
- OneMinusSrc1Color = 0xc901,
- Src1Alpha = 0xc902,
- OneMinusSrc1Alpha = 0xc903
+ Zero = 0x1,
+ One = 0x2,
+ SrcColor = 0x3,
+ OneMinusSrcColor = 0x4,
+ SrcAlpha = 0x5,
+ OneMinusSrcAlpha = 0x6,
+ DstAlpha = 0x7,
+ OneMinusDstAlpha = 0x8,
+ DstColor = 0x9,
+ OneMinusDstColor = 0xa,
+ SrcAlphaSaturate = 0xb,
+ Src1Color = 0x10,
+ OneMinusSrc1Color = 0x11,
+ Src1Alpha = 0x12,
+ OneMinusSrc1Alpha = 0x13,
+ ConstantColor = 0x61,
+ OneMinusConstantColor = 0x62,
+ ConstantAlpha = 0x63,
+ OneMinusConstantAlpha = 0x64
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs
index 99534672..c30c79fb 100644
--- a/Ryujinx.Graphics/Gal/IGalRenderer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs
@@ -6,21 +6,12 @@ namespace Ryujinx.Graphics.Gal
public unsafe interface IGalRenderer
{
void QueueAction(Action ActionMthd);
+
void RunActions();
- void InitializeFrameBuffer();
- void ResetFrameBuffer();
void Render();
+
void SetWindowSize(int Width, int Height);
- void SetFrameBuffer(
- byte* Fb,
- int Width,
- int Height,
- float ScaleX,
- float ScaleY,
- float OffsX,
- float OffsY,
- float Rotate);
//Blend
void SetBlendEnable(bool Enable);
@@ -39,11 +30,17 @@ namespace Ryujinx.Graphics.Gal
GalBlendFactor FuncDstAlpha);
//Frame Buffer
- void SetFb(int FbIndex, int Width, int Height);
+ 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 BindFrameBuffer(int FbIndex);
+ void SetFrameBuffer(byte[] Data, int Width, int Height);
- void DrawFrameBuffer(int FbIndex);
+ void SetFrameBufferTransform(float SX, float SY, float Rotate, float TX, float TY);
//Rasterizer
void ClearBuffers(int RtIndex, GalClearBufferFlags Flags);
@@ -70,8 +67,8 @@ namespace Ryujinx.Graphics.Gal
void BindProgram();
//Texture
- void SetTexture(int Index, GalTexture Tex);
+ void SetTextureAndSampler(int Index, GalTexture Texture, GalTextureSampler Sampler);
- void SetSampler(int Index, GalTextureSampler Sampler);
+ void BindTexture(int Index);
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs
deleted file mode 100644
index 7e7725d6..00000000
--- a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs
+++ /dev/null
@@ -1,250 +0,0 @@
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-using System;
-
-namespace Ryujinx.Graphics.Gal.OpenGL
-{
- unsafe class FrameBuffer
- {
- public int WindowWidth { get; set; }
- public int WindowHeight { get; set; }
-
- private int VtxShaderHandle;
- private int FragShaderHandle;
- private int PrgShaderHandle;
-
- private int TexHandle;
- private int TexWidth;
- private int TexHeight;
-
- private int VaoHandle;
- private int VboHandle;
-
- private int[] Pixels;
-
- private byte* FbPtr;
-
- private object FbPtrLock;
-
- public FrameBuffer(int Width, int Height)
- {
- if (Width < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(Width));
- }
-
- if (Height < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(Height));
- }
-
- FbPtrLock = new object();
-
- TexWidth = Width;
- TexHeight = Height;
-
- WindowWidth = Width;
- WindowHeight = Height;
-
- SetupShaders();
- SetupTexture();
- SetupVertex();
- }
-
- private void SetupShaders()
- {
- VtxShaderHandle = GL.CreateShader(ShaderType.VertexShader);
- FragShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
-
- string VtxShaderSource = EmbeddedResource.GetString("GlFbVtxShader");
- string FragShaderSource = EmbeddedResource.GetString("GlFbFragShader");
-
- GL.ShaderSource(VtxShaderHandle, VtxShaderSource);
- GL.ShaderSource(FragShaderHandle, FragShaderSource);
- GL.CompileShader(VtxShaderHandle);
- GL.CompileShader(FragShaderHandle);
-
- PrgShaderHandle = GL.CreateProgram();
-
- GL.AttachShader(PrgShaderHandle, VtxShaderHandle);
- GL.AttachShader(PrgShaderHandle, FragShaderHandle);
- GL.LinkProgram(PrgShaderHandle);
- GL.UseProgram(PrgShaderHandle);
-
- int TexUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "tex");
-
- GL.Uniform1(TexUniformLocation, 0);
-
- int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size");
-
- GL.Uniform2(WindowSizeUniformLocation, new Vector2(1280.0f, 720.0f));
- }
-
- private void SetupTexture()
- {
- Pixels = new int[TexWidth * TexHeight];
-
- if (TexHandle == 0)
- {
- TexHandle = GL.GenTexture();
- }
-
- GL.BindTexture(TextureTarget.Texture2D, TexHandle);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
- GL.TexImage2D(TextureTarget.Texture2D,
- 0,
- PixelInternalFormat.Rgba,
- TexWidth,
- TexHeight,
- 0,
- PixelFormat.Rgba,
- PixelType.UnsignedByte,
- IntPtr.Zero);
- }
-
- private void SetupVertex()
- {
- VaoHandle = GL.GenVertexArray();
- VboHandle = GL.GenBuffer();
-
- float[] Buffer = new float[]
- {
- -1, 1, 0, 0,
- 1, 1, 1, 0,
- -1, -1, 0, 1,
- 1, -1, 1, 1
- };
-
- IntPtr Length = new IntPtr(Buffer.Length * 4);
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
- GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
- GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
-
- GL.BindVertexArray(VaoHandle);
-
- GL.EnableVertexAttribArray(0);
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
-
- GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 16, 0);
-
- GL.EnableVertexAttribArray(1);
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
-
- GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 16, 8);
-
- GL.BindVertexArray(0);
- }
-
- public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform, Vector2 Offs)
- {
- if (Fb == null)
- {
- throw new ArgumentNullException(nameof(Fb));
- }
-
- if (Width < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(Width));
- }
-
- if (Height < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(Height));
- }
-
- lock (FbPtrLock)
- {
- FbPtr = Fb;
- }
-
- if (Width != TexWidth ||
- Height != TexHeight)
- {
- TexWidth = Width;
- TexHeight = Height;
-
- SetupTexture();
- }
-
- GL.UseProgram(PrgShaderHandle);
-
- int TransformUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "transform");
-
- GL.UniformMatrix2(TransformUniformLocation, false, ref Transform);
-
- int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size");
-
- GL.Uniform2(WindowSizeUniformLocation, new Vector2(WindowWidth, WindowHeight));
-
- int OffsetUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "offset");
-
- GL.Uniform2(OffsetUniformLocation, Offs);
- }
-
- public void Reset()
- {
- lock (FbPtrLock)
- {
- FbPtr = null;
- }
- }
-
- public void Render()
- {
- lock (FbPtrLock)
- {
- if (FbPtr == null)
- {
- return;
- }
-
- for (int Y = 0; Y < TexHeight; Y++)
- for (int X = 0; X < TexWidth; X++)
- {
- Pixels[X + Y * TexWidth] = *((int*)(FbPtr + GetSwizzleOffset(X, Y)));
- }
- }
-
- GL.BindTexture(TextureTarget.Texture2D, TexHandle);
- GL.TexSubImage2D(TextureTarget.Texture2D,
- 0,
- 0,
- 0,
- TexWidth,
- TexHeight,
- PixelFormat.Rgba,
- PixelType.UnsignedByte,
- Pixels);
-
- GL.ActiveTexture(TextureUnit.Texture0);
-
- GL.BindVertexArray(VaoHandle);
-
- GL.UseProgram(PrgShaderHandle);
-
- GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
- }
-
- private int GetSwizzleOffset(int X, int Y)
- {
- int Pos;
-
- Pos = (Y & 0x7f) >> 4;
- Pos += (X >> 4) << 3;
- Pos += (Y >> 7) * ((TexWidth >> 4) << 3);
- Pos *= 1024;
- Pos += ((Y & 0xf) >> 3) << 9;
- Pos += ((X & 0xf) >> 3) << 8;
- Pos += ((Y & 0x7) >> 1) << 6;
- Pos += ((X & 0x7) >> 2) << 5;
- Pos += ((Y & 0x1) >> 0) << 4;
- Pos += ((X & 0x3) >> 0) << 2;
-
- return Pos;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
index 17bf6291..4cc0a039 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
@@ -127,17 +127,72 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public static BlendEquationMode GetBlendEquation(GalBlendEquation BlendEquation)
{
- return (BlendEquationMode)BlendEquation;
+ switch (BlendEquation)
+ {
+ case GalBlendEquation.FuncAdd: return BlendEquationMode.FuncAdd;
+ case GalBlendEquation.FuncSubtract: return BlendEquationMode.FuncSubtract;
+ case GalBlendEquation.FuncReverseSubtract: return BlendEquationMode.FuncReverseSubtract;
+ case GalBlendEquation.Min: return BlendEquationMode.Min;
+ case GalBlendEquation.Max: return BlendEquationMode.Max;
+ }
+
+ throw new ArgumentException(nameof(BlendEquation));
}
public static BlendingFactorSrc GetBlendFactorSrc(GalBlendFactor BlendFactor)
{
- return (BlendingFactorSrc)(BlendFactor - 0x4000);
+ switch (BlendFactor)
+ {
+ case GalBlendFactor.Zero: return BlendingFactorSrc.Zero;
+ case GalBlendFactor.One: return BlendingFactorSrc.One;
+ case GalBlendFactor.SrcColor: return BlendingFactorSrc.SrcColor;
+ case GalBlendFactor.OneMinusSrcColor: return BlendingFactorSrc.OneMinusSrcColor;
+ case GalBlendFactor.DstColor: return BlendingFactorSrc.DstColor;
+ case GalBlendFactor.OneMinusDstColor: return BlendingFactorSrc.OneMinusDstColor;
+ case GalBlendFactor.SrcAlpha: return BlendingFactorSrc.SrcAlpha;
+ case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactorSrc.OneMinusSrcAlpha;
+ case GalBlendFactor.DstAlpha: return BlendingFactorSrc.DstAlpha;
+ case GalBlendFactor.OneMinusDstAlpha: return BlendingFactorSrc.OneMinusDstAlpha;
+ case GalBlendFactor.ConstantColor: return BlendingFactorSrc.ConstantColor;
+ case GalBlendFactor.OneMinusConstantColor: return BlendingFactorSrc.OneMinusConstantColor;
+ case GalBlendFactor.ConstantAlpha: return BlendingFactorSrc.ConstantAlpha;
+ case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactorSrc.OneMinusConstantAlpha;
+ case GalBlendFactor.SrcAlphaSaturate: return BlendingFactorSrc.SrcAlphaSaturate;
+ case GalBlendFactor.Src1Color: return BlendingFactorSrc.Src1Color;
+ case GalBlendFactor.OneMinusSrc1Color: return BlendingFactorSrc.OneMinusSrc1Color;
+ case GalBlendFactor.Src1Alpha: return BlendingFactorSrc.Src1Alpha;
+ case GalBlendFactor.OneMinusSrc1Alpha: return BlendingFactorSrc.OneMinusSrc1Alpha;
+ }
+
+ throw new ArgumentException(nameof(BlendFactor));
}
public static BlendingFactorDest GetBlendFactorDst(GalBlendFactor BlendFactor)
{
- return (BlendingFactorDest)(BlendFactor - 0x4000);
+ switch (BlendFactor)
+ {
+ case GalBlendFactor.Zero: return BlendingFactorDest.Zero;
+ case GalBlendFactor.One: return BlendingFactorDest.One;
+ case GalBlendFactor.SrcColor: return BlendingFactorDest.SrcColor;
+ case GalBlendFactor.OneMinusSrcColor: return BlendingFactorDest.OneMinusSrcColor;
+ case GalBlendFactor.DstColor: return BlendingFactorDest.DstColor;
+ case GalBlendFactor.OneMinusDstColor: return BlendingFactorDest.OneMinusDstColor;
+ case GalBlendFactor.SrcAlpha: return BlendingFactorDest.SrcAlpha;
+ case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactorDest.OneMinusSrcAlpha;
+ case GalBlendFactor.DstAlpha: return BlendingFactorDest.DstAlpha;
+ case GalBlendFactor.OneMinusDstAlpha: return BlendingFactorDest.OneMinusDstAlpha;
+ case GalBlendFactor.ConstantColor: return BlendingFactorDest.ConstantColor;
+ case GalBlendFactor.OneMinusConstantColor: return BlendingFactorDest.OneMinusConstantColor;
+ case GalBlendFactor.ConstantAlpha: return BlendingFactorDest.ConstantAlpha;
+ case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactorDest.OneMinusConstantAlpha;
+ case GalBlendFactor.SrcAlphaSaturate: return BlendingFactorDest.SrcAlphaSaturate;
+ case GalBlendFactor.Src1Color: return BlendingFactorDest.Src1Color;
+ case GalBlendFactor.OneMinusSrc1Color: return BlendingFactorDest.OneMinusSrc1Color;
+ case GalBlendFactor.Src1Alpha: return BlendingFactorDest.Src1Alpha;
+ case GalBlendFactor.OneMinusSrc1Alpha: return BlendingFactorDest.OneMinusSrc1Alpha;
+ }
+
+ throw new ArgumentException(nameof(BlendFactor));
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
index f9c42ae0..818af3b3 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
@@ -1,16 +1,30 @@
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
+using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.OpenGL
{
class OGLFrameBuffer
{
- private struct FrameBuffer
+ private class FrameBuffer
{
- public int FbHandle;
- public int RbHandle;
- public int TexHandle;
+ public int Width { get; set; }
+ public int Height { get; set; }
+
+ public int Handle { get; private set; }
+ public int RbHandle { get; private set; }
+ public int TexHandle { get; private set; }
+
+ public FrameBuffer(int Width, int Height)
+ {
+ this.Width = Width;
+ this.Height = Height;
+
+ Handle = GL.GenFramebuffer();
+ RbHandle = GL.GenRenderbuffer();
+ TexHandle = GL.GenTexture();
+ }
}
private struct ShaderProgram
@@ -20,83 +34,175 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public int FpHandle;
}
- private FrameBuffer[] Fbs;
+ private Dictionary<long, FrameBuffer> Fbs;
private ShaderProgram Shader;
private bool IsInitialized;
+ private int RawFbTexWidth;
+ private int RawFbTexHeight;
+ private int RawFbTexHandle;
+
+ private int CurrFbHandle;
+ private int CurrTexHandle;
+
private int VaoHandle;
private int VboHandle;
public OGLFrameBuffer()
{
- Fbs = new FrameBuffer[16];
+ Fbs = new Dictionary<long, FrameBuffer>();
Shader = new ShaderProgram();
}
- public void Set(int Index, int Width, int Height)
+ public void Create(long Tag, int Width, int Height)
{
- if (Fbs[Index].FbHandle != 0)
+ if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
{
- return;
- }
+ if (Fb.Width != Width ||
+ Fb.Height != Height)
+ {
+ SetupTexture(Fb.TexHandle, Width, Height);
- Fbs[Index].FbHandle = GL.GenFramebuffer();
- Fbs[Index].RbHandle = GL.GenRenderbuffer();
- Fbs[Index].TexHandle = GL.GenTexture();
+ Fb.Width = Width;
+ Fb.Height = Height;
+ }
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fbs[Index].FbHandle);
+ return;
+ }
- GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fbs[Index].RbHandle);
+ Fb = new FrameBuffer(Width, Height);
- GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.Depth24Stencil8, 1280, 720);
+ SetupTexture(Fb.TexHandle, Width, Height);
- GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, Fbs[Index].RbHandle);
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
- GL.BindTexture(TextureTarget.Texture2D, Fbs[Index].TexHandle);
+ GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fb.RbHandle);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+ GL.RenderbufferStorage(
+ RenderbufferTarget.Renderbuffer,
+ RenderbufferStorage.Depth24Stencil8,
+ Width,
+ Height);
- GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 1280, 720, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
+ GL.FramebufferRenderbuffer(
+ FramebufferTarget.Framebuffer,
+ FramebufferAttachment.DepthStencilAttachment,
+ RenderbufferTarget.Renderbuffer,
+ Fb.RbHandle);
- GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, Fbs[Index].TexHandle, 0);
+ GL.FramebufferTexture(
+ FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ Fb.TexHandle,
+ 0);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
+
+ Fbs.Add(Tag, Fb);
}
- public void Bind(int Index)
+ public void Bind(long Tag)
{
- if (Fbs[Index].FbHandle == 0)
+ if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
{
- return;
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
+
+ CurrFbHandle = Fb.Handle;
}
+ }
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fbs[Index].FbHandle);
+ public void BindTexture(long Tag, int Index)
+ {
+ if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
+ {
+ GL.ActiveTexture(TextureUnit.Texture0 + Index);
+
+ GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
+ }
}
- public void Draw(int Index)
+ public void Set(long Tag)
{
- if (Fbs[Index].FbHandle == 0)
+ if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
{
- return;
+ CurrTexHandle = Fb.TexHandle;
}
+ }
- EnsureInitialized();
+ public void Set(byte[] Data, int Width, int Height)
+ {
+ if (RawFbTexHandle == 0)
+ {
+ RawFbTexHandle = GL.GenTexture();
+ }
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
+ if (RawFbTexWidth != Width ||
+ RawFbTexHeight != Height)
+ {
+ SetupTexture(RawFbTexHandle, Width, Height);
- GL.BindTexture(TextureTarget.Texture2D, Fbs[Index].TexHandle);
+ RawFbTexWidth = Width;
+ RawFbTexHeight = Height;
+ }
GL.ActiveTexture(TextureUnit.Texture0);
- GL.BindVertexArray(VaoHandle);
+ GL.BindTexture(TextureTarget.Texture2D, RawFbTexHandle);
+
+ (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
+
+ GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, Format, Type, Data);
+
+ CurrTexHandle = RawFbTexHandle;
+ }
+
+ public void SetTransform(Matrix2 Transform, Vector2 Offs)
+ {
+ EnsureInitialized();
+
+ int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);
GL.UseProgram(Shader.Handle);
- GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
+ int TransformUniformLocation = GL.GetUniformLocation(Shader.Handle, "transform");
+
+ GL.UniformMatrix2(TransformUniformLocation, false, ref Transform);
+
+ int OffsetUniformLocation = GL.GetUniformLocation(Shader.Handle, "offset");
+
+ GL.Uniform2(OffsetUniformLocation, ref Offs);
+
+ GL.UseProgram(CurrentProgram);
+ }
+
+ public void Render()
+ {
+ if (CurrTexHandle != 0)
+ {
+ EnsureInitialized();
+
+ GL.ActiveTexture(TextureUnit.Texture0);
+
+ GL.BindTexture(TextureTarget.Texture2D, CurrTexHandle);
+
+ int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram);
+
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
+
+ GL.BindVertexArray(VaoHandle);
+
+ GL.UseProgram(Shader.Handle);
+
+ GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
+
+ //Restore the original state.
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, CurrFbHandle);
+
+ GL.UseProgram(CurrentProgram);
+ }
}
private void EnsureInitialized()
@@ -130,7 +236,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.LinkProgram(Shader.Handle);
GL.UseProgram(Shader.Handle);
- Matrix2 Transform = Matrix2.CreateScale(1, -1);
+ Matrix2 Transform = Matrix2.Identity;
int TexUniformLocation = GL.GetUniformLocation(Shader.Handle, "tex");
@@ -178,5 +284,32 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 16, 8);
}
+
+ private void SetupTexture(int Handle, int Width, int Height)
+ {
+ GL.BindTexture(TextureTarget.Texture2D, Handle);
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+
+ (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
+
+ const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
+
+ const int Level = 0;
+ const int Border = 0;
+
+ GL.TexImage2D(
+ TextureTarget.Texture2D,
+ Level,
+ InternalFmt,
+ Width,
+ Height,
+ Border,
+ Format,
+ Type,
+ IntPtr.Zero);
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
index b7c8999e..9ea25056 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
@@ -15,10 +15,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
GL.ActiveTexture(TextureUnit.Texture0 + Index);
- int Handle = EnsureTextureInitialized(Index);
-
- GL.BindTexture(TextureTarget.Texture2D, Handle);
+ Bind(Index);
+ const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0;
if (IsCompressedTextureFormat(Texture.Format))
@@ -27,7 +26,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.CompressedTexImage2D(
TextureTarget.Texture2D,
- 0,
+ Level,
InternalFmt,
Texture.Width,
Texture.Height,
@@ -39,27 +38,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
- (PixelFormat, PixelType) Format = OGLEnumConverter.GetTextureFormat(Texture.Format);
+ (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(Texture.Format);
GL.TexImage2D(
TextureTarget.Texture2D,
- 0,
+ Level,
InternalFmt,
Texture.Width,
Texture.Height,
Border,
- Format.Item1,
- Format.Item2,
+ Format,
+ Type,
Texture.Data);
}
}
- public void Set(int Index, GalTextureSampler Sampler)
+ public void Bind(int Index)
{
int Handle = EnsureTextureInitialized(Index);
GL.BindTexture(TextureTarget.Texture2D, Handle);
+ }
+ public static void Set(GalTextureSampler Sampler)
+ {
int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
index 0b7bf92a..b3ccae5f 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
@@ -19,8 +19,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private ConcurrentQueue<Action> ActionsQueue;
- private FrameBuffer FbRenderer;
-
public OpenGLRenderer()
{
Blend = new OGLBlend();
@@ -36,16 +34,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
ActionsQueue = new ConcurrentQueue<Action>();
}
- public void InitializeFrameBuffer()
- {
- FbRenderer = new FrameBuffer(1280, 720);
- }
-
- public void ResetFrameBuffer()
- {
- FbRenderer.Reset();
- }
-
public void QueueAction(Action ActionMthd)
{
ActionsQueue.Enqueue(ActionMthd);
@@ -63,33 +51,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Render()
{
- FbRenderer.Render();
+ FrameBuffer.Render();
}
public void SetWindowSize(int Width, int Height)
{
- FbRenderer.WindowWidth = Width;
- FbRenderer.WindowHeight = Height;
- }
-
- public unsafe void SetFrameBuffer(
- byte* Fb,
- int Width,
- int Height,
- float ScaleX,
- float ScaleY,
- float OffsX,
- float OffsY,
- float Rotate)
- {
- Matrix2 Transform;
-
- Transform = Matrix2.CreateScale(ScaleX, ScaleY);
- Transform *= Matrix2.CreateRotation(Rotate);
-
- Vector2 Offs = new Vector2(OffsX, OffsY);
-
- FbRenderer.Set(Fb, Width, Height, Transform, Offs);
+ //TODO
}
public void SetBlendEnable(bool Enable)
@@ -132,19 +99,46 @@ namespace Ryujinx.Graphics.Gal.OpenGL
});
}
- public void SetFb(int FbIndex, int Width, int Height)
+ public void CreateFrameBuffer(long Tag, int Width, int Height)
{
- ActionsQueue.Enqueue(() => FrameBuffer.Set(FbIndex, Width, Height));
+ ActionsQueue.Enqueue(() => FrameBuffer.Create(Tag, Width, Height));
}
- public void BindFrameBuffer(int FbIndex)
+ public void BindFrameBuffer(long Tag)
{
- ActionsQueue.Enqueue(() => FrameBuffer.Bind(FbIndex));
+ ActionsQueue.Enqueue(() => FrameBuffer.Bind(Tag));
}
- public void DrawFrameBuffer(int FbIndex)
+ public void BindFrameBufferTexture(long Tag, int Index, GalTextureSampler Sampler)
{
- ActionsQueue.Enqueue(() => FrameBuffer.Draw(FbIndex));
+ 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 ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
@@ -239,14 +233,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
ActionsQueue.Enqueue(() => Shader.BindProgram());
}
- public void SetTexture(int Index, GalTexture Tex)
+ public void SetTextureAndSampler(int Index, GalTexture Texture, GalTextureSampler Sampler)
{
- ActionsQueue.Enqueue(() => Texture.Set(Index, Tex));
+ ActionsQueue.Enqueue(() =>
+ {
+ this.Texture.Set(Index, Texture);
+
+ OGLTexture.Set(Sampler);
+ });
}
- public void SetSampler(int Index, GalTextureSampler Sampler)
+ public void BindTexture(int Index)
{
- ActionsQueue.Enqueue(() => Texture.Set(Index, Sampler));
+ ActionsQueue.Enqueue(() => Texture.Bind(Index));
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index e155e475..82dbff9f 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -81,7 +81,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public GlslProgram Decompile(int[] Code, GalShaderType ShaderType)
{
- ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0, ShaderType);
+ ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0);
ShaderIrNode[] Nodes = Block.GetNodes();
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
index 6553cfcf..33f58231 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
@@ -74,11 +74,9 @@ namespace Ryujinx.Graphics.Gal.Shader
for (int Ch = 0; Ch < 4; Ch++)
{
- ShaderIrOperGpr Dst = (Ch >> 1) != 0
- ? GetOperGpr28(OpCode)
- : GetOperGpr0 (OpCode);
-
- Dst.Index += Ch & 1;
+ //Assign it to a temp because the destination registers
+ //may be used as texture coord input aswell.
+ ShaderIrOperGpr Dst = new ShaderIrOperGpr(0x100 + Ch);
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);
@@ -86,6 +84,19 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode));
}
+
+ for (int Ch = 0; Ch < 4; Ch++)
+ {
+ ShaderIrOperGpr Src = new ShaderIrOperGpr(0x100 + Ch);
+
+ ShaderIrOperGpr Dst = (Ch >> 1) != 0
+ ? GetOperGpr28(OpCode)
+ : GetOperGpr0 (OpCode);
+
+ Dst.Index += Ch & 1;
+
+ Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Src), OpCode));
+ }
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
index 7bebea62..e44d5b7d 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
@@ -2,7 +2,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{
static class ShaderDecoder
{
- public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset, GalShaderType ShaderType)
+ public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset)
{
ShaderIrBlock Block = new ShaderIrBlock();
@@ -37,8 +37,6 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- Block.RunOptimizationPasses(ShaderType);
-
return Block;
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
index 1a96d3be..c920d9fa 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
@@ -16,11 +16,6 @@ namespace Ryujinx.Graphics.Gal.Shader
Nodes.Add(Node);
}
- public void RunOptimizationPasses(GalShaderType ShaderType)
- {
- ShaderOptExprProp.Optimize(Nodes, ShaderType);
- }
-
public ShaderIrNode[] GetNodes()
{
return Nodes.ToArray();
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs
deleted file mode 100644
index 9ce7cbe3..00000000
--- a/Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs
+++ /dev/null
@@ -1,366 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Gal.Shader
-{
- static class ShaderOptExprProp
- {
- private struct UseSite
- {
- public ShaderIrNode Parent { get; private set; }
- public ShaderIrCond Cond { get; private set; }
-
- public int UseIndex { get; private set; }
-
- public int OperIndex { get; private set; }
-
- public UseSite(
- ShaderIrNode Parent,
- ShaderIrCond Cond,
- int UseIndex,
- int OperIndex)
- {
- this.Parent = Parent;
- this.Cond = Cond;
- this.UseIndex = UseIndex;
- this.OperIndex = OperIndex;
- }
- }
-
- private class RegUse
- {
- public ShaderIrAsg Asg { get; private set; }
-
- public int AsgIndex { get; private set; }
-
- public int LastSiteIndex { get; private set; }
-
- public ShaderIrCond Cond { get; private set; }
-
- private List<UseSite> Sites;
-
- public RegUse()
- {
- Sites = new List<UseSite>();
- }
-
- public void AddUseSite(UseSite Site)
- {
- if (LastSiteIndex < Site.UseIndex)
- {
- LastSiteIndex = Site.UseIndex;
- }
-
- Sites.Add(Site);
- }
-
- public bool TryPropagate()
- {
- //This happens when a untiliazied register is used,
- //this usually indicates a decoding error, but may also
- //be caused by bogus programs (?). In any case, we just
- //keep the unitialized access and avoid trying to propagate
- //the expression (since we can't propagate what doesn't yet exist).
- if (Asg == null)
- {
- return false;
- }
-
- if (Cond != null)
- {
- //If the assignment is conditional, we can only propagate
- //to the use sites that shares the same condition of the assignment.
- foreach (UseSite Site in Sites)
- {
- if (!IsSameCondition(Cond, Site.Cond))
- {
- return false;
- }
- }
- }
-
- if (Sites.Count > 0)
- {
- foreach (UseSite Site in Sites)
- {
- if (Site.Parent is ShaderIrCond Cond)
- {
- switch (Site.OperIndex)
- {
- case 0: Cond.Pred = Asg.Src; break;
- case 1: Cond.Child = Asg.Src; break;
-
- default: throw new InvalidOperationException();
- }
- }
- else if (Site.Parent is ShaderIrOp Op)
- {
- switch (Site.OperIndex)
- {
- case 0: Op.OperandA = Asg.Src; break;
- case 1: Op.OperandB = Asg.Src; break;
- case 2: Op.OperandC = Asg.Src; break;
-
- default: throw new InvalidOperationException();
- }
- }
- else if (Site.Parent is ShaderIrAsg SiteAsg)
- {
- SiteAsg.Src = Asg.Src;
- }
- else
- {
- throw new InvalidOperationException();
- }
- }
- }
-
- return true;
- }
-
- public void SetNewAsg(ShaderIrAsg Asg, int AsgIndex, ShaderIrCond Cond)
- {
- this.Asg = Asg;
- this.AsgIndex = AsgIndex;
- this.Cond = Cond;
-
- LastSiteIndex = 0;
-
- Sites.Clear();
- }
- }
-
- public static void Optimize(List<ShaderIrNode> Nodes, GalShaderType ShaderType)
- {
- Dictionary<int, RegUse> Uses = new Dictionary<int, RegUse>();
-
- RegUse GetUse(int Key)
- {
- RegUse Use;
-
- if (!Uses.TryGetValue(Key, out Use))
- {
- Use = new RegUse();
-
- Uses.Add(Key, Use);
- }
-
- return Use;
- }
-
- int GetGprKey(int GprIndex)
- {
- return GprIndex;
- }
-
- int GetPredKey(int PredIndex)
- {
- return PredIndex | 0x10000000;
- }
-
- RegUse GetGprUse(int GprIndex)
- {
- return GetUse(GetGprKey(GprIndex));
- }
-
- RegUse GetPredUse(int PredIndex)
- {
- return GetUse(GetPredKey(PredIndex));
- }
-
- void RemoveUse(RegUse Use)
- {
- if (!Nodes.Remove((ShaderIrNode)Use.Cond ?? Use.Asg))
- {
- throw new InvalidOperationException();
- }
- }
-
- void FindRegUses(
- List<(int, UseSite)> UseList,
- ShaderIrNode Parent,
- ShaderIrNode Node,
- ShaderIrCond CondNode,
- int UseIndex,
- int OperIndex = 0)
- {
- if (Node is ShaderIrAsg Asg)
- {
- FindRegUses(UseList, Asg, Asg.Src, CondNode, UseIndex);
- }
- else if (Node is ShaderIrCond Cond)
- {
- FindRegUses(UseList, Cond, Cond.Pred, CondNode, UseIndex, 0);
- FindRegUses(UseList, Cond, Cond.Child, CondNode, UseIndex, 1);
- }
- else if (Node is ShaderIrOp Op)
- {
- FindRegUses(UseList, Op, Op.OperandA, CondNode, UseIndex, 0);
- FindRegUses(UseList, Op, Op.OperandB, CondNode, UseIndex, 1);
- FindRegUses(UseList, Op, Op.OperandC, CondNode, UseIndex, 2);
- }
- else if (Node is ShaderIrOperGpr Gpr && !Gpr.IsConst)
- {
- UseList.Add((GetGprKey(Gpr.Index), new UseSite(Parent, CondNode, UseIndex, OperIndex)));
- }
- else if (Node is ShaderIrOperPred Pred)
- {
- UseList.Add((GetPredKey(Pred.Index), new UseSite(Parent, CondNode, UseIndex, OperIndex)));
- }
- }
-
- void TryAddRegUseSite(ShaderIrNode Node, ShaderIrCond CondNode, int UseIndex)
- {
- List<(int, UseSite)> UseList = new List<(int, UseSite)>();
-
- FindRegUses(UseList, null, Node, CondNode, UseIndex);
-
- foreach ((int Key, UseSite Site) in UseList)
- {
- GetUse(Key).AddUseSite(Site);
- }
- }
-
- bool TryPropagate(RegUse Use)
- {
- //We can only propagate if the registers that the expression depends
- //on weren't assigned after the original expression assignment
- //to a register took place. We traverse the expression tree to find
- //all registers being used, if any of those registers was assigned
- //after the assignment to be propagated, then we can't propagate.
- if (Use?.Asg == null)
- {
- return false;
- }
-
- List<(int, UseSite)> UseList = new List<(int, UseSite)>();
-
- if (Use.Cond != null)
- {
- FindRegUses(UseList, null, Use.Cond, null, 0);
- }
- else
- {
- FindRegUses(UseList, Use.Asg, Use.Asg.Src, null, 0);
- }
-
- foreach ((int Key, UseSite Site) in UseList)
- {
- //TODO: Build an assignment list inside RegUse,
- //and check if there is an assignment inside the
- //range of Use.AsgIndex and Use.LastSiteIndex,
- //and if that's the case, then we should return false.
- //The current method is too conservative.
- if (GetUse(Key).AsgIndex >= Use.AsgIndex)
- {
- return false;
- }
- }
-
- return Use.TryPropagate();
- }
-
- for (int Index = 0, IterCount = 0; Index < Nodes.Count; Index++, IterCount++)
- {
- ShaderIrNode Node = Nodes[Index];
-
- ShaderIrCond CondNode = null;
-
- if (Node is ShaderIrCond)
- {
- CondNode = (ShaderIrCond)Node;
- }
-
- TryAddRegUseSite(Node, CondNode, IterCount);;
-
- while (Node is ShaderIrCond Cond)
- {
- Node = Cond.Child;
- }
-
- if (!(Node is ShaderIrAsg Asg))
- {
- continue;
- }
-
- RegUse Use = null;
-
- if (Asg.Dst is ShaderIrOperGpr Gpr && !Gpr.IsConst)
- {
- Use = GetGprUse(Gpr.Index);
- }
- else if (Asg.Dst is ShaderIrOperPred Pred)
- {
- Use = GetPredUse(Pred.Index);
- }
-
- bool CanRemoveAsg = CondNode == null;
-
- CanRemoveAsg |= IsSameCondition(CondNode, Use?.Cond);
-
- if (CanRemoveAsg && TryPropagate(Use))
- {
- RemoveUse(Use);
-
- //Note: Only decrement if the removal was successful.
- //RemoveUse throws when this is not the case so we should be good.
- Index--;
- }
-
- //All nodes inside conditional nodes can't be propagated,
- //as we don't even know if they will be executed to begin with.
- Use?.SetNewAsg(Asg, IterCount, CondNode);
- }
-
- foreach (RegUse Use in Uses.Values)
- {
- //Gprs 0-3 are the color output on fragment shaders,
- //so we can't remove the last assignments to those registers.
- if (ShaderType == GalShaderType.Fragment)
- {
- if (Use.Asg?.Dst is ShaderIrOperGpr Gpr && Gpr.Index < 4)
- {
- continue;
- }
- }
-
- if (TryPropagate(Use))
- {
- RemoveUse(Use);
- }
- }
- }
-
- private static bool IsSameCondition(ShaderIrCond CondA, ShaderIrCond CondB)
- {
- if (CondA == null || CondB == null)
- {
- return CondA == CondB;
- }
-
- if (CondA.Not != CondB.Not)
- {
- return false;
- }
-
- if (CondA.Pred is ShaderIrOperPred PredA)
- {
- if (!(CondB.Pred is ShaderIrOperPred PredB))
- {
- return false;
- }
-
- if (PredA.Index != PredB.Index)
- {
- return false;
- }
- }
- else if (CondA.Pred != CondB.Pred)
- {
- return false;
- }
-
- return true;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gpu/NsGpu.cs b/Ryujinx.Graphics/Gpu/NsGpu.cs
index 57380502..9a2e9012 100644
--- a/Ryujinx.Graphics/Gpu/NsGpu.cs
+++ b/Ryujinx.Graphics/Gpu/NsGpu.cs
@@ -9,9 +9,9 @@ namespace Ryujinx.Graphics.Gpu
internal NsGpuMemoryMgr MemoryMgr { get; private set; }
- public NvGpuFifo Fifo;
+ public NvGpuFifo Fifo { get; private set; }
- internal NvGpuEngine3d Engine3d;
+ public NvGpuEngine3d Engine3d { get; private set; }
private Thread FifoProcessing;
@@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gpu
KeepRunning = true;
- FifoProcessing = new Thread(ProcessFifo);
+ FifoProcessing = new Thread(ProcessFifo);
FifoProcessing.Start();
}
diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs
index f4486f46..1142e4aa 100644
--- a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs
+++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs
@@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu
{
- class NvGpuEngine3d : INvGpuEngine
+ public class NvGpuEngine3d : INvGpuEngine
{
public int[] Registers { get; private set; }
@@ -20,9 +20,9 @@ namespace Ryujinx.Graphics.Gpu
public int Size;
}
- private ConstBuffer[] Cbs;
+ private ConstBuffer[] ConstBuffers;
- private bool HasDataToRender;
+ private HashSet<long> FrameBuffers;
public NvGpuEngine3d(NsGpu Gpu)
{
@@ -48,7 +48,9 @@ namespace Ryujinx.Graphics.Gpu
AddMethod(0x8e4, 16, 1, CbData);
AddMethod(0x904, 1, 1, CbBind);
- Cbs = new ConstBuffer[18];
+ ConstBuffers = new ConstBuffer[18];
+
+ FrameBuffers = new HashSet<long>();
}
public void CallMethod(AMemory Memory, NsGpuPBEntry PBEntry)
@@ -76,19 +78,10 @@ namespace Ryujinx.Graphics.Gpu
UploadTextures(Memory, Tags);
UploadUniforms(Memory);
UploadVertexArrays(Memory);
-
- HasDataToRender = true;
}
private void ClearBuffers(AMemory Memory, NsGpuPBEntry PBEntry)
{
- if (HasDataToRender)
- {
- HasDataToRender = false;
-
- Gpu.Renderer.DrawFrameBuffer(0);
- }
-
int Arg0 = PBEntry.Arguments[0];
int FbIndex = (Arg0 >> 6) & 0xf;
@@ -99,16 +92,23 @@ namespace Ryujinx.Graphics.Gpu
SetFrameBuffer(0);
- Gpu.Renderer.ClearBuffers(Layer, Flags);
+ //TODO: Enable this once the frame buffer problems are fixed.
+ //Gpu.Renderer.ClearBuffers(Layer, Flags);
}
private void SetFrameBuffer(int FbIndex)
{
- int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
- int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
+ long Address = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + FbIndex * 0x10);
+
+ FrameBuffers.Add(Address);
+
+ int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
+ int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
- Gpu.Renderer.SetFb(FbIndex, Width, Height);
- Gpu.Renderer.BindFrameBuffer(FbIndex);
+ //Note: Using the Width/Height results seems to give incorrect results.
+ //Maybe the size of all frame buffers is hardcoded to screen size? This seems unlikely.
+ Gpu.Renderer.CreateFrameBuffer(Address, 1280, 720);
+ Gpu.Renderer.BindFrameBuffer(Address);
}
private long[] UploadShaders(AMemory Memory)
@@ -167,23 +167,24 @@ namespace Ryujinx.Graphics.Gpu
private void SetAlphaBlending()
{
- bool BlendEnableMaster = (ReadRegister(NvGpuEngine3dReg.BlendEnableMaster) & 1) != 0;
+ //TODO: Support independent blend properly.
+ bool Enable = (ReadRegister(NvGpuEngine3dReg.IBlendEnable) & 1) != 0;
- Gpu.Renderer.SetBlendEnable(BlendEnableMaster);
+ Gpu.Renderer.SetBlendEnable(Enable);
- bool BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.BlendSeparateAlpha) & 1) != 0;
+ bool BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.IBlendNSeparateAlpha) & 1) != 0;
- GalBlendEquation EquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.BlendEquationRgb);
+ GalBlendEquation EquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb);
- GalBlendFactor FuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.BlendFuncSrcRgb);
- GalBlendFactor FuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.BlendFuncDstRgb);
+ GalBlendFactor FuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb);
+ GalBlendFactor FuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstRgb);
if (BlendSeparateAlpha)
{
- GalBlendEquation EquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.BlendEquationAlpha);
+ GalBlendEquation EquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationAlpha);
- GalBlendFactor FuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.BlendFuncSrcAlpha);
- GalBlendFactor FuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.BlendFuncDstAlpha);
+ GalBlendFactor FuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
+ GalBlendFactor FuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
Gpu.Renderer.SetBlendSeparate(
EquationRgb,
@@ -205,11 +206,13 @@ namespace Ryujinx.Graphics.Gpu
int TextureCbIndex = ReadRegister(NvGpuEngine3dReg.TextureCbIndex);
- long BasePosition = Cbs[TextureCbIndex].Position;
+ long BasePosition = ConstBuffers[TextureCbIndex].Position;
- long Size = (uint)Cbs[TextureCbIndex].Size;
+ long Size = (uint)ConstBuffers[TextureCbIndex].Size;
- int TexIndex = 0;
+ //Note: On the emulator renderer, Texture Unit 0 is
+ //reserved for drawing the frame buffer.
+ int TexIndex = 1;
for (int Index = 0; Index < Tags.Length; Index++)
{
@@ -241,8 +244,25 @@ namespace Ryujinx.Graphics.Gpu
TicPosition += TicIndex * 0x20;
TscPosition += TscIndex * 0x20;
- Gpu.Renderer.SetTexture(TexIndex, TextureFactory.MakeTexture(Gpu, Memory, TicPosition));
- Gpu.Renderer.SetSampler(TexIndex, TextureFactory.MakeSampler(Gpu, Memory, TscPosition));
+ GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Memory, TscPosition);
+
+ long TextureAddress = Memory.ReadInt64(TicPosition + 4) & 0xffffffffffff;
+
+ if (FrameBuffers.Contains(TextureAddress))
+ {
+ //This texture is a frame buffer texture,
+ //we shouldn't read anything from memory and bind
+ //the frame buffer texture instead, since we're not
+ //really writing anything to memory.
+ Gpu.Renderer.BindFrameBufferTexture(TextureAddress, TexIndex, Sampler);
+ }
+ else
+ {
+ GalTexture Texture = TextureFactory.MakeTexture(Gpu, Memory, TicPosition);
+
+ Gpu.Renderer.SetTextureAndSampler(TexIndex, Texture, Sampler);
+ Gpu.Renderer.BindTexture(TexIndex);
+ }
}
private void UploadUniforms(AMemory Memory)
@@ -262,9 +282,9 @@ namespace Ryujinx.Graphics.Gpu
continue;
}
- for (int Cbuf = 0; Cbuf < Cbs.Length; Cbuf++)
+ for (int Cbuf = 0; Cbuf < ConstBuffers.Length; Cbuf++)
{
- ConstBuffer Cb = Cbs[Cbuf];
+ ConstBuffer Cb = ConstBuffers[Cbuf];
if (Cb.Enabled)
{
@@ -379,7 +399,7 @@ namespace Ryujinx.Graphics.Gpu
if (Mode == 0)
{
- //Write.
+ //Write mode.
Memory.WriteInt32(Position, Seq);
}
}
@@ -414,16 +434,16 @@ namespace Ryujinx.Graphics.Gpu
if (TryGetCpuAddr(NvGpuEngine3dReg.ConstBufferNAddress, out long Position))
{
- Cbs[Index].Position = Position;
- Cbs[Index].Enabled = Enabled;
+ ConstBuffers[Index].Position = Position;
+ ConstBuffers[Index].Enabled = Enabled;
- Cbs[Index].Size = ReadRegister(NvGpuEngine3dReg.ConstBufferNSize);
+ ConstBuffers[Index].Size = ReadRegister(NvGpuEngine3dReg.ConstBufferNSize);
}
}
private int ReadCb(AMemory Memory, int Cbuf, int Offset)
{
- long Position = Cbs[Cbuf].Position;
+ long Position = ConstBuffers[Cbuf].Position;
int Value = Memory.ReadInt32(Position + Offset);
@@ -465,5 +485,10 @@ namespace Ryujinx.Graphics.Gpu
{
Registers[(int)Reg] = Value;
}
+
+ public bool IsFrameBufferPosition(long Position)
+ {
+ return FrameBuffers.Contains(Position);
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs
index 4bba9abe..cb0b9d98 100644
--- a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs
+++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs
@@ -7,6 +7,7 @@ namespace Ryujinx.Graphics.Gpu
FrameBufferNHeight = 0x203,
FrameBufferNFormat = 0x204,
VertexAttribNFormat = 0x458,
+ IBlendEnable = 0x4b9,
BlendSeparateAlpha = 0x4cf,
BlendEquationRgb = 0x4d0,
BlendFuncSrcRgb = 0x4d1,
@@ -31,6 +32,13 @@ namespace Ryujinx.Graphics.Gpu
VertexArrayNControl = 0x700,
VertexArrayNAddress = 0x701,
VertexArrayNDivisor = 0x703,
+ IBlendNSeparateAlpha = 0x780,
+ IBlendNEquationRgb = 0x781,
+ IBlendNFuncSrcRgb = 0x782,
+ IBlendNFuncDstRgb = 0x783,
+ IBlendNEquationAlpha = 0x784,
+ IBlendNFuncSrcAlpha = 0x785,
+ IBlendNFuncDstAlpha = 0x786,
VertexArrayNEndAddr = 0x7c0,
ShaderNControl = 0x800,
ShaderNOffset = 0x801,
diff --git a/Ryujinx.Graphics/Gpu/Texture.cs b/Ryujinx.Graphics/Gpu/Texture.cs
index 831c664d..cbfa683d 100644
--- a/Ryujinx.Graphics/Gpu/Texture.cs
+++ b/Ryujinx.Graphics/Gpu/Texture.cs
@@ -2,7 +2,7 @@ using Ryujinx.Graphics.Gal;
namespace Ryujinx.Graphics.Gpu
{
- struct Texture
+ public struct Texture
{
public long Position { get; private set; }
@@ -17,6 +17,24 @@ namespace Ryujinx.Graphics.Gpu
public GalTextureFormat Format { get; private set; }
public Texture(
+ long Position,
+ int Width,
+ int Height)
+ {
+ this.Position = Position;
+ this.Width = Width;
+ this.Height = Height;
+
+ Pitch = 0;
+
+ BlockHeight = 16;
+
+ Swizzle = TextureSwizzle.BlockLinear;
+
+ Format = GalTextureFormat.A8B8G8R8;
+ }
+
+ public Texture(
long Position,
int Width,
int Height,
diff --git a/Ryujinx.Graphics/Gpu/TextureReader.cs b/Ryujinx.Graphics/Gpu/TextureReader.cs
index b3b016ed..4c3b4fb1 100644
--- a/Ryujinx.Graphics/Gpu/TextureReader.cs
+++ b/Ryujinx.Graphics/Gpu/TextureReader.cs
@@ -4,7 +4,7 @@ using System;
namespace Ryujinx.Graphics.Gpu
{
- static class TextureReader
+ public static class TextureReader
{
public static byte[] Read(AMemory Memory, Texture Texture)
{
diff --git a/Ryujinx.Graphics/Gpu/TextureSwizzle.cs b/Ryujinx.Graphics/Gpu/TextureSwizzle.cs
index 2142e2c2..7d99279c 100644
--- a/Ryujinx.Graphics/Gpu/TextureSwizzle.cs
+++ b/Ryujinx.Graphics/Gpu/TextureSwizzle.cs
@@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.Gpu
{
- enum TextureSwizzle
+ public enum TextureSwizzle
{
_1dBuffer = 0,
PitchColorKey = 1,
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index d6a33edb..49338247 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -38,8 +38,6 @@ namespace Ryujinx
protected override void OnLoad(EventArgs e)
{
VSync = VSyncMode.On;
-
- Renderer.InitializeFrameBuffer();
}
protected override void OnUpdateFrame(FrameEventArgs e)