TextureFactory.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using Ryujinx.Graphics.Gal;
  2. using Ryujinx.Graphics.Memory;
  3. using System;
  4. namespace Ryujinx.Graphics.Texture
  5. {
  6. static class TextureFactory
  7. {
  8. public static GalImage MakeTexture(NvGpuVmm vmm, long ticPosition)
  9. {
  10. int[] tic = ReadWords(vmm, ticPosition, 8);
  11. GalImageFormat format = GetImageFormat(tic);
  12. GalTextureTarget textureTarget = (GalTextureTarget)((tic[4] >> 23) & 0xF);
  13. GalTextureSource xSource = (GalTextureSource)((tic[0] >> 19) & 7);
  14. GalTextureSource ySource = (GalTextureSource)((tic[0] >> 22) & 7);
  15. GalTextureSource zSource = (GalTextureSource)((tic[0] >> 25) & 7);
  16. GalTextureSource wSource = (GalTextureSource)((tic[0] >> 28) & 7);
  17. TextureSwizzle swizzle = (TextureSwizzle)((tic[2] >> 21) & 7);
  18. int maxMipmapLevel = (tic[3] >> 28) & 0xF + 1;
  19. GalMemoryLayout layout;
  20. if (swizzle == TextureSwizzle.BlockLinear ||
  21. swizzle == TextureSwizzle.BlockLinearColorKey)
  22. {
  23. layout = GalMemoryLayout.BlockLinear;
  24. }
  25. else
  26. {
  27. layout = GalMemoryLayout.Pitch;
  28. }
  29. int gobBlockHeightLog2 = (tic[3] >> 3) & 7;
  30. int gobBlockDepthLog2 = (tic[3] >> 6) & 7;
  31. int tileWidthLog2 = (tic[3] >> 10) & 7;
  32. int gobBlockHeight = 1 << gobBlockHeightLog2;
  33. int gobBlockDepth = 1 << gobBlockDepthLog2;
  34. int tileWidth = 1 << tileWidthLog2;
  35. int width = ((tic[4] >> 0) & 0xffff) + 1;
  36. int height = ((tic[5] >> 0) & 0xffff) + 1;
  37. int depth = ((tic[5] >> 16) & 0x3fff) + 1;
  38. int layoutCount = 1;
  39. // TODO: check this
  40. if (ImageUtils.IsArray(textureTarget))
  41. {
  42. layoutCount = depth;
  43. depth = 1;
  44. }
  45. if (textureTarget == GalTextureTarget.OneD)
  46. {
  47. height = 1;
  48. }
  49. if (textureTarget == GalTextureTarget.TwoD || textureTarget == GalTextureTarget.OneD)
  50. {
  51. depth = 1;
  52. }
  53. else if (textureTarget == GalTextureTarget.CubeMap)
  54. {
  55. // FIXME: This is a bit hacky but I guess it's fine for now
  56. layoutCount = 6;
  57. depth = 1;
  58. }
  59. else if (textureTarget == GalTextureTarget.CubeArray)
  60. {
  61. // FIXME: This is a really really hacky but I guess it's fine for now
  62. layoutCount *= 6;
  63. depth = 1;
  64. }
  65. GalImage image = new GalImage(
  66. width,
  67. height,
  68. depth,
  69. layoutCount,
  70. tileWidth,
  71. gobBlockHeight,
  72. gobBlockDepth,
  73. layout,
  74. format,
  75. textureTarget,
  76. maxMipmapLevel,
  77. xSource,
  78. ySource,
  79. zSource,
  80. wSource);
  81. if (layout == GalMemoryLayout.Pitch)
  82. {
  83. image.Pitch = (tic[3] & 0xffff) << 5;
  84. }
  85. return image;
  86. }
  87. public static GalTextureSampler MakeSampler(NvGpu gpu, NvGpuVmm vmm, long tscPosition)
  88. {
  89. int[] tsc = ReadWords(vmm, tscPosition, 8);
  90. GalTextureWrap addressU = (GalTextureWrap)((tsc[0] >> 0) & 7);
  91. GalTextureWrap addressV = (GalTextureWrap)((tsc[0] >> 3) & 7);
  92. GalTextureWrap addressP = (GalTextureWrap)((tsc[0] >> 6) & 7);
  93. bool depthCompare = ((tsc[0] >> 9) & 1) == 1;
  94. DepthCompareFunc depthCompareFunc = (DepthCompareFunc)((tsc[0] >> 10) & 7);
  95. GalTextureFilter magFilter = (GalTextureFilter) ((tsc[1] >> 0) & 3);
  96. GalTextureFilter minFilter = (GalTextureFilter) ((tsc[1] >> 4) & 3);
  97. GalTextureMipFilter mipFilter = (GalTextureMipFilter)((tsc[1] >> 6) & 3);
  98. GalColorF borderColor = new GalColorF(
  99. BitConverter.Int32BitsToSingle(tsc[4]),
  100. BitConverter.Int32BitsToSingle(tsc[5]),
  101. BitConverter.Int32BitsToSingle(tsc[6]),
  102. BitConverter.Int32BitsToSingle(tsc[7]));
  103. return new GalTextureSampler(
  104. addressU,
  105. addressV,
  106. addressP,
  107. minFilter,
  108. magFilter,
  109. mipFilter,
  110. borderColor,
  111. depthCompare,
  112. depthCompareFunc);
  113. }
  114. private static GalImageFormat GetImageFormat(int[] tic)
  115. {
  116. GalTextureType rType = (GalTextureType)((tic[0] >> 7) & 7);
  117. GalTextureType gType = (GalTextureType)((tic[0] >> 10) & 7);
  118. GalTextureType bType = (GalTextureType)((tic[0] >> 13) & 7);
  119. GalTextureType aType = (GalTextureType)((tic[0] >> 16) & 7);
  120. GalTextureFormat format = (GalTextureFormat)(tic[0] & 0x7f);
  121. bool convSrgb = ((tic[4] >> 22) & 1) != 0;
  122. return ImageUtils.ConvertTexture(format, rType, gType, bType, aType, convSrgb);
  123. }
  124. private static int[] ReadWords(NvGpuVmm vmm, long position, int count)
  125. {
  126. int[] words = new int[count];
  127. for (int index = 0; index < count; index++, position += 4)
  128. {
  129. words[index] = vmm.ReadInt32(position);
  130. }
  131. return words;
  132. }
  133. }
  134. }