aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
blob: c82a555eec1507b674d687552028f07f13bf5f34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;

namespace Ryujinx.Graphics.Gpu.Image
{
    /// <summary>
    /// Maxwell texture descriptor, as stored on the GPU texture pool memory region.
    /// </summary>
    struct TextureDescriptor : ITextureDescriptor, IEquatable<TextureDescriptor>
    {
#pragma warning disable CS0649 // Field is never assigned to
        public uint Word0;
        public uint Word1;
        public uint Word2;
        public uint Word3;
        public uint Word4;
        public uint Word5;
        public uint Word6;
        public uint Word7;
#pragma warning restore CS0649

        /// <summary>
        /// Unpacks Maxwell texture format integer.
        /// </summary>
        /// <returns>The texture format integer</returns>
        public readonly uint UnpackFormat()
        {
            return Word0 & 0x8007ffff;
        }

        /// <summary>
        /// Unpacks the swizzle component for the texture red color channel.
        /// </summary>
        /// <returns>The swizzle component</returns>
        public readonly TextureComponent UnpackSwizzleR()
        {
            return (TextureComponent)((Word0 >> 19) & 7);
        }

        /// <summary>
        /// Unpacks the swizzle component for the texture green color channel.
        /// </summary>
        /// <returns>The swizzle component</returns>
        public readonly TextureComponent UnpackSwizzleG()
        {
            return (TextureComponent)((Word0 >> 22) & 7);
        }

        /// <summary>
        /// Unpacks the swizzle component for the texture blue color channel.
        /// </summary>
        /// <returns>The swizzle component</returns>
        public readonly TextureComponent UnpackSwizzleB()
        {
            return (TextureComponent)((Word0 >> 25) & 7);
        }

        /// <summary>
        /// Unpacks the swizzle component for the texture alpha color channel.
        /// </summary>
        /// <returns>The swizzle component</returns>
        public readonly TextureComponent UnpackSwizzleA()
        {
            return (TextureComponent)((Word0 >> 28) & 7);
        }

        /// <summary>
        /// Unpacks the 40-bits texture GPU virtual address.
        /// </summary>
        /// <returns>The GPU virtual address</returns>
        public readonly ulong UnpackAddress()
        {
            return Word1 | ((ulong)(Word2 & 0xffff) << 32);
        }

        /// <summary>
        /// Unpacks texture descriptor type for this texture descriptor.
        /// This defines the texture layout, among other things.
        /// </summary>
        /// <returns>The texture descriptor type</returns>
        public readonly TextureDescriptorType UnpackTextureDescriptorType()
        {
            return (TextureDescriptorType)((Word2 >> 21) & 7);
        }

        /// <summary>
        /// Unpacks the texture stride (bytes per line) for linear textures only.
        /// Always 32-bytes aligned.
        /// </summary>
        /// <returns>The linear texture stride</returns>
        public readonly int UnpackStride()
        {
            return (int)(Word3 & 0xffff) << 5;
        }

        /// <summary>
        /// Unpacks the GOB block size in X (width) for block linear textures.
        /// Must be always 1, ignored by the GPU.
        /// </summary>
        /// <returns>THe GOB block X size</returns>
        public readonly int UnpackGobBlocksInX()
        {
            return 1 << (int)(Word3 & 7);
        }

        /// <summary>
        /// Unpacks the GOB block size in Y (height) for block linear textures.
        /// Must be always a power of 2, with a maximum value of 32.
        /// </summary>
        /// <returns>THe GOB block Y size</returns>
        public readonly int UnpackGobBlocksInY()
        {
            return 1 << (int)((Word3 >> 3) & 7);
        }

        /// <summary>
        /// Unpacks the GOB block size in Z (depth) for block linear textures.
        /// Must be always a power of 2, with a maximum value of 32.
        /// Must be 1 for any texture target other than 3D textures.
        /// </summary>
        /// <returns>The GOB block Z size</returns>
        public readonly int UnpackGobBlocksInZ()
        {
            return 1 << (int)((Word3 >> 6) & 7);
        }

        /// <summary>
        /// Number of GOB blocks per tile in the X direction.
        /// This is only used for sparse textures, should be 1 otherwise.
        /// </summary>
        /// <returns>The number of GOB blocks per tile</returns>
        public readonly int UnpackGobBlocksInTileX()
        {
            return 1 << (int)((Word3 >> 10) & 7);
        }

