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