TextureHandle.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. namespace Ryujinx.Graphics.Shader
  4. {
  5. public enum TextureHandleType
  6. {
  7. CombinedSampler = 0, // Must be 0.
  8. SeparateSamplerHandle = 1,
  9. SeparateSamplerId = 2,
  10. SeparateConstantSamplerHandle = 3,
  11. Direct = 4,
  12. }
  13. public static class TextureHandle
  14. {
  15. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  16. public static int PackSlots(int cbufSlot0, int cbufSlot1)
  17. {
  18. return cbufSlot0 | ((cbufSlot1 + 1) << 16);
  19. }
  20. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  21. public static (int, int) UnpackSlots(int slots, int defaultTextureBufferIndex)
  22. {
  23. int textureBufferIndex;
  24. int samplerBufferIndex;
  25. if (slots < 0)
  26. {
  27. textureBufferIndex = defaultTextureBufferIndex;
  28. samplerBufferIndex = textureBufferIndex;
  29. }
  30. else
  31. {
  32. uint high = (uint)slots >> 16;
  33. textureBufferIndex = (ushort)slots;
  34. samplerBufferIndex = high != 0 ? (int)high - 1 : textureBufferIndex;
  35. }
  36. return (textureBufferIndex, samplerBufferIndex);
  37. }
  38. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  39. public static int PackOffsets(int cbufOffset0, int cbufOffset1, TextureHandleType type)
  40. {
  41. return cbufOffset0 | (cbufOffset1 << 14) | ((int)type << 28);
  42. }
  43. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  44. public static (int, int, TextureHandleType) UnpackOffsets(int handle)
  45. {
  46. return (handle & 0x3fff, (handle >> 14) & 0x3fff, (TextureHandleType)((uint)handle >> 28));
  47. }
  48. /// <summary>
  49. /// Unpacks the texture ID from the real texture handle.
  50. /// </summary>
  51. /// <param name="packedId">The real texture handle</param>
  52. /// <returns>The texture ID</returns>
  53. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  54. public static int UnpackTextureId(int packedId)
  55. {
  56. return packedId & 0xfffff;
  57. }
  58. /// <summary>
  59. /// Unpacks the sampler ID from the real texture handle.
  60. /// </summary>
  61. /// <param name="packedId">The real texture handle</param>
  62. /// <returns>The sampler ID</returns>
  63. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  64. public static int UnpackSamplerId(int packedId)
  65. {
  66. return (packedId >> 20) & 0xfff;
  67. }
  68. /// <summary>
  69. /// Reads a packed texture and sampler ID (basically, the real texture handle)
  70. /// from a given texture/sampler constant buffer.
  71. /// </summary>
  72. /// <param name="wordOffset">A word offset of the handle on the buffer (the "fake" shader handle)</param>
  73. /// <param name="cachedTextureBuffer">The constant buffer to fetch texture IDs from</param>
  74. /// <param name="cachedSamplerBuffer">The constant buffer to fetch sampler IDs from</param>
  75. /// <returns>The packed texture and sampler ID (the real texture handle)</returns>
  76. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  77. public static int ReadPackedId(int wordOffset, ReadOnlySpan<int> cachedTextureBuffer, ReadOnlySpan<int> cachedSamplerBuffer)
  78. {
  79. (int textureWordOffset, int samplerWordOffset, TextureHandleType handleType) = UnpackOffsets(wordOffset);
  80. int handle = textureWordOffset < cachedTextureBuffer.Length ? cachedTextureBuffer[textureWordOffset] : 0;
  81. // The "wordOffset" (which is really the immediate value used on texture instructions on the shader)
  82. // is a 13-bit value. However, in order to also support separate samplers and textures (which uses
  83. // bindless textures on the shader), we extend it with another value on the higher 16 bits with
  84. // another offset for the sampler.
  85. // The shader translator has code to detect separate texture and sampler uses with a bindless texture,
  86. // turn that into a regular texture access and produce those special handles with values on the higher 16 bits.
  87. if (handleType != TextureHandleType.CombinedSampler)
  88. {
  89. int samplerHandle;
  90. if (handleType != TextureHandleType.SeparateConstantSamplerHandle)
  91. {
  92. samplerHandle = samplerWordOffset < cachedSamplerBuffer.Length ? cachedSamplerBuffer[samplerWordOffset] : 0;
  93. }
  94. else
  95. {
  96. samplerHandle = samplerWordOffset;
  97. }
  98. if (handleType == TextureHandleType.SeparateSamplerId ||
  99. handleType == TextureHandleType.SeparateConstantSamplerHandle)
  100. {
  101. samplerHandle <<= 20;
  102. }
  103. handle |= samplerHandle;
  104. }
  105. return handle;
  106. }
  107. }
  108. }