        /// <summary>
        /// Unpacks the number of mipmap levels of the texture.
        /// </summary>
        /// <returns>The number of mipmap levels</returns>
        public readonly int UnpackLevels()
        {
            return (int)(Word3 >> 28) + 1;
        }

        /// <summary>
        /// Unpack the base level texture width size.
        /// </summary>
        /// <returns>The texture width</returns>
        public readonly int UnpackWidth()
        {
            return (int)(Word4 & 0xffff) + 1;
        }

        /// <summary>
        /// Unpack the width of a buffer texture.
        /// </summary>
        /// <returns>The texture width</returns>
        public readonly int UnpackBufferTextureWidth()
        {
            return (int)((Word4 & 0xffff) | (Word3 << 16)) + 1;
        }

        /// <summary>
        /// Unpacks the texture sRGB format flag.
        /// </summary>
        /// <returns>True if the texture is sRGB, false otherwise</returns>
        public readonly bool UnpackSrgb()
        {
            return (Word4 & (1 << 22)) != 0;
        }

        /// <summary>
        /// Unpacks the texture target.
        /// </summary>
        /// <returns>The texture target</returns>
        public readonly TextureTarget UnpackTextureTarget()
        {
            return (TextureTarget)((Word4 >> 23) & 0xf);
        }

        /// <summary>
        /// Unpack the base level texture height size, or array layers for 1D array textures.
        /// Should be ignored for 1D or buffer textures.
        /// </summary>
        /// <returns>The texture height or layers count</returns>
        public readonly int UnpackHeight()
        {
            return (int)(Word5 & 0xffff) + 1;
        }

        /// <summary>
        /// Unpack the base level texture depth size, number of array layers or cubemap faces.
        /// The meaning of this value depends on the texture target.
        /// </summary>
        /// <returns>The texture depth, layer or faces count</returns>
        public readonly int UnpackDepth()
        {
            return (int)((Word5 >> 16) & 0x3fff) + 1;
        }

        /// <summary>
        /// Unpacks the texture coordinates normalized flag.
        /// When this is true, texture coordinates are expected to be in the [0, 1] range on the shader.
        /// When this is false, texture coordinates are expected to be in the [0, W], [0, H] and [0, D] range.
        /// It must be set to false (by the guest driver) for rectangle textures.
        /// </summary>
        /// <returns>The texture coordinates normalized flag</returns>
        public readonly bool UnpackTextureCoordNormalized()
        {
            return (Word5 & (1 << 31)) != 0;
        }

        /// <summary>
        /// Unpacks the base mipmap level of the texture.
        /// </summary>
        /// <returns>The base mipmap level of the texture</returns>
        public readonly int UnpackBaseLevel()
        {
            return (int)(Word7 & 0xf);
        }

        /// <summary>
        /// Unpacks the maximum mipmap level (inclusive) of the texture.
        /// Usually equal to Levels minus 1.
        /// </summary>
        /// <returns>The maximum mipmap level (inclusive) of the texture</returns>
        public readonly int UnpackMaxLevelInclusive()
        {
            return (int)((Word7 >> 4) & 0xf);
        }

        /// <summary>
        /// Unpacks the multisampled texture samples count in each direction.
        /// Must be ignored for non-multisample textures.
        /// </summary>
        /// <returns>The multisample counts enum</returns>
        public readonly TextureMsaaMode UnpackTextureMsaaMode()
        {
            return (TextureMsaaMode)((Word7 >> 8) & 0xf);
        }

        /// <summary>
        /// Check if two descriptors are equal.
        /// </summary>
        /// <param name="other">The descriptor to compare against</param>
        /// <returns>True if they are equal, false otherwise</returns>
        public bool Equals(ref TextureDescriptor other)
        {
            return Unsafe.As<TextureDescriptor, Vector256<byte>>(ref this).Equals(Unsafe.As<TextureDescriptor, Vector256<byte>>(ref other));
        }

        /// <summary>
        /// Check if two descriptors are equal.
        /// </summary>
        /// <param name="other">The descriptor to compare against</param>
        /// <returns>True if they are equal, false otherwise</returns>
        public bool Equals(TextureDescriptor other)
        {
            return Equals(ref other);
        }

        /// <summary>
        /// Gets a hash code for this descriptor.
        /// </summary>
        /// <returns>The hash code for this descriptor.</returns>
        public override int GetHashCode()
        {
            return Unsafe.As<TextureDescriptor, Vector256<byte>>(ref this).GetHashCode();
        }

        public override bool Equals(object obj)
        {
            return obj is TextureDescriptor descriptor && Equals(descriptor);
        }
    }
}