PicaTexture class
Texture object of the PICA backend (aliased as RHI::Texture).
Keeps a LINEAR host store of level 0 in the uploaded pixel format (the same native R8/RG8/RGBA8 layout the software and PVR backends use) plus a second store the PICA200 can sample directly. That store lives in the linear heap - the part of main memory the GPU addresses physically, which libctru hands out through linearAlloc() - rather than in the 6 MB of VRAM, where only the framebuffers and the render targets are worth their space. It has to satisfy four hardware requirements the host store does not:
- Power-of-two dimensions between 8 and 1024 per axis. Anything larger is split into pages of at most 1024x1024, and the draw path selects the page a primitive's texture rectangle falls into and rebases its texture coordinates onto it (see AcquirePage()). Every sprite/tile draw samples one small sub-rect of an atlas, so a primitive practically never straddles a page boundary; the game's own content is assembled against the 512 the chunking asks for anyway.
- A format the PICA200 samples. The GPU has no colour lookup table of any kind - its 8-bit formats are luminance and alpha - so BOTH indexed formats are baked through their palette row into colour on the CPU (EnsureBakedStore()): R8 with the palette entry's alpha, RG8 (index + per-pixel alpha) with the texel's own. The bake goes into
GPU_RGBA4, and so does true-colour RGB8/RGBA8 content, which halves the store and the sampling bandwidth over RGBA8 for a 2D game whose colours are palette entries to begin with; RGB565 staysGPU_RGB565, whose channel order matches the engine's. - The 8x8 tiled layout. The GPU reads every texture as consecutive 8x8 blocks in Morton (Z) order - there is no linear texture mode - so every store is tiled as it is built (see TilePage()).
- The CPU cache written back, since the GPU reads the linear heap without seeing the ARM11's data cache. Every store rebuild ends in a
GSPGPU_FlushDataCache()of exactly the bytes it wrote.
A render target's store is a colour buffer the GPU renders into (in VRAM when it fits, in the linear heap otherwise) wrapped in a C3D_RenderTarget; the framebuffer layout IS the tiled texture layout, so it is sampled afterwards without any conversion.
Mip levels above 0 and compressed formats are accepted but not stored, exactly like on the other fixed-function backends: the game never uses either.
Public types
- struct Page
- One GPU-addressable piece of the texture.
Public static variables
-
static std::
uint32_t MaxTextureUnits constexpr - Number of texture units tracked by the device.
-
static std::
int32_t MaxPageDimension constexpr - The dimension a single PICA200 texture cannot exceed, per axis (a hardware limit).
-
static std::
int32_t MinPageDimension constexpr - The dimension a single PICA200 texture cannot fall short of, per axis (a hardware limit).
Public static functions
-
static auto Unbind(std::
uint32_t textureUnit) -> bool - Unbinds any texture from the specified texture unit.
-
static void SetUnpackAlignment(std::
int32_t alignment) - Sets the client pixel-row alignment of uploads (ignored, uploads are tightly packed).
- static auto SupportsImmutableStorage() -> bool
- static auto SupportsTextureReadback() -> bool
- static void ClearErrors()
- static auto CheckErrors() -> bool
- static void CheckFormatSupport(PixelFormat format)
-
static auto BytesPerPixel(PixelFormat format) -> std::
int32_t - Returns the number of bytes occupied by one texel of the given format (0 if unsupported).
-
static void TileBand16(std::
uint16_t* dst, const std:: uint16_t* band, std:: int32_t paddedWidth) - Scatters eight linear rows of 16-bit texels into the tile row of a GPU store they belong to.
Constructors, destructors, conversion operators
- PicaTexture(TextureTarget target) explicit
- ~PicaTexture()
- PicaTexture(const PicaTexture&) deleted
Public functions
- auto operator=(const PicaTexture&) -> PicaTexture& deleted
-
auto GetUniqueId() const -> std::
uint32_t - Returns a backend-neutral identifier uniquely identifying the texture (feeds material sort keys).
- auto GetTarget() const -> TextureTarget
- Returns the texture target.
-
auto GetWidth() const -> std::
int32_t - Returns the width of level 0 in texels.
-
auto GetHeight() const -> std::
int32_t - Returns the height of level 0 in texels.
- auto GetFormat() const -> PixelFormat
- Returns the pixel format of the linear host store (native, like the software backend).
- auto GetUploadFormat() const -> PixelFormat
- Returns the original upload format (R8/RG8 kept so the palette path can tell them apart).
-
auto GetStrideBytes() const -> std::
int32_t - Returns the byte distance between two consecutive rows of the linear host store.
-
auto GetPixels(std::
int32_t level = 0) const -> const std:: uint8_t* - Returns the base pointer of the linear host store (may be
nullptrbefore an upload). -
auto MutablePixels() -> std::
uint8_t* - Returns a writable base pointer of the linear host store (
nullptrbefore an upload). - auto GetWrapS() const -> SamplerWrapping
- Returns the horizontal texture-coordinate wrap mode.
- auto GetWrapT() const -> SamplerWrapping
- Returns the vertical texture-coordinate wrap mode (single stored mode).
- auto GetSwizzle() const -> const SwizzleChannel*
- Returns the four-channel sampling swizzle (identity by default; informational here).
-
auto GetMagFiltering() const -> nCine::
SamplerFilter - Returns the magnification filter.
-
auto GetMagFilter() const -> nCine::
SamplerFilter - Alias of GetMagFiltering().
- auto IsRenderTarget() const -> bool
- Returns
trueif the texture is bound as a color render target. - void SetRenderTarget(bool isRenderTarget)
- Marks the texture as (or no longer as) a color render target; becoming one allocates its colour buffer.
-
auto GetContentVersion() const -> std::
uint32_t - Returns a globally monotonic stamp of the texel store, advanced by every allocation or upload.
- auto IsIndexed() const -> bool
- Returns
truewhen the store holds palette indices (R8) - the GPU cannot sample those, see NeedsPaletteBake(). - auto NeedsPaletteBake() const -> bool
- Returns
truewhen the texture needs the per-palette-row CPU bake (both indexed formats, there is no palette hardware). - auto IsPaletteTexture() const -> bool
- Returns
truewhen this is the intercepted shared palette texture (read by the bakes, never sampled). -
auto AcquirePage(std::
int32_t texelX, std:: int32_t texelY) -> const Page* - Builds the GPU store if it is missing and returns the page holding the given source texel.
- auto GetPicaFormat() const -> GPU_TEXCOLOR
- Returns the
GPU_TEXCOLORformat of the GPU store (valid once a page exists). -
auto GetPageCountX() const -> std::
int32_t - Number of pages the image is split into along each axis (1 x 1 for anything up to 1024x1024).
-
auto GetPageCountY() const -> std::
int32_t - Number of pages the image is split into along each axis.
-
auto EnsureBakedStore(const PicaTexture* palette,
std::
int32_t paletteOffset, std:: uint32_t paletteGeneration) -> bool - Makes the GPU store hold this indexed texture baked through one palette row.
- void ReleaseHostCopy()
- Releases the decoded texels once the GPU store built from them is the only copy needed.
-
auto MapStreamingTexels(std::
int32_t& strideBytes) -> void* - Declined here: always returns
nullptr(the contract's streaming-texture fast path). - auto GetRenderTarget() const -> C3D_RenderTarget*
- Returns the render target the GPU renders into when this texture is one, or
nullptr. -
auto Bind(std::
uint32_t textureUnit) const -> bool - Binds the texture to the specified texture unit on the device.
- auto Bind() const -> bool
- Binds the texture to texture unit 0.
- auto Unbind() const -> bool
- Unbinds the texture from the unit it was last bound to.
-
void TexImage2D(std::
int32_t level, PixelFormat format, bool bgr, std:: int32_t width, std:: int32_t height, const void* data) - Allocates level-0 storage of the given format/size and optionally uploads its texels.
-
void TexSubImage2D(std::
int32_t level, std:: int32_t xoffset, std:: int32_t yoffset, std:: int32_t width, std:: int32_t height, PixelFormat format, bool bgr, const void* data) - Updates a rectangular subregion of level 0.
-
void TexStorage2D(std::
int32_t levels, PixelFormat format, std:: int32_t width, std:: int32_t height) - Allocates immutable level-0 storage of the given format/size (no texels yet).
-
void CompressedTexImage2D(std::
int32_t level, PixelFormat format, std:: int32_t width, std:: int32_t height, std:: int32_t imageSize, const void* data) - Compressed upload (unsupported, accepted as a no-op).
-
void CompressedTexSubImage2D(std::
int32_t level, std:: int32_t xoffset, std:: int32_t yoffset, std:: int32_t width, std:: int32_t height, PixelFormat format, std:: int32_t imageSize, const void* data) - Compressed sub-upload (unsupported, accepted as a no-op).
-
void GetTexImage(std::
int32_t level, PixelFormat format, bool bgr, void* pixels) - Reads back level-0 texels of the linear host store into client memory.
-
void SetMinFiltering(nCine::
SamplerFilter filter) - Sets the minification filter.
-
void SetMagFiltering(nCine::
SamplerFilter filter) - Sets the magnification filter.
- void SetWrap(SamplerWrapping wrap)
- Sets the wrap mode.
- void SetSwizzle(SwizzleChannel r, SwizzleChannel g, SwizzleChannel b, SwizzleChannel a)
- Sets the sampling swizzle (stored, informational - the palette path keys off the upload format instead).
-
void SetMaxLevel(std::
int32_t maxLevel) - Sets the highest defined mipmap level (ignored).
- void SetObjectLabel(StringView label)
- Sets a debug label; "Palettes" marks the shared palette texture the bakes read.
Function documentation
static void nCine:: RHI:: PICA:: PicaTexture:: TileBand16(std:: uint16_t* dst,
const std:: uint16_t* band,
std:: int32_t paddedWidth)
Scatters eight linear rows of 16-bit texels into the tile row of a GPU store they belong to.
The GPU reads a texture as 8x8 tiles laid out left to right, tile rows running from the first texel row on: tile (tx, ty) starts at texel index (ty * tilesPerRow + tx) * 64 and holds its 64 texels in Morton (Z) order - the three low bits of x and y interleaved with x in the even positions. dst is the first tile of the band's tile row, band the eight linear rows (paddedWidth texels each). Shared with the device, which tiles the per-frame lightmap texture the same way.
const Page* nCine:: RHI:: PICA:: PicaTexture:: AcquirePage(std:: int32_t texelX,
std:: int32_t texelY)
Builds the GPU store if it is missing and returns the page holding the given source texel.
texelX / texelY are clamped into the image, so the min corner of any texture rectangle is a valid argument. Returns nullptr when there is nothing to sample (no upload yet, an unsupported format, or an indexed store whose bake has not been requested - see EnsureBakedStore()).
bool nCine:: RHI:: PICA:: PicaTexture:: EnsureBakedStore(const PicaTexture* palette,
std:: int32_t paletteOffset,
std:: uint32_t paletteGeneration)
Makes the GPU store hold this indexed texture baked through one palette row.
The row is taken as the 256 RGBA8 entries of palette starting at paletteOffset; the index is resolved through it, and the alpha comes from the texel's own alpha byte (RG8) or from the palette entry (R8), written as GPU_RGBA4 - the analogue of GU::GuTexture::EnsureBakedStore(), applied to both indexed formats here because the PICA200 has no colour lookup table. A small number of bakes is cached, so the common "one extra palette row" case (a sprite and its recolored twin) does not rebuild anything; AcquirePage() then hands out the pages of the matching bake. Returns false when the bake could not be produced.
The offset is taken rather than a ready row pointer so that the 256 entries this reads can be checked to lie inside palette here, once, instead of at each of the callers.
void nCine:: RHI:: PICA:: PicaTexture:: ReleaseHostCopy()
Releases the decoded texels once the GPU store built from them is the only copy needed.
Both live in main memory, so a texture nothing writes again costs twice what it has to. Refused for content that still needs the texels - an indexed texture (its bakes are rebuilt from the indices on every palette change), streaming content, a render target or the shared palette texture. Does nothing on a texture that has already given them up.
void* nCine:: RHI:: PICA:: PicaTexture:: MapStreamingTexels(std:: int32_t& strideBytes)
Declined here: always returns nullptr (the contract's streaming-texture fast path).
The GPU samples only tiled stores, so there is no linear pitch a CPU writer could fill; the cinematics take the copy-through-a-buffer path and the store is tiled at upload.