Quads, QuadStrip, const attributes and half-float attributes support (#447)
* Quads, QuadStrip and const attributes support * Add support for half float attributes and fix texture pitch alignment * Throw when an unsupported float type is used as const attribute aswell
This commit is contained in:
parent
dd3cb33c9f
commit
aa1cd849cf
12 changed files with 420 additions and 53 deletions
|
@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalFrontFace.CCW: return FrontFaceDirection.Ccw;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(FrontFace));
|
||||
throw new ArgumentException(nameof(FrontFace) + " \"" + FrontFace + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static CullFaceMode GetCullFace(GalCullFace CullFace)
|
||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalCullFace.FrontAndBack: return CullFaceMode.FrontAndBack;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(CullFace));
|
||||
throw new ArgumentException(nameof(CullFace) + " \"" + CullFace + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static StencilOp GetStencilOp(GalStencilOp Op)
|
||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalStencilOp.DecrWrap: return StencilOp.DecrWrap;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Op));
|
||||
throw new ArgumentException(nameof(Op) + " \"" + Op + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static DepthFunction GetDepthFunc(GalComparisonOp Func)
|
||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalComparisonOp.Always: return DepthFunction.Always;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Func));
|
||||
throw new ArgumentException(nameof(Func) + " \"" + Func + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static StencilFunction GetStencilFunc(GalComparisonOp Func)
|
||||
|
@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalIndexFormat.Int32: return DrawElementsType.UnsignedInt;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Format));
|
||||
throw new ArgumentException(nameof(Format) + " \"" + Format + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static PrimitiveType GetPrimitiveType(GalPrimitiveType Type)
|
||||
|
@ -98,8 +98,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalPrimitiveType.Triangles: return PrimitiveType.Triangles;
|
||||
case GalPrimitiveType.TriangleStrip: return PrimitiveType.TriangleStrip;
|
||||
case GalPrimitiveType.TriangleFan: return PrimitiveType.TriangleFan;
|
||||
case GalPrimitiveType.Quads: return PrimitiveType.Quads;
|
||||
case GalPrimitiveType.QuadStrip: return PrimitiveType.QuadStrip;
|
||||
case GalPrimitiveType.Polygon: return PrimitiveType.Polygon;
|
||||
case GalPrimitiveType.LinesAdjacency: return PrimitiveType.LinesAdjacency;
|
||||
case GalPrimitiveType.LineStripAdjacency: return PrimitiveType.LineStripAdjacency;
|
||||
|
@ -108,7 +106,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalPrimitiveType.Patches: return PrimitiveType.Patches;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Type));
|
||||
throw new ArgumentException(nameof(Type) + " \"" + Type + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static ShaderType GetShaderType(GalShaderType Type)
|
||||
|
@ -122,7 +120,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalShaderType.Fragment: return ShaderType.FragmentShader;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Type));
|
||||
throw new ArgumentException(nameof(Type) + " \"" + Type + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static (PixelInternalFormat, PixelFormat, PixelType) GetImageFormat(GalImageFormat Format)
|
||||
|
@ -211,7 +209,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalTextureSource.OneFloat: return All.One;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Source));
|
||||
throw new ArgumentException(nameof(Source) + " \"" + Source + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static TextureWrapMode GetTextureWrapMode(GalTextureWrap Wrap)
|
||||
|
@ -245,7 +243,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Wrap));
|
||||
throw new ArgumentException(nameof(Wrap) + " \"" + Wrap + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static TextureMinFilter GetTextureMinFilter(
|
||||
|
@ -259,7 +257,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalTextureFilter.Linear: return TextureMinFilter.Linear;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(MinFilter));
|
||||
throw new ArgumentException(nameof(MinFilter) + " \"" + MinFilter + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static TextureMagFilter GetTextureMagFilter(GalTextureFilter Filter)
|
||||
|
@ -270,7 +268,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalTextureFilter.Linear: return TextureMagFilter.Linear;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(Filter));
|
||||
throw new ArgumentException(nameof(Filter) + " \"" + Filter + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static BlendEquationMode GetBlendEquation(GalBlendEquation BlendEquation)
|
||||
|
@ -284,7 +282,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
case GalBlendEquation.Max: return BlendEquationMode.Max;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(BlendEquation));
|
||||
throw new ArgumentException(nameof(BlendEquation) + " \"" + BlendEquation + "\" is not valid!");
|
||||
}
|
||||
|
||||
public static BlendingFactor GetBlendFactor(GalBlendFactor BlendFactor)
|
||||
|
@ -315,7 +313,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
return BlendingFactor.ConstantColor;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(BlendFactor));
|
||||
throw new ArgumentException(nameof(BlendFactor) + " \"" + BlendFactor + "\" is not valid!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{ GalVertexAttribSize._11_11_10, 3 }
|
||||
};
|
||||
|
||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> FloatAttribTypes =
|
||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||
{
|
||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.HalfFloat },
|
||||
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.HalfFloat },
|
||||
{ GalVertexAttribSize._16_16, VertexAttribPointerType.HalfFloat },
|
||||
{ GalVertexAttribSize._32, VertexAttribPointerType.Float },
|
||||
{ GalVertexAttribSize._16, VertexAttribPointerType.HalfFloat }
|
||||
};
|
||||
|
||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> SignedAttribTypes =
|
||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||
{
|
||||
|
@ -356,8 +369,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
continue;
|
||||
}
|
||||
|
||||
GL.EnableVertexAttribArray(Attrib.Index);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
bool Unsigned =
|
||||
|
@ -373,35 +384,50 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
if (Attrib.Type == GalVertexAttribType.Float)
|
||||
{
|
||||
Type = VertexAttribPointerType.Float;
|
||||
Type = GetType(FloatAttribTypes, Attrib);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Unsigned)
|
||||
{
|
||||
Type = UnsignedAttribTypes[Attrib.Size];
|
||||
Type = GetType(UnsignedAttribTypes, Attrib);
|
||||
}
|
||||
else
|
||||
{
|
||||
Type = SignedAttribTypes[Attrib.Size];
|
||||
Type = GetType(SignedAttribTypes, Attrib);
|
||||
}
|
||||
}
|
||||
|
||||
int Size = AttribElements[Attrib.Size];
|
||||
if (!AttribElements.TryGetValue(Attrib.Size, out int Size))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid attribute size \"" + Attrib.Size + "\"!");
|
||||
}
|
||||
|
||||
int Offset = Attrib.Offset;
|
||||
|
||||
if (Attrib.Type == GalVertexAttribType.Sint ||
|
||||
Attrib.Type == GalVertexAttribType.Uint)
|
||||
if (Binding.Stride != 0)
|
||||
{
|
||||
IntPtr Pointer = new IntPtr(Offset);
|
||||
GL.EnableVertexAttribArray(Attrib.Index);
|
||||
|
||||
VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
|
||||
if (Attrib.Type == GalVertexAttribType.Sint ||
|
||||
Attrib.Type == GalVertexAttribType.Uint)
|
||||
{
|
||||
IntPtr Pointer = new IntPtr(Offset);
|
||||
|
||||
GL.VertexAttribIPointer(Attrib.Index, Size, IType, Binding.Stride, Pointer);
|
||||
VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
|
||||
|
||||
GL.VertexAttribIPointer(Attrib.Index, Size, IType, Binding.Stride, Pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
|
||||
GL.DisableVertexAttribArray(Attrib.Index);
|
||||
|
||||
SetConstAttrib(Attrib);
|
||||
}
|
||||
|
||||
if (Binding.Instanced && Binding.Divisor != 0)
|
||||
|
@ -416,6 +442,149 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
private static VertexAttribPointerType GetType(Dictionary<GalVertexAttribSize, VertexAttribPointerType> Dict, GalVertexAttrib Attrib)
|
||||
{
|
||||
if (!Dict.TryGetValue(Attrib.Size, out VertexAttribPointerType Type))
|
||||
{
|
||||
throw new NotImplementedException("Unsupported size \"" + Attrib.Size + "\" on type \"" + Attrib.Type + "\"!");
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
private unsafe static void SetConstAttrib(GalVertexAttrib Attrib)
|
||||
{
|
||||
void Unsupported()
|
||||
{
|
||||
throw new NotImplementedException("Constant attribute " + Attrib.Size + " not implemented!");
|
||||
}
|
||||
|
||||
if (Attrib.Size == GalVertexAttribSize._10_10_10_2 ||
|
||||
Attrib.Size == GalVertexAttribSize._11_11_10)
|
||||
{
|
||||
Unsupported();
|
||||
}
|
||||
|
||||
if (Attrib.Type == GalVertexAttribType.Unorm)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (byte*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (ushort*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (uint*)Attrib.Pointer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Snorm)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (sbyte*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (short*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttrib4N((uint)Attrib.Index, (int*)Attrib.Pointer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Uint)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (byte*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (ushort*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (uint*)Attrib.Pointer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Sint)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._8:
|
||||
case GalVertexAttribSize._8_8:
|
||||
case GalVertexAttribSize._8_8_8:
|
||||
case GalVertexAttribSize._8_8_8_8:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (sbyte*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._16:
|
||||
case GalVertexAttribSize._16_16:
|
||||
case GalVertexAttribSize._16_16_16:
|
||||
case GalVertexAttribSize._16_16_16_16:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (short*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttribI4((uint)Attrib.Index, (int*)Attrib.Pointer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (Attrib.Type == GalVertexAttribType.Float)
|
||||
{
|
||||
switch (Attrib.Size)
|
||||
{
|
||||
case GalVertexAttribSize._32:
|
||||
case GalVertexAttribSize._32_32:
|
||||
case GalVertexAttribSize._32_32_32:
|
||||
case GalVertexAttribSize._32_32_32_32:
|
||||
GL.VertexAttrib4(Attrib.Index, (float*)Attrib.Pointer);
|
||||
break;
|
||||
|
||||
default: Unsupported(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Enable(EnableCap Cap, bool Enabled)
|
||||
{
|
||||
if (Enabled)
|
||||
|
|
|
@ -119,6 +119,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
|
||||
}
|
||||
|
||||
public void CreateIbo(long Key, int DataSize, byte[] Buffer)
|
||||
{
|
||||
int Handle = GL.GenBuffer();
|
||||
|
||||
IboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
|
||||
|
||||
IntPtr Length = new IntPtr(Buffer.Length);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
|
||||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
||||
}
|
||||
|
||||
public void SetIndexArray(int Size, GalIndexFormat Format)
|
||||
{
|
||||
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
|
||||
|
@ -135,7 +147,26 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
return;
|
||||
}
|
||||
|
||||
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count);
|
||||
if (PrimType == GalPrimitiveType.Quads)
|
||||
{
|
||||
for (int Offset = 0; Offset < Count; Offset += 4)
|
||||
{
|
||||
GL.DrawArrays(PrimitiveType.TriangleFan, First + Offset, 4);
|
||||
}
|
||||
}
|
||||
else if (PrimType == GalPrimitiveType.QuadStrip)
|
||||
{
|
||||
GL.DrawArrays(PrimitiveType.TriangleFan, First, 4);
|
||||
|
||||
for (int Offset = 2; Offset < Count; Offset += 2)
|
||||
{
|
||||
GL.DrawArrays(PrimitiveType.TriangleFan, First + Offset, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType)
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
Attachments.Zeta = Key;
|
||||
}
|
||||
|
||||
|
||||
public void UnbindZeta()
|
||||
{
|
||||
Attachments.Zeta = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue