New shader translator implementation (#654)

* Start implementing a new shader translator

* Fix shift instructions and a typo

* Small refactoring on StructuredProgram, move RemovePhis method to a separate class

* Initial geometry shader support

* Implement TLD4

* Fix -- There's no negation on FMUL32I

* Add constant folding and algebraic simplification optimizations, nits

* Some leftovers from constant folding

* Avoid cast for constant assignments

* Add a branch elimination pass, and misc small fixes

* Remove redundant branches, add expression propagation and other improvements on the code

* Small leftovers -- add missing break and continue, remove unused properties, other improvements

* Add null check to handle empty block cases on block visitor

* Add HADD2 and HMUL2 half float shader instructions

* Optimize pack/unpack sequences, some fixes related to half float instructions

* Add TXQ, TLD, TLDS and TLD4S shader texture instructions, and some support for bindless textures, some refactoring on codegen

* Fix copy paste mistake that caused RZ to be ignored on the AST instruction

* Add workaround for conditional exit, and fix half float instruction with constant buffer

* Add missing 0.0 source for TLDS.LZ variants

* Simplify the switch for TLDS.LZ

* Texture instructions related fixes

* Implement the HFMA instruction, and some misc. fixes

* Enable constant folding on UnpackHalf2x16 instructions

* Refactor HFMA to use OpCode* for opcode decoding rather than on the helper methods

* Remove the old shader translator

* Remove ShaderDeclInfo and other unused things

* Add dual vertex shader support

* Add ShaderConfig, used to pass shader type and maximum cbuffer size

* Move and rename some instruction enums

* Move texture instructions into a separate file

* Move operand GetExpression and locals management to OperandManager

* Optimize opcode decoding using a simple list and binary search

* Add missing condition for do-while on goto elimination

* Misc. fixes on texture instructions

* Simplify TLDS switch

* Address PR feedback, and a nit
This commit is contained in:
gdkchan 2019-04-17 20:57:08 -03:00 committed by jduncanator
parent b2e88b04a8
commit 6b23a2c125
207 changed files with 11514 additions and 6311 deletions

View file

@ -1,5 +1,6 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.Gal.Shader;
using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -51,54 +52,54 @@ namespace Ryujinx.Graphics.Gal.OpenGL
bool isDualVp,
GalShaderType type)
{
GlslProgram program;
ShaderConfig config = new ShaderConfig(type, OglLimit.MaxUboSize);
GlslDecompiler decompiler = new GlslDecompiler(OglLimit.MaxUboSize, OglExtension.NvidiaDriver);
int shaderDumpIndex = ShaderDumper.DumpIndex;
ShaderProgram program;
if (isDualVp)
{
ShaderDumper.Dump(memory, position, type, "a");
ShaderDumper.Dump(memory, positionB, type, "b");
program = decompiler.Decompile(memory, position, positionB, type);
program = Translator.Translate(memory, (ulong)position, (ulong)positionB, config);
}
else
{
ShaderDumper.Dump(memory, position, type);
program = decompiler.Decompile(memory, position, type);
program = Translator.Translate(memory, (ulong)position, config);
}
string code = program.Code;
if (ShaderDumper.IsDumpEnabled())
{
int shaderDumpIndex = ShaderDumper.DumpIndex;
code = "//Shader " + shaderDumpIndex + Environment.NewLine + code;
}
return new OglShaderStage(type, code, program.Uniforms, program.Textures);
return new OglShaderStage(type, code, program.Info.CBuffers, program.Info.Textures);
}
public IEnumerable<ShaderDeclInfo> GetConstBufferUsage(long key)
public IEnumerable<CBufferDescriptor> GetConstBufferUsage(long key)
{
if (_stages.TryGetValue(key, out OglShaderStage stage))
{
return stage.ConstBufferUsage;
}
return Enumerable.Empty<ShaderDeclInfo>();
return Enumerable.Empty<CBufferDescriptor>();
}
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long key)
public IEnumerable<TextureDescriptor> GetTextureUsage(long key)
{
if (_stages.TryGetValue(key, out OglShaderStage stage))
{
return stage.TextureUsage;
}
return Enumerable.Empty<ShaderDeclInfo>();
return Enumerable.Empty<TextureDescriptor>();
}
public unsafe void SetExtraData(float flipX, float flipY, int instance)
@ -130,16 +131,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void Bind(OglShaderStage stage)
{
if (stage.Type == GalShaderType.Geometry)
{
//Enhanced layouts are required for Geometry shaders
//skip this stage if current driver has no ARB_enhanced_layouts
if (!OglExtension.EnhancedLayouts)
{
return;
}
}
switch (stage.Type)
{
case GalShaderType.Vertex: Current.Vertex = stage; break;
@ -221,7 +212,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void BindUniformBlocks(int programHandle)
{
int extraBlockindex = GL.GetUniformBlockIndex(programHandle, GlslDecl.ExtraUniformBlockName);
int extraBlockindex = GL.GetUniformBlockIndex(programHandle, "Extra");
GL.UniformBlockBinding(programHandle, extraBlockindex, 0);
@ -231,14 +222,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
if (stage != null)
{
foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage)
foreach (CBufferDescriptor desc in stage.ConstBufferUsage)
{
int blockIndex = GL.GetUniformBlockIndex(programHandle, declInfo.Name);
int blockIndex = GL.GetUniformBlockIndex(programHandle, desc.Name);
if (blockIndex < 0)
{
//It is expected that its found, if it's not then driver might be in a malfunction
throw new InvalidOperationException();
//This may be fine, the compiler may optimize away unused uniform buffers,
//and in this case the above call would return -1 as the buffer has been
//optimized away.
continue;
}
GL.UniformBlockBinding(programHandle, blockIndex, freeBinding);
@ -263,9 +256,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
if (stage != null)
{
foreach (ShaderDeclInfo decl in stage.TextureUsage)
foreach (TextureDescriptor desc in stage.TextureUsage)
{
int location = GL.GetUniformLocation(programHandle, decl.Name);
int location = GL.GetUniformLocation(programHandle, desc.Name);
GL.Uniform1(location, index);