diff options
Diffstat (limited to 'Ryujinx.Graphics.Shader/TextureHandle.cs')
-rw-r--r-- | Ryujinx.Graphics.Shader/TextureHandle.cs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Shader/TextureHandle.cs b/Ryujinx.Graphics.Shader/TextureHandle.cs index b3712e6b..d468188b 100644 --- a/Ryujinx.Graphics.Shader/TextureHandle.cs +++ b/Ryujinx.Graphics.Shader/TextureHandle.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.CompilerServices; namespace Ryujinx.Graphics.Shader @@ -50,5 +51,63 @@ namespace Ryujinx.Graphics.Shader { return (handle & 0x3fff, (handle >> 14) & 0x3fff, (TextureHandleType)((uint)handle >> 28)); } + + /// <summary> + /// Unpacks the texture ID from the real texture handle. + /// </summary> + /// <param name="packedId">The real texture handle</param> + /// <returns>The texture ID</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int UnpackTextureId(int packedId) + { + return (packedId >> 0) & 0xfffff; + } + + /// <summary> + /// Unpacks the sampler ID from the real texture handle. + /// </summary> + /// <param name="packedId">The real texture handle</param> + /// <returns>The sampler ID</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int UnpackSamplerId(int packedId) + { + return (packedId >> 20) & 0xfff; + } + + /// <summary> + /// Reads a packed texture and sampler ID (basically, the real texture handle) + /// from a given texture/sampler constant buffer. + /// </summary> + /// <param name="wordOffset">A word offset of the handle on the buffer (the "fake" shader handle)</param> + /// <param name="cachedTextureBuffer">The constant buffer to fetch texture IDs from</param> + /// <param name="cachedSamplerBuffer">The constant buffer to fetch sampler IDs from</param> + /// <returns>The packed texture and sampler ID (the real texture handle)</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ReadPackedId(int wordOffset, ReadOnlySpan<int> cachedTextureBuffer, ReadOnlySpan<int> cachedSamplerBuffer) + { + (int textureWordOffset, int samplerWordOffset, TextureHandleType handleType) = UnpackOffsets(wordOffset); + + int handle = cachedTextureBuffer[textureWordOffset]; + + // The "wordOffset" (which is really the immediate value used on texture instructions on the shader) + // is a 13-bit value. However, in order to also support separate samplers and textures (which uses + // bindless textures on the shader), we extend it with another value on the higher 16 bits with + // another offset for the sampler. + // The shader translator has code to detect separate texture and sampler uses with a bindless texture, + // turn that into a regular texture access and produce those special handles with values on the higher 16 bits. + if (handleType != TextureHandleType.CombinedSampler) + { + int samplerHandle = cachedSamplerBuffer[samplerWordOffset]; + + if (handleType == TextureHandleType.SeparateSamplerId) + { + samplerHandle <<= 20; + } + + handle |= samplerHandle; + } + + return handle; + } } } |