Move framebuffer flip into a buffer

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

View file

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

View file

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

View file

@ -108,10 +108,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
//O stands for Older, S for (current) State
BindUniforms(S);
BindConstBuffers(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
//if (S.FrontFace != O.FrontFace)
@ -279,9 +284,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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)
{

View file

@ -5,8 +5,6 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Buffer = System.Buffer;
namespace Ryujinx.Graphics.Gal.OpenGL
{
class OGLShader : IGalShader
@ -21,6 +19,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private OGLConstBuffer Buffer;
private int ExtraUboHandle;
public OGLShader(OGLConstBuffer Buffer)
{
this.Buffer = Buffer;
@ -95,13 +95,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Uniform1(Location, Value);
}
public void SetFlip(float X, float Y)
public unsafe void SetFlip(float X, float Y)
{
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)
@ -178,6 +187,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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)
{
if (Stage != null)
@ -190,7 +213,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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)
{

View file

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

View file

@ -222,7 +222,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{
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();

View file

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