Work continues

This commit is contained in:
gdkchan 2018-03-30 23:14:07 -03:00
commit 34053fdc15
8 changed files with 121 additions and 84 deletions

View file

@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Gal
//Shader //Shader
void CreateShader(long Tag, byte[] Data, GalShaderType Type); void CreateShader(long Tag, byte[] Data, GalShaderType Type);
void SetShaderCb(int Cbuf, byte[] Data); void SetShaderCb(long Tag, int Cbuf, byte[] Data);
void BindShader(long Tag); void BindShader(long Tag);
void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs); void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs);

View file

@ -3,6 +3,7 @@ using Ryujinx.Graphics.Gal.Shader;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
namespace Ryujinx.Graphics.Gal.OpenGL namespace Ryujinx.Graphics.Gal.OpenGL
{ {
@ -14,11 +15,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public GalShaderType Type { get; private set; } public GalShaderType Type { get; private set; }
public ShaderStage(GalShaderType Type) public ICollection<ShaderDeclInfo> TextureUsage { get; private set; }
public ICollection<ShaderDeclInfo> UniformUsage { get; private set; }
public ShaderStage(
GalShaderType Type,
ICollection<ShaderDeclInfo> TextureUsage,
ICollection<ShaderDeclInfo> UniformUsage)
{ {
Handle = GL.CreateShader(OGLEnumConverter.GetShaderType(Type)); Handle = GL.CreateShader(OGLEnumConverter.GetShaderType(Type));
this.Type = Type; this.Type = Type;
this.TextureUsage = TextureUsage;
this.UniformUsage = UniformUsage;
} }
public void Dispose() public void Dispose()
@ -63,21 +72,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
if (!Stages.ContainsKey(Tag)) if (!Stages.ContainsKey(Tag))
{ {
string Glsl = GetGlslCode(Data, Type); GlslProgram Program = GetGlslProgram(Data, Type);
System.Console.WriteLine(Glsl); System.Console.WriteLine(Program.Code);
ShaderStage Stage = new ShaderStage(Type); ShaderStage Stage = new ShaderStage(
Type,
Program.Textures,
Program.Uniforms);
Stages.Add(Tag, Stage); Stages.Add(Tag, Stage);
CompileAndCheck(Stage.Handle, Glsl); CompileAndCheck(Stage.Handle, Program.Code);
} }
} }
public void SetConstBuffer(int Cbuf, byte[] Data) public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
{ {
if (Stages.TryGetValue(Tag, out ShaderStage Stage))
{
foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage.Where(x => x.Cbuf == Cbuf))
{
float Value = BitConverter.ToSingle(Data, DeclInfo.Index * 4);
}
}
} }
public void Bind(long Tag) public void Bind(long Tag)
@ -138,7 +156,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
} }
private string GetGlslCode(byte[] Data, GalShaderType Type) private GlslProgram GetGlslProgram(byte[] Data, GalShaderType Type)
{ {
int[] Code = new int[(Data.Length - 0x50) >> 2]; int[] Code = new int[(Data.Length - 0x50) >> 2];
@ -156,7 +174,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GlslDecompiler Decompiler = new GlslDecompiler(); GlslDecompiler Decompiler = new GlslDecompiler();
return Decompiler.Decompile(Code, Type).Code; return Decompiler.Decompile(Code, Type);
} }
private static void CompileAndCheck(int Handle, string Code) private static void CompileAndCheck(int Handle, string Code)

View file

@ -197,7 +197,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
case GalVertexAttribType.Sint: case GalVertexAttribType.Sint:
case GalVertexAttribType.Uint: case GalVertexAttribType.Uint:
case GalVertexAttribType.Uscaled: case GalVertexAttribType.Uscaled:
case GalVertexAttribType.Sscaled: case GalVertexAttribType.Sscaled:
{ {
switch (Attrib.Size) switch (Attrib.Size)
{ {
@ -287,7 +287,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
GL.ActiveTexture(TextureUnit.Texture0 + Index); GL.ActiveTexture(TextureUnit.Texture0 + Index);
GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle); GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
} }
public void CreateShader(long Tag, byte[] Data, GalShaderType Type) public void CreateShader(long Tag, byte[] Data, GalShaderType Type)
@ -300,14 +300,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
ActionsQueue.Enqueue(() => Shader.Create(Tag, Data, Type)); ActionsQueue.Enqueue(() => Shader.Create(Tag, Data, Type));
} }
public void SetShaderCb(int Cbuf, byte[] Data) public void SetShaderCb(long Tag, int Cbuf, byte[] Data)
{ {
if (Data == null) if (Data == null)
{ {
throw new ArgumentNullException(nameof(Data)); throw new ArgumentNullException(nameof(Data));
} }
ActionsQueue.Enqueue(() => Shader.SetConstBuffer(Cbuf, Data)); ActionsQueue.Enqueue(() => Shader.SetConstBuffer(Tag, Cbuf, Data));
} }
public void BindShader(long Tag) public void BindShader(long Tag)

