diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-06-23 21:39:25 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-23 21:39:25 -0300 |
| commit | e7559f128f99058774a8d53aa45213b51c085e76 (patch) | |
| tree | 42d367bfb4248b19cf2ce55439d24437bbbd2ccb /Ryujinx.HLE/Gpu/Texture | |
| parent | 69697957e6406235d512a89d9144c160fe7efbfd (diff) | |
Small OpenGL Renderer refactoring (#177)
* Call OpenGL functions directly, remove the pfifo thread, some refactoring
* Fix PerformanceStatistics calculating the wrong host fps, remove wait event on PFIFO as this wasn't exactly was causing the freezes (may replace with an exception later)
* Organized the Gpu folder a bit more, renamed a few things, address PR feedback
* Make PerformanceStatistics thread safe
* Remove unused constant
* Use unlimited update rate for better pref
Diffstat (limited to 'Ryujinx.HLE/Gpu/Texture')
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/BlockLinearSwizzle.cs | 59 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/ISwizzle.cs | 7 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/LinearSwizzle.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/TextureFactory.cs | 117 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/TextureHelper.cs | 78 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/TextureInfo.cs | 55 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/TextureReader.cs | 344 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/TextureSwizzle.cs | 11 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Texture/TextureWriter.cs | 55 |
9 files changed, 745 insertions, 0 deletions
diff --git a/Ryujinx.HLE/Gpu/Texture/BlockLinearSwizzle.cs b/Ryujinx.HLE/Gpu/Texture/BlockLinearSwizzle.cs new file mode 100644 index 00000000..e66d7613 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/BlockLinearSwizzle.cs @@ -0,0 +1,59 @@ +using System; + +namespace Ryujinx.HLE.Gpu.Texture +{ + 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 = (int)MathF.Ceiling(Width * Bpp / 64f); + + 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; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Texture/ISwizzle.cs b/Ryujinx.HLE/Gpu/Texture/ISwizzle.cs new file mode 100644 index 00000000..222aab16 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/ISwizzle.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.HLE.Gpu.Texture +{ + interface ISwizzle + { + int GetSwizzleOffset(int X, int Y); + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Texture/LinearSwizzle.cs b/Ryujinx.HLE/Gpu/Texture/LinearSwizzle.cs new file mode 100644 index 00000000..720f7832 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/LinearSwizzle.cs @@ -0,0 +1,19 @@ +namespace Ryujinx.HLE.Gpu.Texture +{ + class LinearSwizzle : ISwizzle + { + private int Pitch; + private int Bpp; + + public LinearSwizzle(int Pitch, int Bpp) + { + this.Pitch = Pitch; + this.Bpp = Bpp; + } + + public int GetSwizzleOffset(int X, int Y) + { + return X * Bpp + Y * Pitch; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs b/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs new file mode 100644 index 00000000..9df0b600 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs @@ -0,0 +1,117 @@ +using Ryujinx.Graphics.Gal; +using Ryujinx.HLE.Gpu.Memory; +using System; + +namespace Ryujinx.HLE.Gpu.Texture +{ + static class TextureFactory + { + public static GalTexture MakeTexture(NvGpuVmm Vmm, long TicPosition) + { + int[] Tic = ReadWords(Vmm, TicPosition, 8); + + GalTextureFormat Format = (GalTextureFormat)(Tic[0] & 0x7f); + + GalTextureSource XSource = (GalTextureSource)((Tic[0] >> 19) & 7); + GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7); + GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7); + GalTextureSource WSource = (GalTextureSource)((Tic[0] >> 28) & 7); + + int Width = (Tic[4] & 0xffff) + 1; + int Height = (Tic[5] & 0xffff) + 1; + + return new GalTexture( + Width, + Height, + Format, + XSource, + YSource, + ZSource, + WSource); + } + + public static byte[] GetTextureData(NvGpuVmm Vmm, long TicPosition) + { + int[] Tic = ReadWords(Vmm, TicPosition, 8); + + GalTextureFormat Format = (GalTextureFormat)(Tic[0] & 0x7f); + + long TextureAddress = (uint)Tic[1]; + + TextureAddress |= (long)((ushort)Tic[2]) << 32; + + TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7); + + if (Swizzle == TextureSwizzle.BlockLinear || + Swizzle == TextureSwizzle.BlockLinearColorKey) + { + TextureAddress &= ~0x1ffL; + } + else if (Swizzle == TextureSwizzle.Pitch || + Swizzle == TextureSwizzle.PitchColorKey) + { + TextureAddress &= ~0x1fL; + } + + int Pitch = (Tic[3] & 0xffff) << 5; + + int BlockHeightLog2 = (Tic[3] >> 3) & 7; + + int BlockHeight = 1 << BlockHeightLog2; + + int Width = (Tic[4] & 0xffff) + 1; + int Height = (Tic[5] & 0xffff) + 1; + + TextureInfo Texture = new TextureInfo( + TextureAddress, + Width, + Height, + Pitch, + BlockHeight, + Swizzle, + Format); + + return TextureReader.Read(Vmm, Texture); + } + + public static GalTextureSampler MakeSampler(NvGpu Gpu, NvGpuVmm Vmm, long TscPosition) + { + int[] Tsc = ReadWords(Vmm, TscPosition, 8); + + GalTextureWrap AddressU = (GalTextureWrap)((Tsc[0] >> 0) & 7); + GalTextureWrap AddressV = (GalTextureWrap)((Tsc[0] >> 3) & 7); + GalTextureWrap AddressP = (GalTextureWrap)((Tsc[0] >> 6) & 7); + + GalTextureFilter MagFilter = (GalTextureFilter) ((Tsc[1] >> 0) & 3); + GalTextureFilter MinFilter = (GalTextureFilter) ((Tsc[1] >> 4) & 3); + GalTextureMipFilter MipFilter = (GalTextureMipFilter)((Tsc[1] >> 6) & 3); + + GalColorF BorderColor = new GalColorF( + BitConverter.Int32BitsToSingle(Tsc[4]), + BitConverter.Int32BitsToSingle(Tsc[5]), + BitConverter.Int32BitsToSingle(Tsc[6]), + BitConverter.Int32BitsToSingle(Tsc[7])); + + return new GalTextureSampler( + AddressU, + AddressV, + AddressP, + MinFilter, + MagFilter, + MipFilter, + BorderColor); + } + + private static int[] ReadWords(NvGpuVmm Vmm, long Position, int Count) + { + int[] Words = new int[Count]; + + for (int Index = 0; Index < Count; Index++, Position += 4) + { + Words[Index] = Vmm.ReadInt32(Position); + } + + return Words; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs b/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs new file mode 100644 index 00000000..ac8f75c5 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs @@ -0,0 +1,78 @@ +using ChocolArm64.Memory; +using Ryujinx.Graphics.Gal; +using Ryujinx.HLE.Gpu.Memory; +using System; + +namespace Ryujinx.HLE.Gpu.Texture +{ + static class TextureHelper + { + public static ISwizzle GetSwizzle(TextureInfo Texture, int Width, int Bpp) + { + switch (Texture.Swizzle) + { + case TextureSwizzle._1dBuffer: + case TextureSwizzle.Pitch: + case TextureSwizzle.PitchColorKey: + return new LinearSwizzle(Texture.Pitch, Bpp); + + case TextureSwizzle.BlockLinear: + case TextureSwizzle.BlockLinearColorKey: + return new BlockLinearSwizzle(Width, Bpp, Texture.BlockHeight); + } + + throw new NotImplementedException(Texture.Swizzle.ToString()); + } + + public static int GetTextureSize(GalTexture Texture) + { + switch (Texture.Format) + { + case GalTextureFormat.R32G32B32A32: return Texture.Width * Texture.Height * 16; + case GalTextureFormat.R16G16B16A16: return Texture.Width * Texture.Height * 8; + case GalTextureFormat.A8B8G8R8: return Texture.Width * Texture.Height * 4; + case GalTextureFormat.R32: return Texture.Width * Texture.Height * 4; + case GalTextureFormat.A1B5G5R5: return Texture.Width * Texture.Height * 2; + case GalTextureFormat.B5G6R5: return Texture.Width * Texture.Height * 2; + case GalTextureFormat.G8R8: return Texture.Width * Texture.Height * 2; + case GalTextureFormat.R16: return Texture.Width * Texture.Height * 2; + case GalTextureFormat.R8: return Texture.Width * Texture.Height; + + case GalTextureFormat.BC1: + case GalTextureFormat.BC4: + { + int W = (Texture.Width + 3) / 4; + int H = (Texture.Height + 3) / 4; + + return W * H * 8; + } + + case GalTextureFormat.BC7U: + case GalTextureFormat.BC2: + case GalTextureFormat.BC3: + case GalTextureFormat.BC5: + case GalTextureFormat.Astc2D4x4: + { + int W = (Texture.Width + 3) / 4; + int H = (Texture.Height + 3) / 4; + + return W * H * 16; + } + } + + throw new NotImplementedException(Texture.Format.ToString()); + } + + public static (AMemory Memory, long Position) GetMemoryAndPosition( + IAMemory Memory, + long Position) + { + if (Memory is NvGpuVmm Vmm) + { + return (Vmm.Memory, Vmm.GetPhysicalAddress(Position)); + } + + return ((AMemory)Memory, Position); + } + } +} diff --git a/Ryujinx.HLE/Gpu/Texture/TextureInfo.cs b/Ryujinx.HLE/Gpu/Texture/TextureInfo.cs new file mode 100644 index 00000000..31784bbc --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/TextureInfo.cs @@ -0,0 +1,55 @@ +using Ryujinx.Graphics.Gal; + +namespace Ryujinx.HLE.Gpu.Texture +{ + struct TextureInfo + { + public long Position { get; private set; } + + public int Width { get; private set; } + public int Height { get; private set; } + public int Pitch { get; private set; } + + public int BlockHeight { get; private set; } + + public TextureSwizzle Swizzle { get; private set; } + + public GalTextureFormat Format { get; private set; } + + public TextureInfo( + long Position, + int Width, + int Height) + { + this.Position = Position; + this.Width = Width; + this.Height = Height; + + Pitch = 0; + + BlockHeight = 16; + + Swizzle = TextureSwizzle.BlockLinear; + + Format = GalTextureFormat.A8B8G8R8; + } + + public TextureInfo( + long Position, + int Width, + int Height, + int Pitch, + int BlockHeight, + TextureSwizzle Swizzle, + GalTextureFormat Format) + { + this.Position = Position; + this.Width = Width; + this.Height = Height; + this.Pitch = Pitch; + this.BlockHeight = BlockHeight; + this.Swizzle = Swizzle; + this.Format = Format; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Texture/TextureReader.cs b/Ryujinx.HLE/Gpu/Texture/TextureReader.cs new file mode 100644 index 00000000..48bf1a90 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/TextureReader.cs @@ -0,0 +1,344 @@ +using ChocolArm64.Memory; +using Ryujinx.Graphics.Gal; +using System; + +namespace Ryujinx.HLE.Gpu.Texture +{ + static class TextureReader + { + public static byte[] Read(IAMemory Memory, TextureInfo Texture) + { + switch (Texture.Format) + { + case GalTextureFormat.R32G32B32A32: return Read16Bpp (Memory, Texture); + case GalTextureFormat.R16G16B16A16: return Read8Bpp (Memory, Texture); + case GalTextureFormat.A8B8G8R8: return Read4Bpp (Memory, Texture); + case GalTextureFormat.R32: return Read4Bpp (Memory, Texture); + case GalTextureFormat.A1B5G5R5: return Read5551 (Memory, Texture); + case GalTextureFormat.B5G6R5: return Read565 (Memory, Texture); + case GalTextureFormat.G8R8: return Read2Bpp (Memory, Texture); + case GalTextureFormat.R16: return Read2Bpp (Memory, Texture); + case GalTextureFormat.R8: return Read1Bpp (Memory, Texture); + case GalTextureFormat.BC7U: return Read16Bpt4x4(Memory, Texture); + case GalTextureFormat.BC1: return Read8Bpt4x4 (Memory, Texture); + case GalTextureFormat.BC2: return Read16Bpt4x4(Memory, Texture); + case GalTextureFormat.BC3: return Read16Bpt4x4(Memory, Texture); + case GalTextureFormat.BC4: return Read8Bpt4x4 (Memory, Texture); + case GalTextureFormat.BC5: return Read16Bpt4x4(Memory, Texture); + case GalTextureFormat.Astc2D4x4: return Read16Bpt4x4(Memory, Texture); + } + + throw new NotImplementedException(Texture.Format.ToString()); + } + + private unsafe static byte[] Read1Bpp(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 1); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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); + + byte Pixel = CpuMem.ReadByteUnchecked(Position + Offset); + + *(BuffPtr + OutOffs) = Pixel; + + OutOffs++; + } + } + + return Output; + } + + private unsafe static byte[] Read5551(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height * 2]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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); + + uint Pixel = (uint)CpuMem.ReadInt16Unchecked(Position + Offset); + + Pixel = (Pixel & 0x001f) << 11 | + (Pixel & 0x03e0) << 1 | + (Pixel & 0x7c00) >> 9 | + (Pixel & 0x8000) >> 15; + + *(short*)(BuffPtr + OutOffs) = (short)Pixel; + + OutOffs += 2; + } + } + + return Output; + } + + private unsafe static byte[] Read565(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height * 2]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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); + + uint Pixel = (uint)CpuMem.ReadInt16Unchecked(Position + Offset); + + Pixel = (Pixel & 0x001f) << 11 | + (Pixel & 0x07e0) | + (Pixel & 0xf800) >> 11; + + *(short*)(BuffPtr + OutOffs) = (short)Pixel; + + OutOffs += 2; + } + } + + return Output; + } + + private unsafe static byte[] Read2Bpp(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height * 2]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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); + + short Pixel = CpuMem.ReadInt16Unchecked(Position + Offset); + + *(short*)(BuffPtr + OutOffs) = Pixel; + + OutOffs += 2; + } + } + + return Output; + } + + private unsafe static byte[] Read4Bpp(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height * 4]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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 = CpuMem.ReadInt32Unchecked(Position + Offset); + + *(int*)(BuffPtr + OutOffs) = Pixel; + + OutOffs += 4; + } + } + + return Output; + } + + private unsafe static byte[] Read8Bpp(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height * 8]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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 Pixel = CpuMem.ReadInt64Unchecked(Position + Offset); + + *(long*)(BuffPtr + OutOffs) = Pixel; + + OutOffs += 8; + } + } + + return Output; + } + + private unsafe static byte[] Read16Bpp(IAMemory Memory, TextureInfo Texture) + { + int Width = Texture.Width; + int Height = Texture.Height; + + byte[] Output = new byte[Width * Height * 16]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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 PxLow = CpuMem.ReadInt64Unchecked(Position + Offset + 0); + long PxHigh = CpuMem.ReadInt64Unchecked(Position + Offset + 8); + + *(long*)(BuffPtr + OutOffs + 0) = PxLow; + *(long*)(BuffPtr + OutOffs + 8) = PxHigh; + + OutOffs += 16; + } + } + + return Output; + } + + private unsafe static byte[] Read8Bpt4x4(IAMemory Memory, TextureInfo Texture) + { + int Width = (Texture.Width + 3) / 4; + int Height = (Texture.Height + 3) / 4; + + byte[] Output = new byte[Width * Height * 8]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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 = CpuMem.ReadInt64Unchecked(Position + Offset); + + *(long*)(BuffPtr + OutOffs) = Tile; + + OutOffs += 8; + } + } + + return Output; + } + + private unsafe static byte[] Read16Bpt4x4(IAMemory Memory, TextureInfo Texture) + { + int Width = (Texture.Width + 3) / 4; + int Height = (Texture.Height + 3) / 4; + + byte[] Output = new byte[Width * Height * 16]; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + 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 = CpuMem.ReadInt64Unchecked(Position + Offset + 0); + long Tile1 = CpuMem.ReadInt64Unchecked(Position + Offset + 8); + + *(long*)(BuffPtr + OutOffs + 0) = Tile0; + *(long*)(BuffPtr + OutOffs + 8) = Tile1; + + OutOffs += 16; + } + } + + return Output; + } + } +} diff --git a/Ryujinx.HLE/Gpu/Texture/TextureSwizzle.cs b/Ryujinx.HLE/Gpu/Texture/TextureSwizzle.cs new file mode 100644 index 00000000..076df97a --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/TextureSwizzle.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.HLE.Gpu.Texture +{ + enum TextureSwizzle + { + _1dBuffer = 0, + PitchColorKey = 1, + Pitch = 2, + BlockLinear = 3, + BlockLinearColorKey = 4 + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Texture/TextureWriter.cs b/Ryujinx.HLE/Gpu/Texture/TextureWriter.cs new file mode 100644 index 00000000..b64302a5 --- /dev/null +++ b/Ryujinx.HLE/Gpu/Texture/TextureWriter.cs @@ -0,0 +1,55 @@ +using ChocolArm64.Memory; +using Ryujinx.Graphics.Gal; +using System; + +namespace Ryujinx.HLE.Gpu.Texture +{ + static class TextureWriter + { + public static void Write( + IAMemory Memory, + TextureInfo Texture, + byte[] Data, + int Width, + int Height) + { + switch (Texture.Format) + { + case GalTextureFormat.A8B8G8R8: Write4Bpp(Memory, Texture, Data, Width, Height); break; + + default: throw new NotImplementedException(Texture.Format.ToString()); + } + } + + private unsafe static void Write4Bpp( + IAMemory Memory, + TextureInfo Texture, + byte[] Data, + int Width, + int Height) + { + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4); + + (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition( + Memory, + Texture.Position); + + fixed (byte* BuffPtr = Data) + { + long InOffs = 0; + + for (int Y = 0; Y < Height; Y++) + for (int X = 0; X < Width; X++) + { + long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); + + int Pixel = *(int*)(BuffPtr + InOffs); + + CpuMem.WriteInt32Unchecked(Position + Offset, Pixel); + + InOffs += 4; + } + } + } + } +} |
