TextureReader.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. using ChocolArm64.Memory;
  2. using Ryujinx.Graphics.Gal;
  3. using System;
  4. namespace Ryujinx.HLE.Gpu.Texture
  5. {
  6. static class TextureReader
  7. {
  8. public static byte[] Read(IAMemory Memory, TextureInfo Texture)
  9. {
  10. switch (Texture.Format)
  11. {
  12. case GalTextureFormat.R32G32B32A32: return Read16Bpp (Memory, Texture);
  13. case GalTextureFormat.R16G16B16A16: return Read8Bpp (Memory, Texture);
  14. case GalTextureFormat.A8B8G8R8: return Read4Bpp (Memory, Texture);
  15. case GalTextureFormat.A2B10G10R10: return Read4Bpp (Memory, Texture);
  16. case GalTextureFormat.R32: return Read4Bpp (Memory, Texture);
  17. case GalTextureFormat.BF10GF11RF11: return Read4Bpp (Memory, Texture);
  18. case GalTextureFormat.Z24S8: return Read4Bpp (Memory, Texture);
  19. case GalTextureFormat.A1B5G5R5: return Read5551 (Memory, Texture);
  20. case GalTextureFormat.B5G6R5: return Read565 (Memory, Texture);
  21. case GalTextureFormat.G8R8: return Read2Bpp (Memory, Texture);
  22. case GalTextureFormat.R16: return Read2Bpp (Memory, Texture);
  23. case GalTextureFormat.R8: return Read1Bpp (Memory, Texture);
  24. case GalTextureFormat.BC6H_SF16: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  25. case GalTextureFormat.BC6H_UF16: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  26. case GalTextureFormat.BC7U: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  27. case GalTextureFormat.BC1: return Read8Bpt4x4 (Memory, Texture);
  28. case GalTextureFormat.BC2: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  29. case GalTextureFormat.BC3: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  30. case GalTextureFormat.BC4: return Read8Bpt4x4 (Memory, Texture);
  31. case GalTextureFormat.BC5: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  32. case GalTextureFormat.ZF32: return Read4Bpp (Memory, Texture);
  33. case GalTextureFormat.Astc2D4x4: return Read16BptCompressedTexture(Memory, Texture, 4, 4);
  34. case GalTextureFormat.Astc2D5x5: return Read16BptCompressedTexture(Memory, Texture, 5, 5);
  35. case GalTextureFormat.Astc2D6x6: return Read16BptCompressedTexture(Memory, Texture, 6, 6);
  36. case GalTextureFormat.Astc2D8x8: return Read16BptCompressedTexture(Memory, Texture, 8, 8);
  37. case GalTextureFormat.Astc2D10x10: return Read16BptCompressedTexture(Memory, Texture, 10, 10);
  38. case GalTextureFormat.Astc2D12x12: return Read16BptCompressedTexture(Memory, Texture, 12, 12);
  39. case GalTextureFormat.Astc2D5x4: return Read16BptCompressedTexture(Memory, Texture, 5, 4);
  40. case GalTextureFormat.Astc2D6x5: return Read16BptCompressedTexture(Memory, Texture, 6, 5);
  41. case GalTextureFormat.Astc2D8x6: return Read16BptCompressedTexture(Memory, Texture, 8, 6);
  42. case GalTextureFormat.Astc2D10x8: return Read16BptCompressedTexture(Memory, Texture, 10, 8);
  43. case GalTextureFormat.Astc2D12x10: return Read16BptCompressedTexture(Memory, Texture, 12, 10);
  44. case GalTextureFormat.Astc2D8x5: return Read16BptCompressedTexture(Memory, Texture, 8, 5);
  45. case GalTextureFormat.Astc2D10x5: return Read16BptCompressedTexture(Memory, Texture, 10, 5);
  46. case GalTextureFormat.Astc2D10x6: return Read16BptCompressedTexture(Memory, Texture, 10, 6);
  47. }
  48. throw new NotImplementedException(Texture.Format.ToString());
  49. }
  50. private unsafe static byte[] Read1Bpp(IAMemory Memory, TextureInfo Texture)
  51. {
  52. int Width = Texture.Width;
  53. int Height = Texture.Height;
  54. byte[] Output = new byte[Width * Height];
  55. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 1);
  56. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  57. Memory,
  58. Texture.Position);
  59. fixed (byte* BuffPtr = Output)
  60. {
  61. long OutOffs = 0;
  62. for (int Y = 0; Y < Height; Y++)
  63. for (int X = 0; X < Width; X++)
  64. {
  65. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  66. byte Pixel = CpuMem.ReadByteUnchecked(Position + Offset);
  67. *(BuffPtr + OutOffs) = Pixel;
  68. OutOffs++;
  69. }
  70. }
  71. return Output;
  72. }
  73. private unsafe static byte[] Read5551(IAMemory Memory, TextureInfo Texture)
  74. {
  75. int Width = Texture.Width;
  76. int Height = Texture.Height;
  77. byte[] Output = new byte[Width * Height * 2];
  78. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
  79. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  80. Memory,
  81. Texture.Position);
  82. fixed (byte* BuffPtr = Output)
  83. {
  84. long OutOffs = 0;
  85. for (int Y = 0; Y < Height; Y++)
  86. for (int X = 0; X < Width; X++)
  87. {
  88. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  89. uint Pixel = (uint)CpuMem.ReadInt16Unchecked(Position + Offset);
  90. Pixel = (Pixel & 0x001f) << 11 |
  91. (Pixel & 0x03e0) << 1 |
  92. (Pixel & 0x7c00) >> 9 |
  93. (Pixel & 0x8000) >> 15;
  94. *(short*)(BuffPtr + OutOffs) = (short)Pixel;
  95. OutOffs += 2;
  96. }
  97. }
  98. return Output;
  99. }
  100. private unsafe static byte[] Read565(IAMemory Memory, TextureInfo Texture)
  101. {
  102. int Width = Texture.Width;
  103. int Height = Texture.Height;
  104. byte[] Output = new byte[Width * Height * 2];
  105. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
  106. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  107. Memory,
  108. Texture.Position);
  109. fixed (byte* BuffPtr = Output)
  110. {
  111. long OutOffs = 0;
  112. for (int Y = 0; Y < Height; Y++)
  113. for (int X = 0; X < Width; X++)
  114. {
  115. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  116. uint Pixel = (uint)CpuMem.ReadInt16Unchecked(Position + Offset);
  117. Pixel = (Pixel & 0x001f) << 11 |
  118. (Pixel & 0x07e0) |
  119. (Pixel & 0xf800) >> 11;
  120. *(short*)(BuffPtr + OutOffs) = (short)Pixel;
  121. OutOffs += 2;
  122. }
  123. }
  124. return Output;
  125. }
  126. private unsafe static byte[] Read2Bpp(IAMemory Memory, TextureInfo Texture)
  127. {
  128. int Width = Texture.Width;
  129. int Height = Texture.Height;
  130. byte[] Output = new byte[Width * Height * 2];
  131. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
  132. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  133. Memory,
  134. Texture.Position);
  135. fixed (byte* BuffPtr = Output)
  136. {
  137. long OutOffs = 0;
  138. for (int Y = 0; Y < Height; Y++)
  139. for (int X = 0; X < Width; X++)
  140. {
  141. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  142. short Pixel = CpuMem.ReadInt16Unchecked(Position + Offset);
  143. *(short*)(BuffPtr + OutOffs) = Pixel;
  144. OutOffs += 2;
  145. }
  146. }
  147. return Output;
  148. }
  149. private unsafe static byte[] Read4Bpp(IAMemory Memory, TextureInfo Texture)
  150. {
  151. int Width = Texture.Width;
  152. int Height = Texture.Height;
  153. byte[] Output = new byte[Width * Height * 4];
  154. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
  155. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  156. Memory,
  157. Texture.Position);
  158. fixed (byte* BuffPtr = Output)
  159. {
  160. long OutOffs = 0;
  161. for (int Y = 0; Y < Height; Y++)
  162. for (int X = 0; X < Width; X++)
  163. {
  164. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  165. int Pixel = CpuMem.ReadInt32Unchecked(Position + Offset);
  166. *(int*)(BuffPtr + OutOffs) = Pixel;
  167. OutOffs += 4;
  168. }
  169. }
  170. return Output;
  171. }
  172. private unsafe static byte[] Read8Bpp(IAMemory Memory, TextureInfo Texture)
  173. {
  174. int Width = Texture.Width;
  175. int Height = Texture.Height;
  176. byte[] Output = new byte[Width * Height * 8];
  177. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 8);
  178. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  179. Memory,
  180. Texture.Position);
  181. fixed (byte* BuffPtr = Output)
  182. {
  183. long OutOffs = 0;
  184. for (int Y = 0; Y < Height; Y++)
  185. for (int X = 0; X < Width; X++)
  186. {
  187. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  188. long Pixel = CpuMem.ReadInt64Unchecked(Position + Offset);
  189. *(long*)(BuffPtr + OutOffs) = Pixel;
  190. OutOffs += 8;
  191. }
  192. }
  193. return Output;
  194. }
  195. private unsafe static byte[] Read16Bpp(IAMemory Memory, TextureInfo Texture)
  196. {
  197. int Width = Texture.Width;
  198. int Height = Texture.Height;
  199. byte[] Output = new byte[Width * Height * 16];
  200. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 16);
  201. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  202. Memory,
  203. Texture.Position);
  204. fixed (byte* BuffPtr = Output)
  205. {
  206. long OutOffs = 0;
  207. for (int Y = 0; Y < Height; Y++)
  208. for (int X = 0; X < Width; X++)
  209. {
  210. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  211. long PxLow = CpuMem.ReadInt64Unchecked(Position + Offset + 0);
  212. long PxHigh = CpuMem.ReadInt64Unchecked(Position + Offset + 8);
  213. *(long*)(BuffPtr + OutOffs + 0) = PxLow;
  214. *(long*)(BuffPtr + OutOffs + 8) = PxHigh;
  215. OutOffs += 16;
  216. }
  217. }
  218. return Output;
  219. }
  220. private unsafe static byte[] Read8Bpt4x4(IAMemory Memory, TextureInfo Texture)
  221. {
  222. int Width = (Texture.Width + 3) / 4;
  223. int Height = (Texture.Height + 3) / 4;
  224. byte[] Output = new byte[Width * Height * 8];
  225. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 4, 8);
  226. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  227. Memory,
  228. Texture.Position);
  229. fixed (byte* BuffPtr = Output)
  230. {
  231. long OutOffs = 0;
  232. for (int Y = 0; Y < Height; Y++)
  233. for (int X = 0; X < Width; X++)
  234. {
  235. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  236. long Tile = CpuMem.ReadInt64Unchecked(Position + Offset);
  237. *(long*)(BuffPtr + OutOffs) = Tile;
  238. OutOffs += 8;
  239. }
  240. }
  241. return Output;
  242. }
  243. private unsafe static byte[] Read16BptCompressedTexture(IAMemory Memory, TextureInfo Texture, int BlockWidth, int BlockHeight)
  244. {
  245. int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
  246. int Height = (Texture.Height + (BlockHeight - 1)) / BlockHeight;
  247. byte[] Output = new byte[Width * Height * 16];
  248. ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, BlockWidth, 16);
  249. (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
  250. Memory,
  251. Texture.Position);
  252. fixed (byte* BuffPtr = Output)
  253. {
  254. long OutOffs = 0;
  255. for (int Y = 0; Y < Height; Y++)
  256. for (int X = 0; X < Width; X++)
  257. {
  258. long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
  259. long Tile0 = CpuMem.ReadInt64Unchecked(Position + Offset + 0);
  260. long Tile1 = CpuMem.ReadInt64Unchecked(Position + Offset + 8);
  261. *(long*)(BuffPtr + OutOffs + 0) = Tile0;
  262. *(long*)(BuffPtr + OutOffs + 8) = Tile1;
  263. OutOffs += 16;
  264. }
  265. }
  266. return Output;
  267. }
  268. }
  269. }