View file

@ -16,15 +16,15 @@ namespace Ryujinx.Graphics.Gal.Shader
private static string[] ElemTypes = new string[] { "float", "vec2", "vec3", "vec4" }; private static string[] ElemTypes = new string[] { "float", "vec2", "vec3", "vec4" };
private Dictionary<int, GlslDeclInfo> Textures; private Dictionary<int, ShaderDeclInfo> Textures;
private Dictionary<(int, int), GlslDeclInfo> Uniforms; private Dictionary<(int, int), ShaderDeclInfo> Uniforms;
private Dictionary<int, GlslDeclInfo> InputAttributes; private Dictionary<int, ShaderDeclInfo> InAttributes;
private Dictionary<int, GlslDeclInfo> OutputAttributes; private Dictionary<int, ShaderDeclInfo> OutAttributes;
private Dictionary<int, GlslDeclInfo> Gprs; private Dictionary<int, ShaderDeclInfo> Gprs;
private Dictionary<int, GlslDeclInfo> Preds; private Dictionary<int, ShaderDeclInfo> Preds;
private const int AttrStartIndex = 8; private const int AttrStartIndex = 8;
private const int TexStartIndex = 8; private const int TexStartIndex = 8;
@ -74,26 +74,26 @@ namespace Ryujinx.Graphics.Gal.Shader
public GlslProgram Decompile(int[] Code, GalShaderType Type) public GlslProgram Decompile(int[] Code, GalShaderType Type)
{ {
Uniforms = new Dictionary<(int, int), GlslDeclInfo>(); Uniforms = new Dictionary<(int, int), ShaderDeclInfo>();
Textures = new Dictionary<int, GlslDeclInfo>(); Textures = new Dictionary<int, ShaderDeclInfo>();
InputAttributes = new Dictionary<int, GlslDeclInfo>(); InAttributes = new Dictionary<int, ShaderDeclInfo>();
OutputAttributes = new Dictionary<int, GlslDeclInfo>(); OutAttributes = new Dictionary<int, ShaderDeclInfo>();
Gprs = new Dictionary<int, GlslDeclInfo>(); Gprs = new Dictionary<int, ShaderDeclInfo>();
Preds = new Dictionary<int, GlslDeclInfo>(); Preds = new Dictionary<int, ShaderDeclInfo>();
SB = new StringBuilder(); SB = new StringBuilder();
//FIXME: Only valid for vertex shaders. //FIXME: Only valid for vertex shaders.
if (Type == GalShaderType.Fragment) if (Type == GalShaderType.Fragment)
{ {
Gprs.Add(0, new GlslDeclInfo("FragColor", 0, 0, 4)); Gprs.Add(0, new ShaderDeclInfo("FragColor", 0, 0, 4));
} }
else else
{ {
OutputAttributes.Add(7, new GlslDeclInfo("gl_Position", -1, 0, 4)); OutAttributes.Add(7, new ShaderDeclInfo("gl_Position", -1, 0, 4));
} }
ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0, Type); ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0, Type);
@ -116,15 +116,12 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintBlockScope("void main()", 1, Nodes); PrintBlockScope("void main()", 1, Nodes);
GlslProgram Program = new GlslProgram(); string GlslCode = SB.ToString();
Program.Code = SB.ToString(); return new GlslProgram(
GlslCode,
Program.Attributes = InputAttributes.Values.ToArray(); Textures.Values,
Uniforms.Values);
SB.Clear();
return Program;
} }
private void Traverse(ShaderIrNode Parent, ShaderIrNode Node) private void Traverse(ShaderIrNode Parent, ShaderIrNode Node)
@ -164,7 +161,7 @@ namespace Ryujinx.Graphics.Gal.Shader
string Name = $"{TextureName}{Index}"; string Name = $"{TextureName}{Index}";
Textures.TryAdd(Handle, new GlslDeclInfo(Name, Index)); Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Index));
} }
break; break;
} }
@ -173,7 +170,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Name = $"{UniformName}{Cbuf.Index}_{Cbuf.Offs}"; string Name = $"{UniformName}{Cbuf.Index}_{Cbuf.Offs}";
GlslDeclInfo DeclInfo = new GlslDeclInfo(Name, Cbuf.Offs, Cbuf.Index); ShaderDeclInfo DeclInfo = new ShaderDeclInfo(Name, Cbuf.Offs, Cbuf.Index);
Uniforms.TryAdd((Cbuf.Index, Cbuf.Offs), DeclInfo); Uniforms.TryAdd((Cbuf.Index, Cbuf.Offs), DeclInfo);
@ -187,24 +184,24 @@ namespace Ryujinx.Graphics.Gal.Shader
int GlslIndex = Index - AttrStartIndex; int GlslIndex = Index - AttrStartIndex;
GlslDeclInfo DeclInfo; ShaderDeclInfo DeclInfo;
if (Parent is ShaderIrAsg Asg && Asg.Dst == Node) if (Parent is ShaderIrAsg Asg && Asg.Dst == Node)
{ {
if (!OutputAttributes.TryGetValue(Index, out DeclInfo)) if (!OutAttributes.TryGetValue(Index, out DeclInfo))
{ {
DeclInfo = new GlslDeclInfo(OutputName + GlslIndex, GlslIndex); DeclInfo = new ShaderDeclInfo(OutputName + GlslIndex, GlslIndex);
OutputAttributes.Add(Index, DeclInfo); OutAttributes.Add(Index, DeclInfo);
} }
} }
else else
{ {
if (!InputAttributes.TryGetValue(Index, out DeclInfo)) if (!InAttributes.TryGetValue(Index, out DeclInfo))
{ {
DeclInfo = new GlslDeclInfo(InputAttrName + GlslIndex, GlslIndex); DeclInfo = new ShaderDeclInfo(InputAttrName + GlslIndex, GlslIndex);
InputAttributes.Add(Index, DeclInfo); InAttributes.Add(Index, DeclInfo);
} }
} }
@ -219,7 +216,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Name = $"{GprName}{Gpr.Index}"; string Name = $"{GprName}{Gpr.Index}";
Gprs.TryAdd(Gpr.Index, new GlslDeclInfo(Name, Gpr.Index)); Gprs.TryAdd(Gpr.Index, new ShaderDeclInfo(Name, Gpr.Index));
} }
break; break;
} }
@ -230,7 +227,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Name = $"{PredName}{Pred.Index}"; string Name = $"{PredName}{Pred.Index}";
Preds.TryAdd(Pred.Index, new GlslDeclInfo(Name, Pred.Index)); Preds.TryAdd(Pred.Index, new ShaderDeclInfo(Name, Pred.Index));
} }
break; break;
} }
@ -244,7 +241,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintDeclUniforms() private void PrintDeclUniforms()
{ {
foreach (GlslDeclInfo DeclInfo in Uniforms.Values.OrderBy(DeclKeySelector)) foreach (ShaderDeclInfo DeclInfo in Uniforms.Values.OrderBy(DeclKeySelector))
{ {
SB.AppendLine($"uniform {GetDecl(DeclInfo)};"); SB.AppendLine($"uniform {GetDecl(DeclInfo)};");
} }
@ -257,19 +254,19 @@ namespace Ryujinx.Graphics.Gal.Shader
private void PrintDeclInAttributes() private void PrintDeclInAttributes()
{ {
PrintDeclAttributes(InputAttributes.Values, "in"); PrintDeclAttributes(InAttributes.Values, "in");
} }
private void PrintDeclOutAttributes() private void PrintDeclOutAttributes()
{ {
PrintDeclAttributes(OutputAttributes.Values, "out"); PrintDeclAttributes(OutAttributes.Values, "out");
} }
private void PrintDeclAttributes(ICollection<GlslDeclInfo> Decls, string InOut) private void PrintDeclAttributes(ICollection<ShaderDeclInfo> Decls, string InOut)
{ {
bool PrintNl = false; bool PrintNl = false;
foreach (GlslDeclInfo DeclInfo in Decls.OrderBy(DeclKeySelector)) foreach (ShaderDeclInfo DeclInfo in Decls.OrderBy(DeclKeySelector))
{ {
if (DeclInfo.Index >= 0) if (DeclInfo.Index >= 0)
{ {
@ -295,9 +292,9 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintDecls(Preds.Values, "bool"); PrintDecls(Preds.Values, "bool");
} }
private void PrintDecls(ICollection<GlslDeclInfo> Decls, string CustomType = null) private void PrintDecls(ICollection<ShaderDeclInfo> Decls, string CustomType = null)
{ {
foreach (GlslDeclInfo DeclInfo in Decls.OrderBy(DeclKeySelector)) foreach (ShaderDeclInfo DeclInfo in Decls.OrderBy(DeclKeySelector))
{ {
string Name; string Name;
@ -319,12 +316,12 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
private int DeclKeySelector(GlslDeclInfo DeclInfo) private int DeclKeySelector(ShaderDeclInfo DeclInfo)
{ {
return DeclInfo.Cbuf << 24 | DeclInfo.Index; return DeclInfo.Cbuf << 24 | DeclInfo.Index;
} }
private string GetDecl(GlslDeclInfo DeclInfo) private string GetDecl(ShaderDeclInfo DeclInfo)
{ {
return $"{ElemTypes[DeclInfo.Size - 1]} {DeclInfo.Name}"; return $"{ElemTypes[DeclInfo.Size - 1]} {DeclInfo.Name}";
} }
@ -362,14 +359,9 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintBlockScope(SubScopeName, IdentationLevel + 1, Cond.Child); PrintBlockScope(SubScopeName, IdentationLevel + 1, Cond.Child);
} }
else if (Node is ShaderIrAsg Asg) else if (Node is ShaderIrAsg Asg && IsValidOutOper(Asg.Dst))
{ {
if (IsValidOutOper(Asg.Dst)) SB.AppendLine($"{Identation}{GetOutOperName(Asg.Dst)} = {GetInOperName(Asg.Src, true)};");
{
SB.AppendLine(Identation +
$"{GetOutOperName(Asg.Dst)} = " +
$"{GetInOperName (Asg.Src, true)};");
}
} }
else if (Node is ShaderIrOp Op) else if (Node is ShaderIrOp Op)
{ {
@ -469,7 +461,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetName(ShaderIrOperCbuf Cbuf) private string GetName(ShaderIrOperCbuf Cbuf)
{ {
if (!Uniforms.TryGetValue((Cbuf.Index, Cbuf.Offs), out GlslDeclInfo DeclInfo)) if (!Uniforms.TryGetValue((Cbuf.Index, Cbuf.Offs), out ShaderDeclInfo DeclInfo))
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
@ -479,20 +471,20 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetOutAbufName(ShaderIrOperAbuf Abuf) private string GetOutAbufName(ShaderIrOperAbuf Abuf)
{ {
return GetName(OutputAttributes, Abuf, Swizzle: true); return GetName(OutAttributes, Abuf, Swizzle: true);
} }
private string GetName(ShaderIrOperAbuf Abuf, bool Swizzle = true) private string GetName(ShaderIrOperAbuf Abuf, bool Swizzle = true)
{ {
return GetName(InputAttributes, Abuf, Swizzle); return GetName(InAttributes, Abuf, Swizzle);
} }
private string GetName(Dictionary<int, GlslDeclInfo> Decls, ShaderIrOperAbuf Abuf, bool Swizzle) private string GetName(Dictionary<int, ShaderDeclInfo> Decls, ShaderIrOperAbuf Abuf, bool Swizzle)
{ {
int Index = Abuf.Offs >> 4; int Index = Abuf.Offs >> 4;
int Elem = (Abuf.Offs >> 2) & 3; int Elem = (Abuf.Offs >> 2) & 3;
if (!Decls.TryGetValue(Index, out GlslDeclInfo DeclInfo)) if (!Decls.TryGetValue(Index, out ShaderDeclInfo DeclInfo))
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
@ -517,11 +509,11 @@ namespace Ryujinx.Graphics.Gal.Shader
return Pred.IsConst ? "true" : GetNameWithSwizzle(Preds, Pred.Index); return Pred.IsConst ? "true" : GetNameWithSwizzle(Preds, Pred.Index);
} }
private string GetNameWithSwizzle(Dictionary<int, GlslDeclInfo> Decls, int Index) private string GetNameWithSwizzle(Dictionary<int, ShaderDeclInfo> Decls, int Index)
{ {
int VecIndex = Index >> 2; int VecIndex = Index >> 2;
if (Decls.TryGetValue(VecIndex, out GlslDeclInfo DeclInfo)) if (Decls.TryGetValue(VecIndex, out ShaderDeclInfo DeclInfo))
{ {
if (DeclInfo.Size > 1 && Index < VecIndex + DeclInfo.Size) if (DeclInfo.Size > 1 && Index < VecIndex + DeclInfo.Size)
{ {
@ -674,7 +666,7 @@ namespace Ryujinx.Graphics.Gal.Shader
int Handle = ((ShaderIrOperImm)Op.OperandC).Imm; int Handle = ((ShaderIrOperImm)Op.OperandC).Imm;
if (!Textures.TryGetValue(Handle, out GlslDeclInfo DeclInfo)) if (!Textures.TryGetValue(Handle, out ShaderDeclInfo DeclInfo))
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }

View file

@ -1,10 +1,22 @@
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.Shader namespace Ryujinx.Graphics.Gal.Shader
{ {
struct GlslProgram struct GlslProgram
{ {
public string Code; public string Code { get; private set; }
public GlslDeclInfo[] ConstBuffers; public ICollection<ShaderDeclInfo> Textures { get; private set; }
public GlslDeclInfo[] Attributes; public ICollection<ShaderDeclInfo> Uniforms { get; private set; }
public GlslProgram(
string Code,
ICollection<ShaderDeclInfo> Textures,
ICollection<ShaderDeclInfo> Uniforms)
{
this.Code = Code;
this.Textures = Textures;
this.Uniforms = Uniforms;
}
} }
} }

View file

@ -1,6 +1,6 @@
namespace Ryujinx.Graphics.Gal.Shader namespace Ryujinx.Graphics.Gal
{ {
public class GlslDeclInfo public class ShaderDeclInfo
{ {
public string Name { get; private set; } public string Name { get; private set; }
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public int Cbuf { get; private set; } public int Cbuf { get; private set; }
public int Size { get; private set; } public int Size { get; private set; }
public GlslDeclInfo(string Name, int Index, int Cbuf = 0, int Size = 1) public ShaderDeclInfo(string Name, int Index, int Cbuf = 0, int Size = 1)
{ {
this.Name = Name; this.Name = Name;
this.Index = Index; this.Index = Index;
@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gal.Shader
this.Size = Size; this.Size = Size;
} }
public void Enlarge(int NewSize) internal void Enlarge(int NewSize)
{ {
if (Size < NewSize) if (Size < NewSize)
{ {

View file

@ -89,7 +89,23 @@ namespace Ryujinx.Graphics.Gpu
byte[] Code = AMemoryHelper.ReadBytes(Memory, Position, (uint)Size); byte[] Code = AMemoryHelper.ReadBytes(Memory, Position, (uint)Size);
Gpu.Renderer.CreateShader(Position, Code, GetTypeFromProgram(Index)); GalShaderType ShaderType = GetTypeFromProgram(Index);
Gpu.Renderer.CreateShader(Position, Code, ShaderType);
for (int Cbuf = 0; Cbuf < Cbs.Length; Cbuf++)
{
ConstBuffer Cb = Cbs[Cbuf];
if (Cb.Enabled)
{
long CbPosition = Cb.Position + (int)ShaderType * Cb.Size;
byte[] Data = AMemoryHelper.ReadBytes(Memory, CbPosition, (uint)Cb.Size);
Gpu.Renderer.SetShaderCb(Position, Cbuf, Data);
}
}
} }
} }
@ -155,10 +171,9 @@ namespace Ryujinx.Graphics.Gpu
if (TryGetCpuAddr(NvGpuEngine3dReg.CbAddress, out long Position)) if (TryGetCpuAddr(NvGpuEngine3dReg.CbAddress, out long Position))
{ {
Cbs[Index].Position = Position; Cbs[Index].Position = Position;
Cbs[Index].Enabled = Enabled;
Cbs[Index].Size = ReadRegister(NvGpuEngine3dReg.CbSize);
} }
Cbs[Index].Enabled = Enabled;
Cbs[Index].Size = ReadRegister(NvGpuEngine3dReg.CbSize);
} }
private int ReadCb(AMemory Memory, int Cbuf, int Offset) private int ReadCb(AMemory Memory, int Cbuf, int Offset)

View file

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu
{ {
public class NvGpuFifo public class NvGpuFifo
{ {
private const int MacrosCount = 32; private const int MacrosCount = 0x80;
private const int MacroIndexMask = MacrosCount - 1; private const int MacroIndexMask = MacrosCount - 1;
private NsGpu Gpu; private NsGpu Gpu;