Move Vertex Assembly into GalPipelineState
This commit is contained in:
parent
9c2316a965
commit
c9245100a0
6 changed files with 167 additions and 147 deletions
|
@ -1,8 +1,28 @@
|
||||||
namespace Ryujinx.Graphics.Gal
|
namespace Ryujinx.Graphics.Gal
|
||||||
{
|
{
|
||||||
|
public struct GalVertexBinding
|
||||||
|
{
|
||||||
|
//VboKey shouldn't be here, but ARB_vertex_attrib_binding is core since 4.3
|
||||||
|
|
||||||
|
public bool Enabled;
|
||||||
|
public int Stride;
|
||||||
|
public long VboKey;
|
||||||
|
public GalVertexAttrib[] Attribs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct GalConstBufferBinding
|
||||||
|
{
|
||||||
|
public bool Enabled;
|
||||||
|
public long Key;
|
||||||
|
}
|
||||||
|
|
||||||
public struct GalPipelineState
|
public struct GalPipelineState
|
||||||
{
|
{
|
||||||
|
public const int ConstBuffersPerStage = 18;
|
||||||
|
|
||||||
|
public GalConstBufferBinding[][] ConstBufferKeys;
|
||||||
|
|
||||||
|
public GalVertexBinding[] VertexBindings;
|
||||||
|
|
||||||
public GalFrontFace FrontFace;
|
public GalFrontFace FrontFace;
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@ namespace Ryujinx.Graphics.Gal
|
||||||
|
|
||||||
void CreateIbo(long Key, int DataSize, IntPtr HostAddress);
|
void CreateIbo(long Key, int DataSize, IntPtr HostAddress);
|
||||||
|
|
||||||
void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs);
|
|
||||||
|
|
||||||
void SetIndexArray(int Size, GalIndexFormat Format);
|
void SetIndexArray(int Size, GalIndexFormat Format);
|
||||||
|
|
||||||
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
|
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
|
||||||
|
|
|
@ -1,62 +1,157 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
public class OGLPipeline : IGalPipeline
|
public class OGLPipeline : IGalPipeline
|
||||||
{
|
{
|
||||||
|
private static Dictionary<GalVertexAttribSize, int> AttribElements =
|
||||||
|
new Dictionary<GalVertexAttribSize, int>()
|
||||||
|
{
|
||||||
|
{ GalVertexAttribSize._32_32_32_32, 4 },
|
||||||
|
{ GalVertexAttribSize._32_32_32, 3 },
|
||||||
|
{ GalVertexAttribSize._16_16_16_16, 4 },
|
||||||
|
{ GalVertexAttribSize._32_32, 2 },
|
||||||
|
{ GalVertexAttribSize._16_16_16, 3 },
|
||||||
|
{ GalVertexAttribSize._8_8_8_8, 4 },
|
||||||
|
{ GalVertexAttribSize._16_16, 2 },
|
||||||
|
{ GalVertexAttribSize._32, 1 },
|
||||||
|
{ GalVertexAttribSize._8_8_8, 3 },
|
||||||
|
{ GalVertexAttribSize._8_8, 2 },
|
||||||
|
{ GalVertexAttribSize._16, 1 },
|
||||||
|
{ GalVertexAttribSize._8, 1 },
|
||||||
|
{ GalVertexAttribSize._10_10_10_2, 4 },
|
||||||
|
{ GalVertexAttribSize._11_11_10, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
|
||||||
|
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
||||||
|
{
|
||||||
|
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
|
||||||
|
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
|
||||||
|
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
|
||||||
|
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
|
||||||
|
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
|
||||||
|
{ GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
|
||||||
|
{ GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
|
||||||
|
{ GalVertexAttribSize._32, VertexAttribPointerType.Int },
|
||||||
|
{ GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
|
||||||
|
{ GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
|
||||||
|
{ GalVertexAttribSize._16, VertexAttribPointerType.Short },
|
||||||
|
{ GalVertexAttribSize._8, VertexAttribPointerType.Byte },
|
||||||
|
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
|
||||||
|
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
|
||||||
|
};
|
||||||
|
|
||||||
private GalPipelineState O;
|
private GalPipelineState O;
|
||||||
|
|
||||||
public OGLPipeline()
|
private OGLRasterizer Rasterizer;
|
||||||
|
|
||||||
|
private int VaoHandle;
|
||||||
|
|
||||||
|
public OGLPipeline(OGLRasterizer Rasterizer)
|
||||||
{
|
{
|
||||||
//The following values match OpenGL's defaults
|
this.Rasterizer = Rasterizer;
|
||||||
O = new GalPipelineState();
|
|
||||||
|
|
||||||
O.FrontFace = GalFrontFace.CCW;
|
//These values match OpenGL's defaults
|
||||||
|
O = new GalPipelineState
|
||||||
|
{
|
||||||
|
FrontFace = GalFrontFace.CCW,
|
||||||
|
|
||||||
O.CullFaceEnabled = false;
|
CullFaceEnabled = false,
|
||||||
O.CullFace = GalCullFace.Back;
|
CullFace = GalCullFace.Back,
|
||||||
|
|
||||||
O.DepthTestEnabled = false;
|
DepthTestEnabled = false,
|
||||||
O.DepthClear = 1f;
|
DepthClear = 1f,
|
||||||
O.DepthFunc = GalComparisonOp.Less;
|
DepthFunc = GalComparisonOp.Less,
|
||||||
|
|
||||||
O.StencilTestEnabled = false;
|
StencilTestEnabled = false,
|
||||||
O.StencilClear = 0;
|
StencilClear = 0,
|
||||||
|
|
||||||
O.StencilBackFuncFunc = GalComparisonOp.Always;
|
StencilBackFuncFunc = GalComparisonOp.Always,
|
||||||
O.StencilBackFuncRef = 0;
|
StencilBackFuncRef = 0,
|
||||||
O.StencilBackFuncMask = UInt32.MaxValue;
|
StencilBackFuncMask = UInt32.MaxValue,
|
||||||
O.StencilBackOpFail = GalStencilOp.Keep;
|
StencilBackOpFail = GalStencilOp.Keep,
|
||||||
O.StencilBackOpZFail = GalStencilOp.Keep;
|
StencilBackOpZFail = GalStencilOp.Keep,
|
||||||
O.StencilBackOpZPass = GalStencilOp.Keep;
|
StencilBackOpZPass = GalStencilOp.Keep,
|
||||||
O.StencilBackMask = UInt32.MaxValue;
|
StencilBackMask = UInt32.MaxValue,
|
||||||
|
|
||||||
O.StencilFrontFuncFunc = GalComparisonOp.Always;
|
StencilFrontFuncFunc = GalComparisonOp.Always,
|
||||||
O.StencilFrontFuncRef = 0;
|
StencilFrontFuncRef = 0,
|
||||||
O.StencilFrontFuncMask = UInt32.MaxValue;
|
StencilFrontFuncMask = UInt32.MaxValue,
|
||||||
O.StencilFrontOpFail = GalStencilOp.Keep;
|
StencilFrontOpFail = GalStencilOp.Keep,
|
||||||
O.StencilFrontOpZFail = GalStencilOp.Keep;
|
StencilFrontOpZFail = GalStencilOp.Keep,
|
||||||
O.StencilFrontOpZPass = GalStencilOp.Keep;
|
StencilFrontOpZPass = GalStencilOp.Keep,
|
||||||
O.StencilFrontMask = UInt32.MaxValue;
|
StencilFrontMask = UInt32.MaxValue,
|
||||||
|
|
||||||
O.BlendEnabled = false;
|
BlendEnabled = false,
|
||||||
O.BlendSeparateAlpha = false;
|
BlendSeparateAlpha = false,
|
||||||
|
|
||||||
O.BlendEquationRgb = 0;
|
BlendEquationRgb = 0,
|
||||||
O.BlendFuncSrcRgb = GalBlendFactor.One;
|
BlendFuncSrcRgb = GalBlendFactor.One,
|
||||||
O.BlendFuncDstRgb = GalBlendFactor.Zero;
|
BlendFuncDstRgb = GalBlendFactor.Zero,
|
||||||
O.BlendEquationAlpha = 0;
|
BlendEquationAlpha = 0,
|
||||||
O.BlendFuncSrcAlpha = GalBlendFactor.One;
|
BlendFuncSrcAlpha = GalBlendFactor.One,
|
||||||
O.BlendFuncDstAlpha = GalBlendFactor.Zero;
|
BlendFuncDstAlpha = GalBlendFactor.Zero,
|
||||||
|
|
||||||
O.PrimitiveRestartEnabled = false;
|
PrimitiveRestartEnabled = false,
|
||||||
O.PrimitiveRestartIndex = 0;
|
PrimitiveRestartIndex = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind(ref GalPipelineState S)
|
public void Bind(ref GalPipelineState S)
|
||||||
{
|
{
|
||||||
// O stands for Other, S from State (current state)
|
//O stands for Older, S for (current) State
|
||||||
|
|
||||||
|
foreach (GalVertexBinding Binding in S.VertexBindings)
|
||||||
|
{
|
||||||
|
if (!Binding.Enabled || !Rasterizer.TryGetVbo(Binding.VboKey, out int VboHandle))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VaoHandle == 0)
|
||||||
|
{
|
||||||
|
VaoHandle = GL.GenVertexArray();
|
||||||
|
|
||||||
|
//Vertex arrays shouldn't be used anywhere else in OpenGL's backend
|
||||||
|
//if you want to use it, move this line out of the if
|
||||||
|
GL.BindVertexArray(VaoHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (GalVertexAttrib Attrib in Binding.Attribs)
|
||||||
|
{
|
||||||
|
GL.EnableVertexAttribArray(Attrib.Index);
|
||||||
|
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||||
|
|
||||||
|
bool Unsigned =
|
||||||
|
Attrib.Type == GalVertexAttribType.Unorm ||
|
||||||
|
Attrib.Type == GalVertexAttribType.Uint ||
|
||||||
|
Attrib.Type == GalVertexAttribType.Uscaled;
|
||||||
|
|
||||||
|
bool Normalize =
|
||||||
|
Attrib.Type == GalVertexAttribType.Snorm ||
|
||||||
|
Attrib.Type == GalVertexAttribType.Unorm;
|
||||||
|
|
||||||
|
VertexAttribPointerType Type = 0;
|
||||||
|
|
||||||
|
if (Attrib.Type == GalVertexAttribType.Float)
|
||||||
|
{
|
||||||
|
Type = VertexAttribPointerType.Float;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Size = AttribElements[Attrib.Size];
|
||||||
|
int Offset = Attrib.Offset;
|
||||||
|
|
||||||
|
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved
|
//Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved
|
||||||
|
|
||||||
|
|
|
@ -6,46 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
public class OGLRasterizer : IGalRasterizer
|
public class OGLRasterizer : IGalRasterizer
|
||||||
{
|
{
|
||||||
private static Dictionary<GalVertexAttribSize, int> AttribElements =
|
|
||||||
new Dictionary<GalVertexAttribSize, int>()
|
|
||||||
{
|
|
||||||
{ GalVertexAttribSize._32_32_32_32, 4 },
|
|
||||||
{ GalVertexAttribSize._32_32_32, 3 },
|
|
||||||
{ GalVertexAttribSize._16_16_16_16, 4 },
|
|
||||||
{ GalVertexAttribSize._32_32, 2 },
|
|
||||||
{ GalVertexAttribSize._16_16_16, 3 },
|
|
||||||
{ GalVertexAttribSize._8_8_8_8, 4 },
|
|
||||||
{ GalVertexAttribSize._16_16, 2 },
|
|
||||||
{ GalVertexAttribSize._32, 1 },
|
|
||||||
{ GalVertexAttribSize._8_8_8, 3 },
|
|
||||||
{ GalVertexAttribSize._8_8, 2 },
|
|
||||||
{ GalVertexAttribSize._16, 1 },
|
|
||||||
{ GalVertexAttribSize._8, 1 },
|
|
||||||
{ GalVertexAttribSize._10_10_10_2, 4 },
|
|
||||||
{ GalVertexAttribSize._11_11_10, 3 }
|
|
||||||
};
|
|
||||||
|
|
||||||
private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
|
|
||||||
new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
|
|
||||||
{
|
|
||||||
{ GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
|
|
||||||
{ GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
|
|
||||||
{ GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
|
|
||||||
{ GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
|
|
||||||
{ GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
|
|
||||||
{ GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
|
|
||||||
{ GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
|
|
||||||
{ GalVertexAttribSize._32, VertexAttribPointerType.Int },
|
|
||||||
{ GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
|
|
||||||
{ GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
|
|
||||||
{ GalVertexAttribSize._16, VertexAttribPointerType.Short },
|
|
||||||
{ GalVertexAttribSize._8, VertexAttribPointerType.Byte },
|
|
||||||
{ GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
|
|
||||||
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
|
|
||||||
};
|
|
||||||
|
|
||||||
private int VaoHandle;
|
|
||||||
|
|
||||||
private int[] VertexBuffers;
|
private int[] VertexBuffers;
|
||||||
|
|
||||||
private OGLCachedResource<int> VboCache;
|
private OGLCachedResource<int> VboCache;
|
||||||
|
@ -142,65 +102,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
|
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs)
|
|
||||||
{
|
|
||||||
if (!VboCache.TryGetValue(VboKey, out int VboHandle))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VaoHandle == 0)
|
|
||||||
{
|
|
||||||
VaoHandle = GL.GenVertexArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.BindVertexArray(VaoHandle);
|
|
||||||
|
|
||||||
foreach (GalVertexAttrib Attrib in Attribs)
|
|
||||||
{
|
|
||||||
GL.EnableVertexAttribArray(Attrib.Index);
|
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
|
||||||
|
|
||||||
bool Unsigned =
|
|
||||||
Attrib.Type == GalVertexAttribType.Unorm ||
|
|
||||||
Attrib.Type == GalVertexAttribType.Uint ||
|
|
||||||
Attrib.Type == GalVertexAttribType.Uscaled;
|
|
||||||
|
|
||||||
bool Normalize =
|
|
||||||
Attrib.Type == GalVertexAttribType.Snorm ||
|
|
||||||
Attrib.Type == GalVertexAttribType.Unorm;
|
|
||||||
|
|
||||||
VertexAttribPointerType Type = 0;
|
|
||||||
|
|
||||||
if (Attrib.Type == GalVertexAttribType.Float)
|
|
||||||
{
|
|
||||||
Type = VertexAttribPointerType.Float;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Size = AttribElements[Attrib.Size];
|
|
||||||
int Offset = Attrib.Offset;
|
|
||||||
|
|
||||||
if (Attrib.Type == GalVertexAttribType.Sint ||
|
|
||||||
Attrib.Type == GalVertexAttribType.Uint)
|
|
||||||
{
|
|
||||||
IntPtr Pointer = new IntPtr(Offset);
|
|
||||||
|
|
||||||
VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
|
|
||||||
|
|
||||||
GL.VertexAttribIPointer(Attrib.Index, Size, IType, Stride, Pointer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Stride, Offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetIndexArray(int Size, GalIndexFormat Format)
|
public void SetIndexArray(int Size, GalIndexFormat Format)
|
||||||
{
|
{
|
||||||
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
|
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
|
||||||
|
@ -217,8 +118,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BindVertexArray(VaoHandle);
|
|
||||||
|
|
||||||
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
|
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,8 +130,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
|
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
|
||||||
|
|
||||||
GL.BindVertexArray(VaoHandle);
|
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
|
||||||
|
|
||||||
First <<= IndexBuffer.ElemSizeLog2;
|
First <<= IndexBuffer.ElemSizeLog2;
|
||||||
|
@ -248,5 +145,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
|
GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetVbo(long VboKey, out int VboHandle)
|
||||||
|
{
|
||||||
|
return VboCache.TryGetValue(VboKey, out VboHandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
Shader = new OGLShader(Buffer as OGLConstBuffer);
|
Shader = new OGLShader(Buffer as OGLConstBuffer);
|
||||||
|
|
||||||
Pipeline = new OGLPipeline();
|
Pipeline = new OGLPipeline(Rasterizer as OGLRasterizer);
|
||||||
|
|
||||||
Texture = new OGLTexture();
|
Texture = new OGLTexture();
|
||||||
|
|
||||||
|
|
|
@ -530,6 +530,8 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
((Packed >> 31) & 0x1) != 0));
|
((Packed >> 31) & 0x1) != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State.VertexBindings = new GalVertexBinding[32];
|
||||||
|
|
||||||
for (int Index = 0; Index < 32; Index++)
|
for (int Index = 0; Index < 32; Index++)
|
||||||
{
|
{
|
||||||
if (Attribs[Index] == null)
|
if (Attribs[Index] == null)
|
||||||
|
@ -541,14 +543,14 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
|
|
||||||
bool Enable = (Control & 0x1000) != 0;
|
bool Enable = (Control & 0x1000) != 0;
|
||||||
|
|
||||||
long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
|
|
||||||
long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2);
|
|
||||||
|
|
||||||
if (!Enable)
|
if (!Enable)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
|
||||||
|
long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2);
|
||||||
|
|
||||||
long VboKey = Vmm.GetPhysicalAddress(VertexPosition);
|
long VboKey = Vmm.GetPhysicalAddress(VertexPosition);
|
||||||
|
|
||||||
int Stride = Control & 0xfff;
|
int Stride = Control & 0xfff;
|
||||||
|
@ -564,7 +566,10 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress);
|
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray());
|
State.VertexBindings[Index].Enabled = true;
|
||||||
|
State.VertexBindings[Index].Stride = Stride;
|
||||||
|
State.VertexBindings[Index].VboKey = VboKey;
|
||||||
|
State.VertexBindings[Index].Attribs = Attribs[Index].ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue