Move framebuffer flip into a buffer

This commit is contained in:
ReinUsesLisp 2018-08-01 21:15:28 -03:00
commit 38a6af032f
7 changed files with 67 additions and 23 deletions

View file

@ -19,6 +19,9 @@
public GalVertexBinding[] VertexBindings; public GalVertexBinding[] VertexBindings;
public float FlipX;
public float FlipY;
public GalFrontFace FrontFace; public GalFrontFace FrontFace;
public bool CullFaceEnabled; public bool CullFaceEnabled;

View file

@ -13,8 +13,6 @@ namespace Ryujinx.Graphics.Gal
void EnsureTextureBinding(string UniformName, int Value); void EnsureTextureBinding(string UniformName, int Value);
void SetFlip(float X, float Y);
void Bind(long Key); void Bind(long Key);
void Unbind(GalShaderType Type); void Unbind(GalShaderType Type);

View file

@ -108,10 +108,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
//O stands for Older, S for (current) State //O stands for Older, S for (current) State
BindUniforms(S); BindConstBuffers(S);
BindVertexLayout(S); BindVertexLayout(S);
if (S.FlipX != O.FlipX || S.FlipY != O.FlipY)
{
Shader.SetFlip(S.FlipX, S.FlipY);
}
//Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved
//if (S.FrontFace != O.FrontFace) //if (S.FrontFace != O.FrontFace)
@ -279,9 +284,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
O = S; O = S;
} }
private void BindUniforms(GalPipelineState S) private void BindConstBuffers(GalPipelineState S)
{ {
int FreeBinding = 0; //Index 0 is reserved
int FreeBinding = 1;
void BindIfNotNull(OGLShaderStage Stage) void BindIfNotNull(OGLShaderStage Stage)
{ {

View file

@ -5,8 +5,6 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Buffer = System.Buffer;
namespace Ryujinx.Graphics.Gal.OpenGL namespace Ryujinx.Graphics.Gal.OpenGL
{ {
class OGLShader : IGalShader class OGLShader : IGalShader
@ -21,6 +19,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private OGLConstBuffer Buffer; private OGLConstBuffer Buffer;
private int ExtraUboHandle;
public OGLShader(OGLConstBuffer Buffer) public OGLShader(OGLConstBuffer Buffer)
{ {
this.Buffer = Buffer; this.Buffer = Buffer;
@ -95,13 +95,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Uniform1(Location, Value); GL.Uniform1(Location, Value);
} }
public void SetFlip(float X, float Y) public unsafe void SetFlip(float X, float Y)
{ {
BindProgram(); BindProgram();
int Location = GL.GetUniformLocation(CurrentProgramHandle, GlslDecl.FlipUniformName); EnsureExtraBlock();
GL.Uniform2(Location, X, Y); GL.BindBuffer(BufferTarget.UniformBuffer, ExtraUboHandle);
float* Data = stackalloc float[4];
Data[0] = X;
Data[1] = Y;
//Invalidate buffer
GL.BufferData(BufferTarget.UniformBuffer, 4 * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, 4 * sizeof(float), (IntPtr)Data);
} }
public void Bind(long Key) public void Bind(long Key)
@ -178,6 +187,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL
CurrentProgramHandle = Handle; CurrentProgramHandle = Handle;
} }
private void EnsureExtraBlock()
{
if (ExtraUboHandle == 0)
{
ExtraUboHandle = GL.GenBuffer();
GL.BindBuffer(BufferTarget.UniformBuffer, ExtraUboHandle);
GL.BufferData(BufferTarget.UniformBuffer, 4 * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
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)
@ -190,7 +213,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void BindUniformBlocks(int ProgramHandle) private void BindUniformBlocks(int ProgramHandle)
{ {
int FreeBinding = 0; int ExtraBlockindex = GL.GetUniformBlockIndex(ProgramHandle, GlslDecl.ExtraUniformBlockName);
GL.UniformBlockBinding(ProgramHandle, ExtraBlockindex, 0);
//First index is reserved
int FreeBinding = 1;
void BindUniformBlocksIfNotNull(OGLShaderStage Stage) void BindUniformBlocksIfNotNull(OGLShaderStage Stage)
{ {

View file

@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public const string FragmentOutputName = "FragColor"; public const string FragmentOutputName = "FragColor";
public const string ExtraUniformBlockName = "Extra";
public const string FlipUniformName = "flip"; public const string FlipUniformName = "flip";
public const string ProgramName = "program"; public const string ProgramName = "program";

View file

@ -222,7 +222,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
if (Decl.ShaderType == GalShaderType.Vertex) if (Decl.ShaderType == GalShaderType.Vertex)
{ {
SB.AppendLine("uniform vec2 " + GlslDecl.FlipUniformName + ";"); SB.AppendLine("layout (std140) uniform " + GlslDecl.ExtraUniformBlockName + "{");
SB.AppendLine(IdentationStr + "vec2 " + GlslDecl.FlipUniformName + ";");
SB.AppendLine("};");
} }
SB.AppendLine(); SB.AppendLine();

View file

@ -86,12 +86,7 @@ namespace Ryujinx.HLE.Gpu.Engines
GalPipelineState State = new GalPipelineState(); GalPipelineState State = new GalPipelineState();
SetFrameBuffer(Vmm, 0); SetFlip(State);
long[] Keys = UploadShaders(Vmm);
Gpu.Renderer.Shader.BindProgram();
SetFrontFace(State); SetFrontFace(State);
SetCullFace(State); SetCullFace(State);
SetDepth(State); SetDepth(State);
@ -99,6 +94,12 @@ namespace Ryujinx.HLE.Gpu.Engines
SetAlphaBlending(State); SetAlphaBlending(State);
SetPrimitiveRestart(State); SetPrimitiveRestart(State);
SetFrameBuffer(Vmm, 0);
long[] Keys = UploadShaders(Vmm);
Gpu.Renderer.Shader.BindProgram();
UploadTextures(Vmm, State, Keys); UploadTextures(Vmm, State, Keys);
UploadConstBuffers(Vmm, State); UploadConstBuffers(Vmm, State);
UploadVertexArrays(Vmm, State); UploadVertexArrays(Vmm, State);
@ -190,6 +191,8 @@ namespace Ryujinx.HLE.Gpu.Engines
long VpAPos = BasePosition + (uint)VpAOffset; long VpAPos = BasePosition + (uint)VpAOffset;
long VpBPos = BasePosition + (uint)VpBOffset; long VpBPos = BasePosition + (uint)VpBOffset;
Keys[(int)GalShaderType.Vertex] = VpBPos;
Gpu.Renderer.Shader.Create(Vmm, VpAPos, VpBPos, GalShaderType.Vertex); Gpu.Renderer.Shader.Create(Vmm, VpAPos, VpBPos, GalShaderType.Vertex);
Gpu.Renderer.Shader.Bind(VpBPos); Gpu.Renderer.Shader.Bind(VpBPos);
@ -221,11 +224,6 @@ namespace Ryujinx.HLE.Gpu.Engines
Gpu.Renderer.Shader.Bind(Key); Gpu.Renderer.Shader.Bind(Key);
} }
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
Gpu.Renderer.Shader.SetFlip(SignX, SignY);
return Keys; return Keys;
} }
@ -244,6 +242,12 @@ namespace Ryujinx.HLE.Gpu.Engines
throw new ArgumentOutOfRangeException(nameof(Program)); throw new ArgumentOutOfRangeException(nameof(Program));
} }
private void SetFlip(GalPipelineState State)
{
State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
}
private void SetFrontFace(GalPipelineState State) private void SetFrontFace(GalPipelineState State)
{ {
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX); float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);