nCine::RHI::GXM::GxmMemory namespace

GPU-visible memory of the sceGxm backend.

Every address the GPU reads or writes - vertex and index streams, texture texels, uniform buffers, the driver's own ring buffers and the display surfaces - has to live in a kernel memory block that was handed to sceGxmMapMemory(), so it cannot come from the C++ heap. This wraps that two-step allocate-and-map dance into one call, keeps the SceUID needed to release the block, and rounds the request up to the page size the block type requires (the kernel rejects a size that is not a multiple of it).

Every block is allocated uncached. The Vita exposes no user-mode data-cache write-back call (ksceKernelCpuDcacheWritebackRange is kernel-only), so a cached mapping could not be made visible to the GPU reliably - the classic "nothing renders" failure the GU backend flushes around on the PSP has no user-space remedy here. The cost is only on the CPU side of an upload; the GPU has its own cache in front of this memory either way.

Two address spaces sit alongside the mappable one and get their own entry points because they are mapped through different calls and hand back a USSE offset rather than only a pointer: the vertex and fragment USSE code windows the shader patcher uploads compiled programs into.

Classes

struct Block
A GPU-visible allocation: the kernel block that owns it and its CPU-side base address.

Enums

enum class Kind { Mapped, VertexUsse, FragmentUsse }
Which address space a block was mapped into (it decides the unmap call Free() has to issue).

Functions

auto Alloc(const char* name, std::uint32_t size, SceGxmMemoryAttribFlags attribs) -> Block
Allocates GPU-visible memory from main LPDDR and maps it for the GPU.
auto AllocCdram(const char* name, std::uint32_t size, SceGxmMemoryAttribFlags attribs) -> Block
Allocates GPU-visible memory from CDRAM and maps it for the GPU.
auto AcquireSurface(const char* name, std::uint32_t stride, std::uint32_t height) -> Block
Acquires CDRAM for a render target's texels, at an address reserved for that exact geometry.
void ReleaseSurface(Block& block)
Retires a block from AcquireSurface(), keeping its address reserved for the same geometry.
auto AllocVertexUsse(const char* name, std::uint32_t size) -> Block
Allocates memory in the vertex USSE window (for the shader patcher's compiled vertex programs).
auto AllocFragmentUsse(const char* name, std::uint32_t size) -> Block
Allocates memory in the fragment USSE window (for the shader patcher's compiled fragment programs).
void Free(Block& block)
Unmaps and releases a block obtained from any of the allocators above.
auto GetAllocatedBytes() -> std::uint32_t
Returns the total number of bytes currently reserved through this allocator (for the memory report).

Variables

SceUID InvalidUid constexpr
Value Block::Uid carries when an allocation failed (the SDK has no SCE_UID_INVALID_UID macro).

Enum documentation

enum class nCine::RHI::GXM::GxmMemory::Kind

Which address space a block was mapped into (it decides the unmap call Free() has to issue).

Function documentation

Block nCine::RHI::GXM::GxmMemory::Alloc(const char* name, std::uint32_t size, SceGxmMemoryAttribFlags attribs)

Allocates GPU-visible memory from main LPDDR and maps it for the GPU.

Parameters
name Debug name of the kernel block (shown by the memory-usage tools)
size Requested size in bytes, rounded up to the block type's 4 KB page size
attribs What the GPU may do with the memory (read, write or both)

Block nCine::RHI::GXM::GxmMemory::AllocCdram(const char* name, std::uint32_t size, SceGxmMemoryAttribFlags attribs)

Allocates GPU-visible memory from CDRAM and maps it for the GPU.

The 128 MB of CDRAM is the memory the display controller scans out of and the fastest memory the GPU can render into, so the display surfaces and the off-screen render targets are placed here. Falls back to LPDDR (Alloc()) when CDRAM is exhausted, which keeps a large level loading rather than failing outright. Its allocation granularity is 256 KB, so small requests are better served by Alloc().

Block nCine::RHI::GXM::GxmMemory::AcquireSurface(const char* name, std::uint32_t stride, std::uint32_t height)

Acquires CDRAM for a render target's texels, at an address reserved for that exact geometry.

A colour surface is identified to the driver by its base address, and a target of a given size always comes back here at the same address: blocks handed out through this pair are retired for reuse rather than released, and only ever reused for the identical stride and height. That matters because the pipeline destroys and rebuilds its whole viewport chain whenever the render passes change (entering a level, leaving it, splitting the screen), so a plain allocator hands the address a retired target used to occupy to the next target of a different size - and a driver that has cached anything about that address, an emulator especially, then has two conflicting descriptions of one surface and drops one of them. Trading a bounded amount of retained CDRAM for stable addresses avoids the whole class of problem; past MaxRetainedSurfaces distinct geometries it degrades to AllocCdram().

void nCine::RHI::GXM::GxmMemory::ReleaseSurface(Block& block)

Retires a block from AcquireSurface(), keeping its address reserved for the same geometry.

Block nCine::RHI::GXM::GxmMemory::AllocVertexUsse(const char* name, std::uint32_t size)

Allocates memory in the vertex USSE window (for the shader patcher's compiled vertex programs).

Block nCine::RHI::GXM::GxmMemory::AllocFragmentUsse(const char* name, std::uint32_t size)

Allocates memory in the fragment USSE window (for the shader patcher's compiled fragment programs).

void nCine::RHI::GXM::GxmMemory::Free(Block& block)

Unmaps and releases a block obtained from any of the allocators above.

std::uint32_t nCine::RHI::GXM::GxmMemory::GetAllocatedBytes()

Returns the total number of bytes currently reserved through this allocator (for the memory report).

Variable documentation

SceUID nCine::RHI::GXM::GxmMemory::InvalidUid constexpr

Value Block::Uid carries when an allocation failed (the SDK has no SCE_UID_INVALID_UID macro).