TextureInfo.cs
1 using Ryujinx.Common; 2 using Ryujinx.Graphics.GAL; 3 using Ryujinx.Graphics.Texture; 4 using System; 5 6 namespace Ryujinx.Graphics.Gpu.Image 7 { 8 /// <summary> 9 /// Texture information. 10 /// </summary> 11 readonly struct TextureInfo 12 { 13 /// <summary> 14 /// Address of the texture in GPU mapped memory. 15 /// </summary> 16 public ulong GpuAddress { get; } 17 18 /// <summary> 19 /// The width of the texture. 20 /// </summary> 21 public int Width { get; } 22 23 /// <summary> 24 /// The height of the texture, or layers count for 1D array textures. 25 /// </summary> 26 public int Height { get; } 27 28 /// <summary> 29 /// The depth of the texture (for 3D textures), or layers count for array textures. 30 /// </summary> 31 public int DepthOrLayers { get; } 32 33 /// <summary> 34 /// The number of mipmap levels of the texture. 35 /// </summary> 36 public int Levels { get; } 37 38 /// <summary> 39 /// The number of samples in the X direction for multisampled textures. 40 /// </summary> 41 public int SamplesInX { get; } 42 43 /// <summary> 44 /// The number of samples in the Y direction for multisampled textures. 45 /// </summary> 46 public int SamplesInY { get; } 47 48 /// <summary> 49 /// The number of bytes per line for linear textures. 50 /// </summary> 51 public int Stride { get; } 52 53 /// <summary> 54 /// Indicates whenever or not the texture is a linear texture. 55 /// </summary> 56 public bool IsLinear { get; } 57 58 /// <summary> 59 /// GOB blocks in the Y direction, for block linear textures. 60 /// </summary> 61 public int GobBlocksInY { get; } 62 63 /// <summary> 64 /// GOB blocks in the Z direction, for block linear textures. 65 /// </summary> 66 public int GobBlocksInZ { get; } 67 68 /// <summary> 69 /// Number of GOB blocks per tile in the X direction, for block linear textures. 70 /// </summary> 71 public int GobBlocksInTileX { get; } 72 73 /// <summary> 74 /// Total number of samples for multisampled textures. 75 /// </summary> 76 public int Samples => SamplesInX * SamplesInY; 77 78 /// <summary> 79 /// Texture target type. 80 /// </summary> 81 public Target Target { get; } 82 83 /// <summary> 84 /// Texture format information. 85 /// </summary> 86 public FormatInfo FormatInfo { get; } 87 88 /// <summary> 89 /// Depth-stencil mode of the texture. This defines whenever the depth or stencil value is read from shaders, 90 /// for depth-stencil texture formats. 91 /// </summary> 92 public DepthStencilMode DepthStencilMode { get; } 93 94 /// <summary> 95 /// Texture swizzle for the red color channel. 96 /// </summary> 97 public SwizzleComponent SwizzleR { get; } 98 99 /// <summary> 100 /// Texture swizzle for the green color channel. 101 /// </summary> 102 public SwizzleComponent SwizzleG { get; } 103 104 /// <summary> 105 /// Texture swizzle for the blue color channel. 106 /// </summary> 107 public SwizzleComponent SwizzleB { get; } 108 109 /// <summary> 110 /// Texture swizzle for the alpha color channel. 111 /// </summary> 112 public SwizzleComponent SwizzleA { get; } 113 114 /// <summary> 115 /// Constructs the texture information structure. 116 /// </summary> 117 /// <param name="gpuAddress">The GPU address of the texture</param> 118 /// <param name="width">The width of the texture</param> 119 /// <param name="height">The height or the texture</param> 120 /// <param name="depthOrLayers">The depth or layers count of the texture</param> 121 /// <param name="levels">The amount of mipmap levels of the texture</param> 122 /// <param name="samplesInX">The number of samples in the X direction for multisample textures, should be 1 otherwise</param> 123 /// <param name="samplesInY">The number of samples in the Y direction for multisample textures, should be 1 otherwise</param> 124 /// <param name="stride">The stride for linear textures</param> 125 /// <param name="isLinear">Whenever the texture is linear or block linear</param> 126 /// <param name="gobBlocksInY">Number of GOB blocks in the Y direction</param> 127 /// <param name="gobBlocksInZ">Number of GOB blocks in the Z direction</param> 128 /// <param name="gobBlocksInTileX">Number of GOB blocks per tile in the X direction</param> 129 /// <param name="target">Texture target type</param> 130 /// <param name="formatInfo">Texture format information</param> 131 /// <param name="depthStencilMode">Depth-stencil mode</param> 132 /// <param name="swizzleR">Swizzle for the red color channel</param> 133 /// <param name="swizzleG">Swizzle for the green color channel</param> 134 /// <param name="swizzleB">Swizzle for the blue color channel</param> 135 /// <param name="swizzleA">Swizzle for the alpha color channel</param> 136 public TextureInfo( 137 ulong gpuAddress, 138 int width, 139 int height, 140 int depthOrLayers, 141 int levels, 142 int samplesInX, 143 int samplesInY, 144 int stride, 145 bool isLinear, 146 int gobBlocksInY, 147 int gobBlocksInZ, 148 int gobBlocksInTileX, 149 Target target, 150 FormatInfo formatInfo, 151 DepthStencilMode depthStencilMode = DepthStencilMode.Depth, 152 SwizzleComponent swizzleR = SwizzleComponent.Red, 153 SwizzleComponent swizzleG = SwizzleComponent.Green, 154 SwizzleComponent swizzleB = SwizzleComponent.Blue, 155 SwizzleComponent swizzleA = SwizzleComponent.Alpha) 156 { 157 GpuAddress = gpuAddress; 158 Width = width; 159 Height = height; 160 DepthOrLayers = depthOrLayers; 161 Levels = levels; 162 SamplesInX = samplesInX; 163 SamplesInY = samplesInY; 164 Stride = stride; 165 IsLinear = isLinear; 166 GobBlocksInY = gobBlocksInY; 167 GobBlocksInZ = gobBlocksInZ; 168 GobBlocksInTileX = gobBlocksInTileX; 169 Target = target; 170 FormatInfo = formatInfo; 171 DepthStencilMode = depthStencilMode; 172 SwizzleR = swizzleR; 173 SwizzleG = swizzleG; 174 SwizzleB = swizzleB; 175 SwizzleA = swizzleA; 176 } 177 178 /// <summary> 179 /// Gets the real texture depth. 180 /// Returns 1 for any target other than 3D textures. 181 /// </summary> 182 /// <returns>Texture depth</returns> 183 public int GetDepth() 184 { 185 return GetDepth(Target, DepthOrLayers); 186 } 187 188 /// <summary> 189 /// Gets the real texture depth. 190 /// Returns 1 for any target other than 3D textures. 191 /// </summary> 192 /// <param name="target">Texture target</param> 193 /// <param name="depthOrLayers">Texture depth if the texture is 3D, otherwise ignored</param> 194 /// <returns>Texture depth</returns> 195 public static int GetDepth(Target target, int depthOrLayers) 196 { 197 return target == Target.Texture3D ? depthOrLayers : 1; 198 } 199 200 /// <summary> 201 /// Gets the number of layers of the texture. 202 /// Returns 1 for non-array textures, 6 for cubemap textures, and layer faces for cubemap array textures. 203 /// </summary> 204 /// <returns>The number of texture layers</returns> 205 public int GetLayers() 206 { 207 return GetLayers(Target, DepthOrLayers); 208 } 209 210 /// <summary> 211 /// Gets the number of layers of the texture. 212 /// Returns 1 for non-array textures, 6 for cubemap textures, and layer faces for cubemap array textures. 213 /// </summary> 214 /// <param name="target">Texture target</param> 215 /// <param name="depthOrLayers">Texture layers if the is a array texture, ignored otherwise</param> 216 /// <returns>The number of texture layers</returns> 217 public static int GetLayers(Target target, int depthOrLayers) 218 { 219 if (target == Target.Texture2DArray || target == Target.Texture2DMultisampleArray) 220 { 221 return depthOrLayers; 222 } 223 else if (target == Target.CubemapArray) 224 { 225 return depthOrLayers * 6; 226 } 227 else if (target == Target.Cubemap) 228 { 229 return 6; 230 } 231 else 232 { 233 return 1; 234 } 235 } 236 237 /// <summary> 238 /// Gets the number of 2D slices of the texture. 239 /// Returns 6 for cubemap textures, layer faces for cubemap array textures, and DepthOrLayers for everything else. 240 /// </summary> 241 /// <returns>The number of texture slices</returns> 242 public int GetSlices() 243 { 244 if (Target == Target.Texture3D || Target == Target.Texture2DArray || Target == Target.Texture2DMultisampleArray) 245 { 246 return DepthOrLayers; 247 } 248 else if (Target == Target.CubemapArray) 249 { 250 return DepthOrLayers * 6; 251 } 252 else if (Target == Target.Cubemap) 253 { 254 return 6; 255 } 256 else 257 { 258 return 1; 259 } 260 } 261 262 /// <summary> 263 /// Calculates the size information from the texture information. 264 /// </summary> 265 /// <param name="layerSize">Optional size of each texture layer in bytes</param> 266 /// <returns>Texture size information</returns> 267 public SizeInfo CalculateSizeInfo(int layerSize = 0) 268 { 269 if (Target == Target.TextureBuffer) 270 { 271 return new SizeInfo(Width * FormatInfo.BytesPerPixel); 272 } 273 else if (IsLinear) 274 { 275 return SizeCalculator.GetLinearTextureSize( 276 Stride, 277 Height, 278 FormatInfo.BlockHeight); 279 } 280 else 281 { 282 return SizeCalculator.GetBlockLinearTextureSize( 283 Width, 284 Height, 285 GetDepth(), 286 Levels, 287 GetLayers(), 288 FormatInfo.BlockWidth, 289 FormatInfo.BlockHeight, 290 FormatInfo.BytesPerPixel, 291 GobBlocksInY, 292 GobBlocksInZ, 293 GobBlocksInTileX, 294 layerSize); 295 } 296 } 297 298 /// <summary> 299 /// Creates texture information for a given mipmap level of the specified parent texture and this information. 300 /// </summary> 301 /// <param name="parent">The parent texture</param> 302 /// <param name="firstLevel">The first level of the texture view</param> 303 /// <param name="parentFormat">True if the parent format should be inherited</param> 304 /// <returns>The adjusted texture information with the new size</returns> 305 public TextureInfo CreateInfoForLevelView(Texture parent, int firstLevel, bool parentFormat) 306 { 307 // When the texture is used as view of another texture, we must 308 // ensure that the sizes are valid, otherwise data uploads would fail 309 // (and the size wouldn't match the real size used on the host API). 310 // Given a parent texture from where the view is created, we have the 311 // following rules: 312 // - The view size must be equal to the parent size, divided by (2 ^ l), 313 // where l is the first mipmap level of the view. The division result must 314 // be rounded down, and the result must be clamped to 1. 315 // - If the parent format is compressed, and the view format isn't, the 316 // view size is calculated as above, but the width and height of the 317 // view must be also divided by the compressed format block width and height. 318 // - If the parent format is not compressed, and the view is, the view 319 // size is calculated as described on the first point, but the width and height 320 // of the view must be also multiplied by the block width and height. 321 int width = Math.Max(1, parent.Info.Width >> firstLevel); 322 int height = Math.Max(1, parent.Info.Height >> firstLevel); 323 324 if (parent.Info.FormatInfo.IsCompressed && !FormatInfo.IsCompressed) 325 { 326 width = BitUtils.DivRoundUp(width, parent.Info.FormatInfo.BlockWidth); 327 height = BitUtils.DivRoundUp(height, parent.Info.FormatInfo.BlockHeight); 328 } 329 else if (!parent.Info.FormatInfo.IsCompressed && FormatInfo.IsCompressed) 330 { 331 width *= FormatInfo.BlockWidth; 332 height *= FormatInfo.BlockHeight; 333 } 334 335 int depthOrLayers; 336 337 if (Target == Target.Texture3D) 338 { 339 depthOrLayers = Math.Max(1, parent.Info.DepthOrLayers >> firstLevel); 340 } 341 else 342 { 343 depthOrLayers = DepthOrLayers; 344 } 345 346 // 2D and 2D multisample textures are not considered compatible. 347 // This specific case is required for copies, where the source texture might be multisample. 348 // In this case, we inherit the parent texture multisample state. 349 Target target = Target; 350 int samplesInX = SamplesInX; 351 int samplesInY = SamplesInY; 352 353 if (target == Target.Texture2D && parent.Target == Target.Texture2DMultisample) 354 { 355 target = Target.Texture2DMultisample; 356 samplesInX = parent.Info.SamplesInX; 357 samplesInY = parent.Info.SamplesInY; 358 } 359 360 return new TextureInfo( 361 GpuAddress, 362 width, 363 height, 364 depthOrLayers, 365 Levels, 366 samplesInX, 367 samplesInY, 368 Stride, 369 IsLinear, 370 GobBlocksInY, 371 GobBlocksInZ, 372 GobBlocksInTileX, 373 target, 374 parentFormat ? parent.Info.FormatInfo : FormatInfo, 375 DepthStencilMode, 376 SwizzleR, 377 SwizzleG, 378 SwizzleB, 379 SwizzleA); 380 } 381 382 /// <summary> 383 /// Creates texture information for a given format and this information. 384 /// </summary> 385 /// <param name="formatInfo">Format for the new texture info</param> 386 /// <returns>New info with the specified format</returns> 387 public TextureInfo CreateInfoWithFormat(FormatInfo formatInfo) 388 { 389 return new TextureInfo( 390 GpuAddress, 391 Width, 392 Height, 393 DepthOrLayers, 394 Levels, 395 SamplesInX, 396 SamplesInY, 397 Stride, 398 IsLinear, 399 GobBlocksInY, 400 GobBlocksInZ, 401 GobBlocksInTileX, 402 Target, 403 formatInfo, 404 DepthStencilMode, 405 SwizzleR, 406 SwizzleG, 407 SwizzleB, 408 SwizzleA); 409 } 410 } 411 }