|
@@ -1,8 +1,10 @@
|
|
|
using Ryujinx.Graphics.Gal;
|
|
using Ryujinx.Graphics.Gal;
|
|
|
|
|
+using Ryujinx.HLE.Gpu.Memory;
|
|
|
|
|
+using Ryujinx.HLE.Gpu.Texture;
|
|
|
using System;
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
-namespace Ryujinx.HLE.Gpu
|
|
|
|
|
|
|
+namespace Ryujinx.HLE.Gpu.Engines
|
|
|
{
|
|
{
|
|
|
class NvGpuEngine3d : INvGpuEngine
|
|
class NvGpuEngine3d : INvGpuEngine
|
|
|
{
|
|
{
|
|
@@ -73,13 +75,13 @@ namespace Ryujinx.HLE.Gpu
|
|
|
{
|
|
{
|
|
|
SetFrameBuffer(Vmm, 0);
|
|
SetFrameBuffer(Vmm, 0);
|
|
|
|
|
|
|
|
- long[] Tags = UploadShaders(Vmm);
|
|
|
|
|
|
|
+ long[] Keys = UploadShaders(Vmm);
|
|
|
|
|
|
|
|
- Gpu.Renderer.BindProgram();
|
|
|
|
|
|
|
+ Gpu.Renderer.Shader.BindProgram();
|
|
|
|
|
|
|
|
SetAlphaBlending();
|
|
SetAlphaBlending();
|
|
|
|
|
|
|
|
- UploadTextures(Vmm, Tags);
|
|
|
|
|
|
|
+ UploadTextures(Vmm, Keys);
|
|
|
UploadUniforms(Vmm);
|
|
UploadUniforms(Vmm);
|
|
|
UploadVertexArrays(Vmm);
|
|
UploadVertexArrays(Vmm);
|
|
|
}
|
|
}
|
|
@@ -113,13 +115,13 @@ namespace Ryujinx.HLE.Gpu
|
|
|
|
|
|
|
|
//Note: Using the Width/Height results seems to give incorrect results.
|
|
//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.
|
|
//Maybe the size of all frame buffers is hardcoded to screen size? This seems unlikely.
|
|
|
- Gpu.Renderer.CreateFrameBuffer(PA, 1280, 720);
|
|
|
|
|
- Gpu.Renderer.BindFrameBuffer(PA);
|
|
|
|
|
|
|
+ Gpu.Renderer.FrameBuffer.Create(PA, 1280, 720);
|
|
|
|
|
+ Gpu.Renderer.FrameBuffer.Bind(PA);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private long[] UploadShaders(NvGpuVmm Vmm)
|
|
private long[] UploadShaders(NvGpuVmm Vmm)
|
|
|
{
|
|
{
|
|
|
- long[] Tags = new long[5];
|
|
|
|
|
|
|
+ long[] Keys = new long[5];
|
|
|
|
|
|
|
|
long BasePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
|
|
long BasePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
|
|
|
|
|
|
|
@@ -136,14 +138,14 @@ namespace Ryujinx.HLE.Gpu
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- long Tag = BasePosition + (uint)Offset;
|
|
|
|
|
|
|
+ long Key = BasePosition + (uint)Offset;
|
|
|
|
|
|
|
|
GalShaderType ShaderType = GetTypeFromProgram(Index);
|
|
GalShaderType ShaderType = GetTypeFromProgram(Index);
|
|
|
|
|
|
|
|
- Tags[(int)ShaderType] = Tag;
|
|
|
|
|
|
|
+ Keys[(int)ShaderType] = Key;
|
|
|
|
|
|
|
|
- Gpu.Renderer.CreateShader(Vmm, Tag, ShaderType);
|
|
|
|
|
- Gpu.Renderer.BindShader(Tag);
|
|
|
|
|
|
|
+ Gpu.Renderer.Shader.Create(Vmm, Key, ShaderType);
|
|
|
|
|
+ Gpu.Renderer.Shader.Bind(Key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int RawSX = ReadRegister(NvGpuEngine3dReg.ViewportScaleX);
|
|
int RawSX = ReadRegister(NvGpuEngine3dReg.ViewportScaleX);
|
|
@@ -155,9 +157,9 @@ namespace Ryujinx.HLE.Gpu
|
|
|
float SignX = MathF.Sign(SX);
|
|
float SignX = MathF.Sign(SX);
|
|
|
float SignY = MathF.Sign(SY);
|
|
float SignY = MathF.Sign(SY);
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetUniform2F(GalConsts.FlipUniformName, SignX, SignY);
|
|
|
|
|
|
|
+ Gpu.Renderer.Shader.SetFlip(SignX, SignY);
|
|
|
|
|
|
|
|
- return Tags;
|
|
|
|
|
|
|
+ return Keys;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static GalShaderType GetTypeFromProgram(int Program)
|
|
private static GalShaderType GetTypeFromProgram(int Program)
|
|
@@ -180,7 +182,14 @@ namespace Ryujinx.HLE.Gpu
|
|
|
//TODO: Support independent blend properly.
|
|
//TODO: Support independent blend properly.
|
|
|
bool Enable = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0;
|
|
bool Enable = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0;
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetBlendEnable(Enable);
|
|
|
|
|
|
|
+ if (Enable)
|
|
|
|
|
+ {
|
|
|
|
|
+ Gpu.Renderer.Blend.Enable();
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ Gpu.Renderer.Blend.Disable();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if (!Enable)
|
|
if (!Enable)
|
|
|
{
|
|
{
|
|
@@ -203,7 +212,7 @@ namespace Ryujinx.HLE.Gpu
|
|
|
GalBlendFactor FuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
|
|
GalBlendFactor FuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
|
|
|
GalBlendFactor FuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
|
|
GalBlendFactor FuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetBlendSeparate(
|
|
|
|
|
|
|
+ Gpu.Renderer.Blend.SetSeparate(
|
|
|
EquationRgb,
|
|
EquationRgb,
|
|
|
EquationAlpha,
|
|
EquationAlpha,
|
|
|
FuncSrcRgb,
|
|
FuncSrcRgb,
|
|
@@ -213,11 +222,11 @@ namespace Ryujinx.HLE.Gpu
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- Gpu.Renderer.SetBlend(EquationRgb, FuncSrcRgb, FuncDstRgb);
|
|
|
|
|
|
|
+ Gpu.Renderer.Blend.Set(EquationRgb, FuncSrcRgb, FuncDstRgb);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void UploadTextures(NvGpuVmm Vmm, long[] Tags)
|
|
|
|
|
|
|
+ private void UploadTextures(NvGpuVmm Vmm, long[] Keys)
|
|
|
{
|
|
{
|
|
|
long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
|
|
long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
|
|
|
|
|
|
|
@@ -227,15 +236,15 @@ namespace Ryujinx.HLE.Gpu
|
|
|
//reserved for drawing the frame buffer.
|
|
//reserved for drawing the frame buffer.
|
|
|
int TexIndex = 1;
|
|
int TexIndex = 1;
|
|
|
|
|
|
|
|
- for (int Index = 0; Index < Tags.Length; Index++)
|
|
|
|
|
|
|
+ for (int Index = 0; Index < Keys.Length; Index++)
|
|
|
{
|
|
{
|
|
|
- foreach (ShaderDeclInfo DeclInfo in Gpu.Renderer.GetTextureUsage(Tags[Index]))
|
|
|
|
|
|
|
+ foreach (ShaderDeclInfo DeclInfo in Gpu.Renderer.Shader.GetTextureUsage(Keys[Index]))
|
|
|
{
|
|
{
|
|
|
long Position = ConstBuffers[Index][TextureCbIndex].Position;
|
|
long Position = ConstBuffers[Index][TextureCbIndex].Position;
|
|
|
|
|
|
|
|
UploadTexture(Vmm, Position, TexIndex, DeclInfo.Index);
|
|
UploadTexture(Vmm, Position, TexIndex, DeclInfo.Index);
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetUniform1(DeclInfo.Name, TexIndex);
|
|
|
|
|
|
|
+ Gpu.Renderer.Shader.EnsureTextureBinding(DeclInfo.Name, TexIndex);
|
|
|
|
|
|
|
|
TexIndex++;
|
|
TexIndex++;
|
|
|
}
|
|
}
|
|
@@ -270,7 +279,7 @@ namespace Ryujinx.HLE.Gpu
|
|
|
|
|
|
|
|
long TextureAddress = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff;
|
|
long TextureAddress = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff;
|
|
|
|
|
|
|
|
- long Tag = TextureAddress;
|
|
|
|
|
|
|
+ long Key = TextureAddress;
|
|
|
|
|
|
|
|
TextureAddress = Vmm.GetPhysicalAddress(TextureAddress);
|
|
TextureAddress = Vmm.GetPhysicalAddress(TextureAddress);
|
|
|
|
|
|
|
@@ -280,7 +289,7 @@ namespace Ryujinx.HLE.Gpu
|
|
|
//we shouldn't read anything from memory and bind
|
|
//we shouldn't read anything from memory and bind
|
|
|
//the frame buffer texture instead, since we're not
|
|
//the frame buffer texture instead, since we're not
|
|
|
//really writing anything to memory.
|
|
//really writing anything to memory.
|
|
|
- Gpu.Renderer.BindFrameBufferTexture(TextureAddress, TexIndex, Sampler);
|
|
|
|
|
|
|
+ Gpu.Renderer.FrameBuffer.BindTexture(TextureAddress, TexIndex);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -288,22 +297,29 @@ namespace Ryujinx.HLE.Gpu
|
|
|
|
|
|
|
|
long Size = (uint)TextureHelper.GetTextureSize(NewTexture);
|
|
long Size = (uint)TextureHelper.GetTextureSize(NewTexture);
|
|
|
|
|
|
|
|
- if (Gpu.Renderer.TryGetCachedTexture(Tag, Size, out GalTexture Texture))
|
|
|
|
|
|
|
+ bool HasCachedTexture = false;
|
|
|
|
|
+
|
|
|
|
|
+ if (Gpu.Renderer.Texture.TryGetCachedTexture(Key, Size, out GalTexture Texture))
|
|
|
{
|
|
{
|
|
|
- if (NewTexture.Equals(Texture) && !Vmm.IsRegionModified(Tag, Size, NvGpuBufferType.Texture))
|
|
|
|
|
|
|
+ if (NewTexture.Equals(Texture) && !Vmm.IsRegionModified(Key, Size, NvGpuBufferType.Texture))
|
|
|
{
|
|
{
|
|
|
- Gpu.Renderer.BindTexture(Tag, TexIndex);
|
|
|
|
|
|
|
+ Gpu.Renderer.Texture.Bind(Key, TexIndex);
|
|
|
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ HasCachedTexture = true;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition);
|
|
|
|
|
|
|
+ if (!HasCachedTexture)
|
|
|
|
|
+ {
|
|
|
|
|
+ byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition);
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetTextureAndSampler(Tag, Data, NewTexture, Sampler);
|
|
|
|
|
|
|
+ Gpu.Renderer.Texture.Create(Key, Data, NewTexture);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- Gpu.Renderer.BindTexture(Tag, TexIndex);
|
|
|
|
|
|
|
+ Gpu.Renderer.Texture.Bind(Key, TexIndex);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ Gpu.Renderer.Texture.SetSampler(Sampler);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void UploadUniforms(NvGpuVmm Vmm)
|
|
private void UploadUniforms(NvGpuVmm Vmm)
|
|
@@ -331,7 +347,7 @@ namespace Ryujinx.HLE.Gpu
|
|
|
{
|
|
{
|
|
|
byte[] Data = Vmm.ReadBytes(Cb.Position, (uint)Cb.Size);
|
|
byte[] Data = Vmm.ReadBytes(Cb.Position, (uint)Cb.Size);
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Data);
|
|
|
|
|
|
|
+ Gpu.Renderer.Shader.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Data);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -341,33 +357,33 @@ namespace Ryujinx.HLE.Gpu
|
|
|
{
|
|
{
|
|
|
long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress);
|
|
long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress);
|
|
|
|
|
|
|
|
- int IndexSize = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat);
|
|
|
|
|
- int IndexFirst = ReadRegister(NvGpuEngine3dReg.IndexBatchFirst);
|
|
|
|
|
- int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount);
|
|
|
|
|
|
|
+ int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat);
|
|
|
|
|
+ int IndexFirst = ReadRegister(NvGpuEngine3dReg.IndexBatchFirst);
|
|
|
|
|
+ int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount);
|
|
|
|
|
|
|
|
- GalIndexFormat IndexFormat = (GalIndexFormat)IndexSize;
|
|
|
|
|
|
|
+ GalIndexFormat IndexFormat = (GalIndexFormat)IndexEntryFmt;
|
|
|
|
|
|
|
|
- IndexSize = 1 << IndexSize;
|
|
|
|
|
|
|
+ int IndexEntrySize = 1 << IndexEntryFmt;
|
|
|
|
|
|
|
|
- if (IndexSize > 4)
|
|
|
|
|
|
|
+ if (IndexEntrySize > 4)
|
|
|
{
|
|
{
|
|
|
throw new InvalidOperationException();
|
|
throw new InvalidOperationException();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (IndexCount != 0)
|
|
if (IndexCount != 0)
|
|
|
{
|
|
{
|
|
|
- int IbSize = IndexCount * IndexSize;
|
|
|
|
|
|
|
+ int IbSize = IndexCount * IndexEntrySize;
|
|
|
|
|
|
|
|
- bool IboCached = Gpu.Renderer.IsIboCached(IndexPosition, (uint)IbSize);
|
|
|
|
|
|
|
+ bool IboCached = Gpu.Renderer.Rasterizer.IsIboCached(IndexPosition, (uint)IbSize);
|
|
|
|
|
|
|
|
if (!IboCached || Vmm.IsRegionModified(IndexPosition, (uint)IbSize, NvGpuBufferType.Index))
|
|
if (!IboCached || Vmm.IsRegionModified(IndexPosition, (uint)IbSize, NvGpuBufferType.Index))
|
|
|
{
|
|
{
|
|
|
byte[] Data = Vmm.ReadBytes(IndexPosition, (uint)IbSize);
|
|
byte[] Data = Vmm.ReadBytes(IndexPosition, (uint)IbSize);
|
|
|
|
|
|
|
|
- Gpu.Renderer.CreateIbo(IndexPosition, Data);
|
|
|
|
|
|
|
+ Gpu.Renderer.Rasterizer.CreateIbo(IndexPosition, Data);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetIndexArray(IndexPosition, IbSize, IndexFormat);
|
|
|
|
|
|
|
+ Gpu.Renderer.Rasterizer.SetIndexArray(IndexPosition, IbSize, IndexFormat);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
List<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[32];
|
|
List<GalVertexAttrib>[] Attribs = new List<GalVertexAttrib>[32];
|
|
@@ -429,27 +445,27 @@ namespace Ryujinx.HLE.Gpu
|
|
|
VbSize = VertexCount * Stride;
|
|
VbSize = VertexCount * Stride;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- bool VboCached = Gpu.Renderer.IsVboCached(VertexPosition, VbSize);
|
|
|
|
|
|
|
+ bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VertexPosition, VbSize);
|
|
|
|
|
|
|
|
if (!VboCached || Vmm.IsRegionModified(VertexPosition, VbSize, NvGpuBufferType.Vertex))
|
|
if (!VboCached || Vmm.IsRegionModified(VertexPosition, VbSize, NvGpuBufferType.Vertex))
|
|
|
{
|
|
{
|
|
|
byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize);
|
|
byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize);
|
|
|
|
|
|
|
|
- Gpu.Renderer.CreateVbo(VertexPosition, Data);
|
|
|
|
|
|
|
+ Gpu.Renderer.Rasterizer.CreateVbo(VertexPosition, Data);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Gpu.Renderer.SetVertexArray(Index, Stride, VertexPosition, Attribs[Index].ToArray());
|
|
|
|
|
|
|
+ Gpu.Renderer.Rasterizer.SetVertexArray(Index, Stride, VertexPosition, Attribs[Index].ToArray());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff);
|
|
GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff);
|
|
|
|
|
|
|
|
if (IndexCount != 0)
|
|
if (IndexCount != 0)
|
|
|
{
|
|
{
|
|
|
- Gpu.Renderer.DrawElements(IndexPosition, IndexFirst, PrimType);
|
|
|
|
|
|
|
+ Gpu.Renderer.Rasterizer.DrawElements(IndexPosition, IndexFirst, PrimType);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- Gpu.Renderer.DrawArrays(VertexFirst, VertexCount, PrimType);
|
|
|
|
|
|
|
+ Gpu.Renderer.Rasterizer.DrawArrays(VertexFirst, VertexCount, PrimType);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|