// SPDX-License-Identifier: MPL-2.0 // Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2018-2020 fincs (https://github.com/devkitPro/deko3d) #pragma once #include #include namespace skyline::gpu::interconnect { #pragma pack(push, 1) /** * @brief The Texture Image Control is a descriptor used to configure the texture unit in Maxwell GPUs * @url https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml * @url https://github.com/devkitPro/deko3d/blob/00c12d1f4809014f1cc22719dd2e3476735eec64/source/maxwell/texture_image_control_block.h * @note Any members with underscore number suffixes represent a bitfield range of a value that member represents * @note Any enumerations that have numerical enumerants are prefixed with 'e' */ struct TextureImageControl { /** * @note An underscore may be used to describe a different block in a format */ enum class ImageFormat : u32 { Invalid = 0x0, R32G32B32A32 = 0x01, R32G32B32 = 0x02, R16G16B16A16 = 0x03, R32G32 = 0x04, R32B24G8 = 0x05, Etc2Rgb = 0x06, X8B8G8R8 = 0x07, A8B8G8R8 = 0x08, A2B10G10R10 = 0x09, Etc2RgbPta = 0x0A, Etc2Rgba = 0x0B, R16G16 = 0x0C, R24G8 = 0x0D, R8G24 = 0x0E, R32 = 0x0F, Bc6HSfloat = 0x10, Bc6HUfloat = 0x11, R4G4B4A4 = 0x12, A5B5G5R1 = 0x13, A1B5G5R5 = 0x14, B5G6R5 = 0x15, B6G5R5 = 0x16, BC7 = 0x17, R8G8 = 0x18, Eac = 0x19, EacX2 = 0x1A, R16 = 0x1B, Y8Video = 0x1C, R8 = 0x1D, G4R4 = 0x1E, R1 = 0x1F, E5B9G9R9 = 0x20, B10G11R11 = 0x21, G8B8G8R8 = 0x22, B8G8R8G8 = 0x23, BC1 = 0x24, BC2 = 0x25, BC3 = 0x26, BC4 = 0x27, BC5 = 0x28, S8D24 = 0x29, X8D24 = 0x2A, D24S8 = 0x2B, X4V4D24_Cov4R4V = 0x2C, X4V4D24_Cov8R8V = 0x2D, V8D24_Cov4R12V = 0x2E, D32 = 0x2F, D32S8 = 0x30, X8D24_X20V4S8_Cov4R4V = 0x31, X8D24_X20V4S8_Cov8R8V = 0x32, D32_X20V4X8_Cov4R4V = 0x33, D32_X20V4X8_Cov8R8V = 0x34, D32_X20V4S8_Cov4R4V = 0x35, D32_X20V4S8_Cov8R8V = 0x36, X8D24_X16V8S8_Cov4R12V = 0x37, D32_X16V8X8_Cov4R12V = 0x38, D32_X16V8S8_Cov4R12V = 0x39, D16 = 0x3A, V8D24_Cov8R24V = 0x3B, X8D24_X16V8S8_Cov8R24V = 0x3C, D32_X16V8X8_Cov8R24V = 0x3D, D32_X16V8S8_Cov8R24V = 0x3E, Astc4x4 = 0x40, Astc5x5 = 0x41, Astc6x6 = 0x42, Astc8x8 = 0x44, Astc10x10 = 0x45, Astc12x12 = 0x46, Astc5x4 = 0x50, Astc6x5 = 0x51, Astc8x6 = 0x52, Astc10x8 = 0x53, Astc12x10 = 0x54, Astc8x5 = 0x55, Astc10x5 = 0x56, Astc10x6 = 0x57, }; enum class ImageComponent : u32 { Snorm = 1, Unorm = 2, Sint = 3, Uint = 4, SnormForceFp16 = 5, UnormForceFp16 = 6, Float = 7, }; enum class ImageSwizzle : u32 { Zero = 0, R = 2, G = 3, B = 4, A = 5, OneInt = 6, OneFloat = 7, }; enum class HeaderType : u32 { Buffer1D = 0, PitchColorKey = 1, Pitch = 2, BlockLinear = 3, BlockLinearColorKey = 4, }; enum class TextureType : u32 { e1D = 0, e2D = 1, e3D = 2, eCube = 3, e1DArray = 4, e2DArray = 5, e1DBuffer = 6, e2DNoMipmap = 7, eCubeArray = 8, }; enum class MsaaMode : u32 { e1x1 = 0, e2x1 = 1, e2x2 = 2, e4x2 = 3, e4x2D3D = 4, e2x1D3D = 5, e4x4 = 6, e2x2Vc4 = 8, e2x2Vc12 = 9, e4x2Vc8 = 10, e4x2Vc24 = 11, }; enum class LodQuality : u32 { Low = 0, High = 1, }; enum class SectorPromotion : u32 { None = 0, To2V = 1, To2H = 2, To4 = 3, }; enum class BorderSize : u32 { One = 0, Two = 1, Four = 2, Eight = 3, SamplerColor = 7, }; enum class AnisotropySpreadModifier : u32 { None = 0, One = 1, Two = 2, Sqrt = 3, }; enum class AnisotropySpread : u32 { Half = 0, One = 1, Two = 2, Max = 3, }; enum class MaxAnisotropy : u32 { e1to1 = 0, e2to1 = 1, e4to1 = 2, e6to1 = 3, e8to1 = 4, e10to1 = 5, e12to1 = 6, e16to1 = 7, }; // 0x00 struct FormatWord { static constexpr u32 FormatColorComponentPadMask{(1U << 31) | 0b111'111'111'111'1111111U}; //!< Mask for the format, component and pad fields ImageFormat format : 7; ImageComponent componentR : 3; ImageComponent componentG : 3; ImageComponent componentB : 3; ImageComponent componentA : 3; ImageSwizzle swizzleX : 3; ImageSwizzle swizzleY : 3; ImageSwizzle swizzleZ : 3; ImageSwizzle swizzleW : 3; u32 _pad_ : 1; bool operator==(const FormatWord &) const = default; constexpr u32 Raw() const { if (std::is_constant_evaluated()) { u32 raw{_pad_}; raw <<= 3; raw |= static_cast(swizzleW); raw <<= 3; raw |= static_cast(swizzleZ); raw <<= 3; raw |= static_cast(swizzleY); raw <<= 3; raw |= static_cast(swizzleX); raw <<= 3; raw |= static_cast(componentA); raw <<= 3; raw |= static_cast(componentB); raw <<= 3; raw |= static_cast(componentG); raw <<= 3; raw |= static_cast(componentR); raw <<= 7; raw |= static_cast(format); return raw; } else { return util::BitCast(*this); } } } formatWord; // 0x04 u32 addressLow; // 0x08 u32 addressHigh : 16; u32 viewLayerBase_3_7 : 5; HeaderType headerType : 3; u32 loadStoreHint : 1; u32 viewCoherencyHash : 4; u32 viewLayerBase_8_10 : 3; // 0x0C union TileConfig { u16 widthMinusOne_16_31; constexpr static size_t PitchAlignmentBits{5}; //!< The amount of bits that are 0 in the pitch due to alignment (Aligned to 32 bytes) u16 pitchHigh; //!< Upper 16-bits of the 21-bit pitch, lower bits are implicitly zero due to alignment struct { u16 tileWidthGobsLog2 : 3; u16 tileHeightGobsLog2 : 3; u16 tileDepthGobsLog2 : 3; u16 _pad0_ : 1; u16 sparseTileWidthGobsLog2 : 3; u16 gob3d : 1; u16 _pad1_ : 2; }; u16 raw; bool operator==(const TileConfig &other) const { return raw == other.raw; } } tileConfig; u16 lodAnisotropyQuality_2 : 1; LodQuality lodAnisotropyQuality : 1; LodQuality lodIsotropyQuality : 1; AnisotropySpreadModifier anisotropyCoarseSpreadModifier : 2; u16 anisotropySpreadScale : 5; u16 useHeaderOptControl : 1; u16 depthTexture : 1; u16 mipMaxLevels : 4; // 0x10 u32 widthMinusOne : 16; u32 viewLayerBase_0_2 : 3; u32 anisotropySpreadMaxLog2 : 3; u32 isSrgb : 1; TextureType textureType : 4; SectorPromotion sectorPromotion : 2; BorderSize borderSize : 3; // 0x14 u32 heightMinusOne : 16; u32 depthMinusOne : 14; u32 isSparse : 1; u32 normalizedCoordinates : 1; // 0x18 u32 colorKeyOp : 1; u32 trilinOpt : 5; u32 mipLodBias : 13; u32 anisoBias : 4; AnisotropySpread anisotropyFineSpread : 2; AnisotropySpread anisotropyCoarseSpread : 2; MaxAnisotropy maxAnisotropy : 3; AnisotropySpreadModifier anisotropyFineSpreadModifier : 2; // 0x1C union ViewConfig { u32 colorKeyValue; struct { u32 mipMinLevel : 4; u32 mipMaxLevel : 4; MsaaMode msaaMode : 4; u32 minLodClamp : 12; u32 _pad2_ : 8; }; u32 raw; bool operator==(const ViewConfig &other) const { return raw == other.raw; } } viewConfig; bool operator==(const TextureImageControl &) const = default; u64 Iova() const { return (static_cast(addressHigh) << 32) | addressLow; } u32 BaseLayer() const { return static_cast(viewLayerBase_0_2 | (viewLayerBase_3_7 << 3) | (viewLayerBase_8_10 << 8)); } }; static_assert(sizeof(TextureImageControl) == 0x20); #pragma pack(pop) }