You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Convert engineLoadTXD textures to D3DPOOL_DEFAULT (#4062)
GTA SA's RenderWare loader (D3DResourceSystem::CreateTexture @ 0x730510
and the inline CreateCubeTexture branch in _rwD3D9NativeTextureRead @
0x4CD982) hardcodes D3DPOOL_MANAGED for every texture in a TXD. MANAGED
textures are mirrored 1:1 in system memory so D3D9 can auto-restore them
on a device reset, which is exactly what makes a 10 MB DXT TXD count as
~20 MB of working set in MTA's process.
After RW finishes decoding a script-loaded TXD in CRenderWareSA::ReadTXD
we now walk every raster, allocate a fresh IDirect3DTexture9 (or
IDirect3DCubeTexture9) in D3DPOOL_DEFAULT, copy each mip through a
transient SYSTEMMEM scratch + UpdateTexture, release the original
MANAGED texture, and swap the pointer in rasterExt->texture. The release
deliberately bypasses D3DResourceSystem::DestroyTexture so the
gD3DTextureBuffer cache (MANAGED-only, keyed by w/h/format/levels) never
sees DEFAULT-pool entries; the destroy intercept in
CRenderWareSA::DestroyTexture NULLs rasterExt->texture before
RwTextureDestroy so _rwD3D9RasterDestroy hits its existing early-out.
Conversion happens before ScriptAddedTxd so the shader-matching map
(m_D3DDataTexInfoMap) is keyed against the new IDirect3DTexture9
pointer the renderer will see when GTA later calls SetTexture.
Coverage:
- Regular 2D rasters (RwRaster::type == 4, no cube flag, no palette,
no D3DUSAGE_AUTOGENMIPMAP): converted via CreateTexture.
- Cube-map rasters (cubeTextureFlags & 0x01): converted via
CreateCubeTexture; both faces and sub-levels are explicitly locked
on the SYSTEMMEM scratch so UpdateTexture copies the full mipchain
of every face. EdgeLength == desc.Width == desc.Height (D3D9
enforces square cube faces).
- Palettised rasters (P8 + 1024-byte palette buffer) and rasters
flagged with auto-mipmap generation are skipped: D3DUSAGE_AUTOGENMIPMAP
is incompatible with D3DPOOL_SYSTEMMEM and palette-format DEFAULT
textures aren't supported by modern drivers; both paths leave the
raster MANAGED so behaviour matches today.
- Unrecognised formats (anything not in our explicit byte-count table)
stay MANAGED.
- CreateTexture / CreateCubeTexture for the DEFAULT pool retry once
after IDirect3DDevice9::EvictManagedResources on
D3DERR_OUTOFVIDEOMEMORY, mirroring CDirect3DEvents9::CreateTexture.
Because DEFAULT-pool resources are auto-destroyed on a D3D9 cooperative
loss, CRenderWareSA gains OnDeviceLost / OnDeviceReset hooks called from
CGraphics::OnDeviceInvalidate / OnDeviceRestore around the existing
CRenderItemManager handling. CClientTXD implements a new
CRwReplacementOwner interface and re-decodes on Reset: file-path TXDs
re-read from disk, raw-data TXDs use the m_FileData buffer that
LoadFromBuffer already keeps for the clothes system.
Memory impact for a 10 MB TXD:
- file path (the common case for vehicle/skin packs):
~10 MB sysmem dropped, VRAM usage unchanged. ~50% total saving.
- raw-data path (rare; engineLoadTXD with a buffer):
m_FileData was already kept by master for clothes compatibility, so
the MANAGED shadow is replaced by that buffer at no net memory cost.
For texture-heavy servers (large vehicle / skin / map packs) this
typically reclaims hundreds of megabytes of sysmem with zero per-frame
cost (DEFAULT and MANAGED render identically once bound).
0 commit comments