Support linear swizzling, upload compressed textures instead of decoding on the CPU (this is a bit faster)
This commit is contained in:
parent
8f0f1c489c
commit
36f85260bb
12 changed files with 411 additions and 74 deletions
|
@ -18,5 +18,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
throw new ArgumentException(nameof(Type));
|
||||
}
|
||||
|
||||
public static PixelInternalFormat GetCompressedTextureFormat(GalTextureFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case GalTextureFormat.BC1: return PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
|
||||
case GalTextureFormat.BC2: return PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
|
||||
case GalTextureFormat.BC3: return PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Format.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using OpenTK.Graphics.OpenGL;
|
||||
using Ryujinx.Graphics.Gal.Texture;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
|
@ -58,18 +57,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||
|
||||
const PixelInternalFormat Pif = PixelInternalFormat.Rgba;
|
||||
|
||||
int W = Texture.Width;
|
||||
int H = Texture.Height;
|
||||
|
||||
const PixelFormat Pf = PixelFormat.Rgba;
|
||||
byte[] Data = Texture.Data;
|
||||
|
||||
const PixelType Pt = PixelType.UnsignedByte;
|
||||
int Length = Data.Length;
|
||||
|
||||
byte[] Buffer = TextureDecoder.Decode(Texture);
|
||||
if (IsCompressedTextureFormat(Texture.Format))
|
||||
{
|
||||
PixelInternalFormat Pif = OGLEnumConverter.GetCompressedTextureFormat(Texture.Format);
|
||||
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, Pif, W, H, 0, Pf, Pt, Buffer);
|
||||
GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, Pif, W, H, 0, Length, Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Get those from Texture format.
|
||||
const PixelInternalFormat Pif = PixelInternalFormat.Rgba;
|
||||
|
||||
const PixelFormat Pf = PixelFormat.Rgba;
|
||||
|
||||
const PixelType Pt = PixelType.UnsignedByte;
|
||||
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, Pif, W, H, 0, Pf, Pt, Data);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsCompressedTextureFormat(GalTextureFormat Format)
|
||||
{
|
||||
return Format == GalTextureFormat.BC1 ||
|
||||
Format == GalTextureFormat.BC2 ||
|
||||
Format == GalTextureFormat.BC3;
|
||||
}
|
||||
|
||||
private int EnsureTextureInitialized(int TextureIndex)
|
||||
|
|
|
@ -64,45 +64,14 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Fmul);
|
||||
}
|
||||
|
||||
public static void Fsetp_R(ShaderIrBlock Block, long OpCode)
|
||||
{
|
||||
EmitFsetp(Block, OpCode, ShaderOper.RR);
|
||||
}
|
||||
|
||||
public static void Fsetp_C(ShaderIrBlock Block, long OpCode)
|
||||
{
|
||||
bool Aa = ((OpCode >> 7) & 1) != 0;
|
||||
bool Na = ((OpCode >> 43) & 1) != 0;
|
||||
bool Ab = ((OpCode >> 44) & 1) != 0;
|
||||
|
||||
ShaderIrNode OperA = GetOperGpr8 (OpCode);
|
||||
ShaderIrNode OperB = GetOperCbuf34(OpCode);
|
||||
|
||||
ShaderIrInst CmpInst = GetCmp(OpCode);
|
||||
|
||||
ShaderIrOp Op = new ShaderIrOp(CmpInst,
|
||||
GetAluAbsNeg(OperA, Aa, Na),
|
||||
GetAluAbs (OperB, Ab));
|
||||
|
||||
ShaderIrOperPred P0Node = GetOperPred3 (OpCode);
|
||||
ShaderIrOperPred P1Node = GetOperPred0 (OpCode);
|
||||
ShaderIrOperPred P2Node = GetOperPred39(OpCode);
|
||||
|
||||
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
|
||||
|
||||
ShaderIrInst LopInst = GetBLop(OpCode);
|
||||
|
||||
if (LopInst == ShaderIrInst.Band &&
|
||||
P1Node.Index == ShaderIrOperPred.UnusedIndex &&
|
||||
P2Node.Index == ShaderIrOperPred.UnusedIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderIrNode P2NNode = GetOperPred39N(OpCode);
|
||||
|
||||
Op = new ShaderIrOp(LopInst, new ShaderIrOp(ShaderIrInst.Bnot, P0Node), P2NNode);
|
||||
|
||||
Block.AddNode(GetPredNode(new ShaderIrAsg(P1Node, Op), OpCode));
|
||||
|
||||
Op = new ShaderIrOp(LopInst, P0Node, P2NNode);
|
||||
|
||||
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
|
||||
EmitFsetp(Block, OpCode, ShaderOper.CR);
|
||||
}
|
||||
|
||||
public static void Ipa(ShaderIrBlock Block, long OpCode)
|
||||
|
@ -211,6 +180,61 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
|
||||
}
|
||||
|
||||
private static void EmitFsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
|
||||
{
|
||||
bool Aa = ((OpCode >> 7) & 1) != 0;
|
||||
bool Np = ((OpCode >> 42) & 1) != 0;
|
||||
bool Na = ((OpCode >> 43) & 1) != 0;
|
||||
bool Ab = ((OpCode >> 44) & 1) != 0;
|
||||
|
||||
ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
|
||||
|
||||
switch (Oper)
|
||||
{
|
||||
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
|
||||
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
|
||||
case ShaderOper.Imm: OperB = GetOperImmf19_20(OpCode); break;
|
||||
|
||||
default: throw new ArgumentException(nameof(Oper));
|
||||
}
|
||||
|
||||
ShaderIrInst CmpInst = GetCmp(OpCode);
|
||||
|
||||
ShaderIrOp Op = new ShaderIrOp(CmpInst,
|
||||
GetAluAbsNeg(OperA, Aa, Na),
|
||||
GetAluAbs (OperB, Ab));
|
||||
|
||||
ShaderIrOperPred P0Node = GetOperPred3 (OpCode);
|
||||
ShaderIrOperPred P1Node = GetOperPred0 (OpCode);
|
||||
ShaderIrOperPred P2Node = GetOperPred39(OpCode);
|
||||
|
||||
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
|
||||
|
||||
ShaderIrInst LopInst = GetBLop(OpCode);
|
||||
|
||||
if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderIrNode P2NNode = P2Node;
|
||||
|
||||
if (Np)
|
||||
{
|
||||
P2NNode = new ShaderIrOp(ShaderIrInst.Bnot, P2NNode);
|
||||
}
|
||||
|
||||
Op = new ShaderIrOp(ShaderIrInst.Bnot, P0Node);
|
||||
|
||||
Op = new ShaderIrOp(LopInst, Op, P2NNode);
|
||||
|
||||
Block.AddNode(GetPredNode(new ShaderIrAsg(P1Node, Op), OpCode));
|
||||
|
||||
Op = new ShaderIrOp(LopInst, P0Node, P2NNode);
|
||||
|
||||
Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
|
||||
}
|
||||
|
||||
private static ShaderIrNode GetAluAbsNeg(ShaderIrNode Node, bool Abs, bool Neg)
|
||||
{
|
||||
return GetAluNeg(GetAluAbs(Node, Abs), Neg);
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
|||
Set("0101110001101x", ShaderDecode.Fmul_R);
|
||||
Set("0100110001101x", ShaderDecode.Fmul_C);
|
||||
Set("0011100x01101x", ShaderDecode.Fmul_Imm);
|
||||
Set("010110111011xx", ShaderDecode.Fsetp_R);
|
||||
Set("010010111011xx", ShaderDecode.Fsetp_C);
|
||||
Set("11100000xxxxxx", ShaderDecode.Ipa);
|
||||
Set("111000110011xx", ShaderDecode.Kil);
|
||||
|
|
57
Ryujinx.Graphics/Gpu/BlockLinearSwizzle.cs
Normal file
57
Ryujinx.Graphics/Gpu/BlockLinearSwizzle.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
class BlockLinearSwizzle : ISwizzle
|
||||
{
|
||||
private int BhShift;
|
||||
private int BppShift;
|
||||
private int BhMask;
|
||||
|
||||
private int XShift;
|
||||
private int GobStride;
|
||||
|
||||
public BlockLinearSwizzle(int Width, int Bpp, int BlockHeight = 16)
|
||||
{
|
||||
BhMask = (BlockHeight * 8) - 1;
|
||||
|
||||
BhShift = CountLsbZeros(BlockHeight * 8);
|
||||
BppShift = CountLsbZeros(Bpp);
|
||||
|
||||
int WidthInGobs = Width * Bpp / 64;
|
||||
|
||||
GobStride = 512 * BlockHeight * WidthInGobs;
|
||||
|
||||
XShift = CountLsbZeros(512 * BlockHeight);
|
||||
}
|
||||
|
||||
private int CountLsbZeros(int Value)
|
||||
{
|
||||
int Count = 0;
|
||||
|
||||
while (((Value >> Count) & 1) == 0)
|
||||
{
|
||||
Count++;
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
public int GetSwizzleOffset(int X, int Y)
|
||||
{
|
||||
X <<= BppShift;
|
||||
|
||||
int Position = (Y >> BhShift) * GobStride;
|
||||
|
||||
Position += (X >> 6) << XShift;
|
||||
|
||||
Position += ((Y & BhMask) >> 3) << 9;
|
||||
|
||||
Position += ((X & 0x3f) >> 5) << 8;
|
||||
Position += ((Y & 0x07) >> 1) << 6;
|
||||
Position += ((X & 0x1f) >> 4) << 5;
|
||||
Position += ((Y & 0x01) >> 0) << 4;
|
||||
Position += ((X & 0x0f) >> 0) << 0;
|
||||
|
||||
return Position;
|
||||
}
|
||||
}
|
||||
}
|
7
Ryujinx.Graphics/Gpu/ISwizzle.cs
Normal file
7
Ryujinx.Graphics/Gpu/ISwizzle.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
interface ISwizzle
|
||||
{
|
||||
int GetSwizzleOffset(int X, int Y);
|
||||
}
|
||||
}
|
20
Ryujinx.Graphics/Gpu/LinearSwizzle.cs
Normal file
20
Ryujinx.Graphics/Gpu/LinearSwizzle.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
class LinearSwizzle : ISwizzle
|
||||
{
|
||||
private int Bpp;
|
||||
private int Stride;
|
||||
|
||||
public LinearSwizzle(int Width, int Bpp)
|
||||
{
|
||||
this.Bpp = Bpp;
|
||||
|
||||
Stride = Width * Bpp;
|
||||
}
|
||||
|
||||
public int GetSwizzleOffset(int X, int Y)
|
||||
{
|
||||
return X * Bpp + Y * Stride;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -232,37 +232,9 @@ namespace Ryujinx.Graphics.Gpu
|
|||
|
||||
TryGetCpuAddr(NvGpuEngine3dReg.TexHeaderPoolOffset, out long TicPosition);
|
||||
|
||||
int[] Tic = ReadWords(Memory, TicPosition + TicIndex * 0x20, 8);
|
||||
TicPosition += TicIndex * 0x20;
|
||||
|
||||
GalTextureFormat Format = (GalTextureFormat)(Tic[0] & 0x7f);
|
||||
|
||||
long TextureAddress = (uint)Tic[1];
|
||||
|
||||
TextureAddress |= (long)((ushort)Tic[2]) << 32;
|
||||
|
||||
TextureAddress = Gpu.GetCpuAddr(TextureAddress);
|
||||
|
||||
int Width = (Tic[4] & 0xffff) + 1;
|
||||
int Height = (Tic[5] & 0xffff) + 1;
|
||||
|
||||
long TextureSize = GetTextureSize(Width, Height, Format);
|
||||
|
||||
byte[] Data = AMemoryHelper.ReadBytes(Memory, TextureAddress, TextureSize);
|
||||
|
||||
return new GalTexture(Data, Width, Height, Format);
|
||||
}
|
||||
|
||||
private long GetTextureSize(int Width, int Height, GalTextureFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case GalTextureFormat.A8B8G8R8: return (Width * Height) << 2;
|
||||
case GalTextureFormat.BC1: return (Width * Height) >> 1;
|
||||
case GalTextureFormat.BC2: return Width * Height;
|
||||
case GalTextureFormat.BC3: return Width * Height;
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Format.ToString());
|
||||
return TextureFactory.MakeTexture(Gpu, Memory, TicPosition);
|
||||
}
|
||||
|
||||
private int[] ReadWords(AMemory Memory, long Position, int Count)
|
||||
|
|
34
Ryujinx.Graphics/Gpu/Texture.cs
Normal file
34
Ryujinx.Graphics/Gpu/Texture.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using Ryujinx.Graphics.Gal;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
struct Texture
|
||||
{
|
||||
public long Position { get; private set; }
|
||||
|
||||
public int Width { get; private set; }
|
||||
public int Height { get; private set; }
|
||||
|
||||
public int BlockHeight { get; private set; }
|
||||
|
||||
public TextureSwizzle Swizzle { get; private set; }
|
||||
|
||||
public GalTextureFormat Format { get; private set; }
|
||||
|
||||
public Texture(
|
||||
long Position,
|
||||
int Width,
|
||||
int Height,
|
||||
int BlockHeight,
|
||||
TextureSwizzle Swizzle,
|
||||
GalTextureFormat Format)
|
||||
{
|
||||
this.Position = Position;
|
||||
this.Width = Width;
|
||||
this.Height = Height;
|
||||
this.BlockHeight = BlockHeight;
|
||||
this.Swizzle = Swizzle;
|
||||
this.Format = Format;
|
||||
}
|
||||
}
|
||||
}
|
54
Ryujinx.Graphics/Gpu/TextureFactory.cs
Normal file
54
Ryujinx.Graphics/Gpu/TextureFactory.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Graphics.Gal;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
static class TextureFactory
|
||||
{
|
||||
public static GalTexture MakeTexture(NsGpu Gpu, AMemory Memory, long TicPosition)
|
||||
{
|
||||
int[] Tic = ReadWords(Memory, TicPosition, 8);
|
||||
|
||||
GalTextureFormat Format = (GalTextureFormat)(Tic[0] & 0x7f);
|
||||
|
||||
long TextureAddress = (uint)Tic[1];
|
||||
|
||||
TextureAddress |= (long)((ushort)Tic[2]) << 32;
|
||||
|
||||
TextureAddress = Gpu.GetCpuAddr(TextureAddress);
|
||||
|
||||
TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7);
|
||||
|
||||
int BlockHeightLog2 = (Tic[3] >> 3) & 7;
|
||||
|
||||
int BlockHeight = 1 << BlockHeightLog2;
|
||||
|
||||
int Width = (Tic[4] & 0xffff) + 1;
|
||||
int Height = (Tic[5] & 0xffff) + 1;
|
||||
|
||||
Texture Texture = new Texture(
|
||||
TextureAddress,
|
||||
Width,
|
||||
Height,
|
||||
BlockHeight,
|
||||
Swizzle,
|
||||
Format);
|
||||
|
||||
byte[] Data = TextureReader.Read(Memory, Texture);
|
||||
|
||||
return new GalTexture(Data, Width, Height, Format);
|
||||
}
|
||||
|
||||
private static int[] ReadWords(AMemory Memory, long Position, int Count)
|
||||
{
|
||||
int[] Words = new int[Count];
|
||||
|
||||
for (int Index = 0; Index < Count; Index++, Position += 4)
|
||||
{
|
||||
Words[Index] = Memory.ReadInt32(Position);
|
||||
}
|
||||
|
||||
return Words;
|
||||
}
|
||||
}
|
||||
}
|
127
Ryujinx.Graphics/Gpu/TextureReader.cs
Normal file
127
Ryujinx.Graphics/Gpu/TextureReader.cs
Normal file
|
@ -0,0 +1,127 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Graphics.Gal;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
static class TextureReader
|
||||
{
|
||||
public static byte[] Read(AMemory Memory, Texture Texture)
|
||||
{
|
||||
switch (Texture.Format)
|
||||
{
|
||||
case GalTextureFormat.A8B8G8R8: return Read4Bpp (Memory, Texture);
|
||||
case GalTextureFormat.BC1: return Read8Bpt4x4 (Memory, Texture);
|
||||
case GalTextureFormat.BC2: return Read16Bpt4x4(Memory, Texture);
|
||||
case GalTextureFormat.BC3: return Read16Bpt4x4(Memory, Texture);
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Texture.Format.ToString());
|
||||
}
|
||||
|
||||
private unsafe static byte[] Read4Bpp(AMemory Memory, Texture Texture)
|
||||
{
|
||||
int Width = Texture.Width;
|
||||
int Height = Texture.Height;
|
||||
|
||||
byte[] Output = new byte[Width * Height * 4];
|
||||
|
||||
ISwizzle Swizzle = GetSwizzle(Texture.Swizzle, Width, 4, Texture.BlockHeight);
|
||||
|
||||
fixed (byte* BuffPtr = Output)
|
||||
{
|
||||
long OutOffs = 0;
|
||||
|
||||
for (int Y = 0; Y < Height; Y++)
|
||||
for (int X = 0; X < Width; X++)
|
||||
{
|
||||
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
|
||||
|
||||
int Pixel = Memory.ReadInt32Unchecked(Texture.Position + Offset);
|
||||
|
||||
*(int*)(BuffPtr + OutOffs) = Pixel;
|
||||
|
||||
OutOffs += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
private unsafe static byte[] Read8Bpt4x4(AMemory Memory, Texture Texture)
|
||||
{
|
||||
int Width = (Texture.Width + 3) / 4;
|
||||
int Height = (Texture.Height + 3) / 4;
|
||||
|
||||
byte[] Output = new byte[Width * Height * 8];
|
||||
|
||||
ISwizzle Swizzle = GetSwizzle(Texture.Swizzle, Width, 8, Texture.BlockHeight);
|
||||
|
||||
fixed (byte* BuffPtr = Output)
|
||||
{
|
||||
long OutOffs = 0;
|
||||
|
||||
for (int Y = 0; Y < Height; Y++)
|
||||
for (int X = 0; X < Width; X++)
|
||||
{
|
||||
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
|
||||
|
||||
long Tile = Memory.ReadInt64Unchecked(Texture.Position + Offset);
|
||||
|
||||
*(long*)(BuffPtr + OutOffs) = Tile;
|
||||
|
||||
OutOffs += 8;
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
private unsafe static byte[] Read16Bpt4x4(AMemory Memory, Texture Texture)
|
||||
{
|
||||
int Width = (Texture.Width + 3) / 4;
|
||||
int Height = (Texture.Height + 3) / 4;
|
||||
|
||||
byte[] Output = new byte[Width * Height * 16];
|
||||
|
||||
ISwizzle Swizzle = GetSwizzle(Texture.Swizzle, Width, 16, Texture.BlockHeight);
|
||||
|
||||
fixed (byte* BuffPtr = Output)
|
||||
{
|
||||
long OutOffs = 0;
|
||||
|
||||
for (int Y = 0; Y < Height; Y++)
|
||||
for (int X = 0; X < Width; X++)
|
||||
{
|
||||
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
|
||||
|
||||
long Tile0 = Memory.ReadInt64Unchecked(Texture.Position + Offset + 0);
|
||||
long Tile1 = Memory.ReadInt64Unchecked(Texture.Position + Offset + 8);
|
||||
|
||||
*(long*)(BuffPtr + OutOffs + 0) = Tile0;
|
||||
*(long*)(BuffPtr + OutOffs + 8) = Tile1;
|
||||
|
||||
OutOffs += 16;
|
||||
}
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
private static ISwizzle GetSwizzle(TextureSwizzle Swizzle, int Width, int Bpp, int BlockHeight)
|
||||
{
|
||||
switch (Swizzle)
|
||||
{
|
||||
case TextureSwizzle.Pitch:
|
||||
case TextureSwizzle.PitchColorKey:
|
||||
return new LinearSwizzle(Width, Bpp);
|
||||
|
||||
case TextureSwizzle.BlockLinear:
|
||||
case TextureSwizzle.BlockLinearColorKey:
|
||||
return new BlockLinearSwizzle(Width, Bpp, BlockHeight);
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Swizzle.ToString());
|
||||
}
|
||||
}
|
||||
}
|
11
Ryujinx.Graphics/Gpu/TextureSwizzle.cs
Normal file
11
Ryujinx.Graphics/Gpu/TextureSwizzle.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Ryujinx.Graphics.Gpu
|
||||
{
|
||||
enum TextureSwizzle
|
||||
{
|
||||
_1dBuffer = 0,
|
||||
PitchColorKey = 1,
|
||||
Pitch = 2,
|
||||
BlockLinear = 3,
|
||||
BlockLinearColorKey = 4
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue