Ryujinx/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs
Thomas Guillemard 884b4e5fd3 Initial non 2D textures support (#525)
* Initial non 2D textures support

- Shaders still need to be changed
- Some types aren't yet implemented

* Start implementing texture instructions suffixes

Fix wrong texture type with cube and TEXS

Also support array textures in TEX and TEX.B

Clean up TEX and TEXS coords managment

Fix TEXS.LL with non-2d textures

Implement TEX.AOFFI

Get the right arguments for TEX, TEXS and TLDS

Also, store suffix operands in appropriate values to support multiple
suffix combinaisons

* Support depth in read/writeTexture

Also support WrapR and detect mipmap

* Proper cube map textures support + fix TEXS.LZ

* Implement depth compare

* some code clean up

* Implement CubeMap textures in OGLTexture.Create

* Implement TLD4 and TLD4S

* Add Texture 1D support

* updates comments

* fix some code style issues

* Fix some nits + rename some things to be less confusing

* Remove GetSuffix local functions

* AOFFI => AOffI

* TextureType => GalTextureTarget

* finish renaming TextureType to TextureTarget

* Disable LL, LZ and LB support in the decompiler

This needs more work at the GL level (GLSL implementation should be
right)

* Revert "Disable LL, LZ and LB support in the decompiler"

This reverts commit 64536c3d9f673645faff3152838d1413c3203395.

* Fix TEXS ARRAY_2D index

* ImageFormat depth should be 1 for all image format

* Fix shader build issues with sampler1DShadow and texture

* Fix DC & AOFFI combinaison with TEX/TEXS

* Support AOFFI with TLD4 and TLD4S

* Fix shader compilation error for TLD4.AOFFI with no DC

* Fix binding isuses on the 2d copy engine

TODO: support 2d array copy

* Support 2D array copy operation in the 2D engine

This make every copy right in the GPU side.
Thie CPU copy probably needs to be updated

* Implement GetGpuSize + fix somes issues with 2d engine copies

TODO: mipmap level in it

* Don't throw an exception in the layer handling

* Fix because of rebase

* Reject 2d layers of non textures in 2d copy engine

* Add 3D textures and mipmap support on BlockLinearSwizzle

* Fix naming on new BitUtils methods

* gpu cache: Make sure to invalidate textures that doesn't have the same target

* Add the concept of layer count for array instead of using depth

Also cleanup GetGpuSize as Swizzle can compute the size with mipmap

* Support multi layer with mip map in ReadTexture

* Add more check for cache invalidation & remove cubemap and cubemap array code for now

Also fix compressed 2d array

* Fix texelFetchOffset shader build error

* Start looking into cube map again

Also add some way to log write in register in engines

* fix write register log levles

* Remove debug logs in WriteRegister

* Disable AOFFI support on non NVIDIA drivers

* Fix code align
2019-02-28 12:12:24 +11:00

313 lines
9 KiB
C#

using System;
namespace Ryujinx.Graphics.Gal.Shader
{
static partial class ShaderDecode
{
private static int Read(this long OpCode, int Position, int Mask)
{
return (int)(OpCode >> Position) & Mask;
}
private static bool Read(this long OpCode, int Position)
{
return ((OpCode >> Position) & 1) != 0;
}
private static int Branch(this long OpCode)
{
return ((int)(OpCode >> 20) << 8) >> 8;
}
private static bool HasArray(this long OpCode)
{
return OpCode.Read(0x1c);
}
private static ShaderIrOperAbuf[] Abuf20(this long OpCode)
{
int Abuf = OpCode.Read(20, 0x3ff);
int Size = OpCode.Read(47, 3);
ShaderIrOperGpr Vertex = OpCode.Gpr39();
ShaderIrOperAbuf[] Opers = new ShaderIrOperAbuf[Size + 1];
for (int Index = 0; Index <= Size; Index++)
{
Opers[Index] = new ShaderIrOperAbuf(Abuf + Index * 4, Vertex);
}
return Opers;
}
private static ShaderIrOperAbuf Abuf28(this long OpCode)
{
int Abuf = OpCode.Read(28, 0x3ff);
return new ShaderIrOperAbuf(Abuf, OpCode.Gpr39());
}
private static ShaderIrOperCbuf Cbuf34(this long OpCode)
{
return new ShaderIrOperCbuf(
OpCode.Read(34, 0x1f),
OpCode.Read(20, 0x3fff));
}
private static ShaderIrOperGpr Gpr8(this long OpCode)
{
return new ShaderIrOperGpr(OpCode.Read(8, 0xff));
}
private static ShaderIrOperGpr Gpr20(this long OpCode)
{
return new ShaderIrOperGpr(OpCode.Read(20, 0xff));
}
private static ShaderIrOperGpr Gpr39(this long OpCode)
{
return new ShaderIrOperGpr(OpCode.Read(39, 0xff));
}
private static ShaderIrOperGpr Gpr0(this long OpCode)
{
return new ShaderIrOperGpr(OpCode.Read(0, 0xff));
}
private static ShaderIrOperGpr Gpr28(this long OpCode)
{
return new ShaderIrOperGpr(OpCode.Read(28, 0xff));
}
private static ShaderIrOperGpr[] GprHalfVec8(this long OpCode)
{
return GetGprHalfVec2(OpCode.Read(8, 0xff), OpCode.Read(47, 3));
}
private static ShaderIrOperGpr[] GprHalfVec20(this long OpCode)
{
return GetGprHalfVec2(OpCode.Read(20, 0xff), OpCode.Read(28, 3));
}
private static ShaderIrOperGpr[] GetGprHalfVec2(int Gpr, int Mask)
{
if (Mask == 1)
{
//This value is used for FP32, the whole 32-bits register
//is used as each element on the vector.
return new ShaderIrOperGpr[]
{
new ShaderIrOperGpr(Gpr),
new ShaderIrOperGpr(Gpr)
};
}
ShaderIrOperGpr Low = new ShaderIrOperGpr(Gpr, 0);
ShaderIrOperGpr High = new ShaderIrOperGpr(Gpr, 1);
return new ShaderIrOperGpr[]
{
(Mask & 1) != 0 ? High : Low,
(Mask & 2) != 0 ? High : Low
};
}
private static ShaderIrOperGpr GprHalf0(this long OpCode, int HalfPart)
{
return new ShaderIrOperGpr(OpCode.Read(0, 0xff), HalfPart);
}
private static ShaderIrOperGpr GprHalf28(this long OpCode, int HalfPart)
{
return new ShaderIrOperGpr(OpCode.Read(28, 0xff), HalfPart);
}
private static ShaderIrOperImm Imm5_39(this long OpCode)
{
return new ShaderIrOperImm(OpCode.Read(39, 0x1f));
}
private static ShaderIrOperImm Imm13_36(this long OpCode)
{
return new ShaderIrOperImm(OpCode.Read(36, 0x1fff));
}
private static ShaderIrOperImm Imm32_20(this long OpCode)
{
return new ShaderIrOperImm((int)(OpCode >> 20));
}
private static ShaderIrOperImmf Immf32_20(this long OpCode)
{
return new ShaderIrOperImmf(BitConverter.Int32BitsToSingle((int)(OpCode >> 20)));
}
private static ShaderIrOperImm ImmU16_20(this long OpCode)
{
return new ShaderIrOperImm(OpCode.Read(20, 0xffff));
}
private static ShaderIrOperImm Imm19_20(this long OpCode)
{
int Value = OpCode.Read(20, 0x7ffff);
bool Neg = OpCode.Read(56);
if (Neg)
{
Value = -Value;
}
return new ShaderIrOperImm(Value);
}
private static ShaderIrOperImmf Immf19_20(this long OpCode)
{
uint Imm = (uint)(OpCode >> 20) & 0x7ffff;
bool Neg = OpCode.Read(56);
Imm <<= 12;
if (Neg)
{
Imm |= 0x80000000;
}
float Value = BitConverter.Int32BitsToSingle((int)Imm);
return new ShaderIrOperImmf(Value);
}
private static ShaderIrOperPred Pred0(this long OpCode)
{
return new ShaderIrOperPred(OpCode.Read(0, 7));
}
private static ShaderIrOperPred Pred3(this long OpCode)
{
return new ShaderIrOperPred(OpCode.Read(3, 7));
}
private static ShaderIrOperPred Pred12(this long OpCode)
{
return new ShaderIrOperPred(OpCode.Read(12, 7));
}
private static ShaderIrOperPred Pred29(this long OpCode)
{
return new ShaderIrOperPred(OpCode.Read(29, 7));
}
private static ShaderIrNode Pred39N(this long OpCode)
{
ShaderIrNode Node = OpCode.Pred39();
if (OpCode.Read(42))
{
Node = new ShaderIrOp(ShaderIrInst.Bnot, Node);
}
return Node;
}
private static ShaderIrOperPred Pred39(this long OpCode)
{
return new ShaderIrOperPred(OpCode.Read(39, 7));
}
private static ShaderIrOperPred Pred48(this long OpCode)
{
return new ShaderIrOperPred(OpCode.Read(48, 7));
}
private static ShaderIrInst Cmp(this long OpCode)
{
switch (OpCode.Read(49, 7))
{
case 1: return ShaderIrInst.Clt;
case 2: return ShaderIrInst.Ceq;
case 3: return ShaderIrInst.Cle;
case 4: return ShaderIrInst.Cgt;
case 5: return ShaderIrInst.Cne;
case 6: return ShaderIrInst.Cge;
}
throw new ArgumentException(nameof(OpCode));
}
private static ShaderIrInst CmpF(this long OpCode)
{
switch (OpCode.Read(48, 0xf))
{
case 0x1: return ShaderIrInst.Fclt;
case 0x2: return ShaderIrInst.Fceq;
case 0x3: return ShaderIrInst.Fcle;
case 0x4: return ShaderIrInst.Fcgt;
case 0x5: return ShaderIrInst.Fcne;
case 0x6: return ShaderIrInst.Fcge;
case 0x7: return ShaderIrInst.Fcnum;
case 0x8: return ShaderIrInst.Fcnan;
case 0x9: return ShaderIrInst.Fcltu;
case 0xa: return ShaderIrInst.Fcequ;
case 0xb: return ShaderIrInst.Fcleu;
case 0xc: return ShaderIrInst.Fcgtu;
case 0xd: return ShaderIrInst.Fcneu;
case 0xe: return ShaderIrInst.Fcgeu;
}
throw new ArgumentException(nameof(OpCode));
}
private static ShaderIrInst BLop45(this long OpCode)
{
switch (OpCode.Read(45, 3))
{
case 0: return ShaderIrInst.Band;
case 1: return ShaderIrInst.Bor;
case 2: return ShaderIrInst.Bxor;
}
throw new ArgumentException(nameof(OpCode));
}
private static ShaderIrInst BLop24(this long OpCode)
{
switch (OpCode.Read(24, 3))
{
case 0: return ShaderIrInst.Band;
case 1: return ShaderIrInst.Bor;
case 2: return ShaderIrInst.Bxor;
}
throw new ArgumentException(nameof(OpCode));
}
private static ShaderIrNode PredNode(this long OpCode, ShaderIrNode Node)
{
ShaderIrOperPred Pred = OpCode.PredNode();
if (Pred.Index != ShaderIrOperPred.UnusedIndex)
{
bool Inv = OpCode.Read(19);
Node = new ShaderIrCond(Pred, Node, Inv);
}
return Node;
}
private static ShaderIrOperPred PredNode(this long OpCode)
{
int Pred = OpCode.Read(16, 0xf);
if (Pred != 0xf)
{
Pred &= 7;
}
return new ShaderIrOperPred(Pred);
}
}
}