mirror of
https://github.com/iHaiDeeZ/SSBU.git
synced 2026-10-29 04:01:44 +01:00
v00.15's match: 940 ms of compiling a shader, up to 370 waiting, their draws skipped (the stage half drawn, the sky black then white), three cores busy compiling (frame times 15-100 ms). - scripts/build-mesa-host.sh: RADV for the PC with the console's identity (Mesa's ac_ps4_info.h, AC_PS4_HOST_IDENTITY: the GPU the queries describe, DRM 3.61, address32_hi 0x44, conditional rendering off), same build id and btver2 target (no FMA): the same cache folder and pipeline keys as the console's (checked against the console's cache) - scripts/build-dxvk-host.sh: DXVK for the PC as the PS4 build is (native_ps4) - tools/shaderpack + scripts/build-shaderpack.sh: the game's 45,653 DXBC shaders made through them (8.5 min on 20 threads): RADV's cache (ssbu_pack.foz, 331 MB) and DXVK's IR cache - scripts/pack-shadercache.py: the DXBC cache folder as one file (dump/shadercache.pak), read by the runtime instead of 45,000 files (the renderer waited in stat 30% of its time) - the port reads ssbu_pack as a read-only Mesa cache (MESA_DISK_CACHE_READ_ONLY_FOZ_DBS) - the PS4 DXVK rebuilt from the committed tree: its cache version matches the PC's
62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""The game's shader disk cache (DXBC files) in one file, for the PS4: <out> = shadercache.pak, read by the runtime in
|
|
place of the folder (runtime/gpu_d3d11.c pack_open: on the PS4 a look-up in a folder of 45,000 files is slow).
|
|
|
|
pack-shadercache.py <out.pak> <folder> [<folder>...] (a later folder's file wins over an earlier one's)
|
|
|
|
Layout (little-endian): "SSBUDXBC", u32 version 1, u32 count; count entries {u64 FNV-1a of the file's name, u64 offset,
|
|
u32 size, u32 0}, sorted by the hash; then the files' bytes, each at a multiple of 16."""
|
|
import os
|
|
import struct
|
|
import sys
|
|
|
|
|
|
def fnv1a(data):
|
|
h = 1469598103934665603
|
|
for b in data:
|
|
h = ((h ^ b) * 1099511628211) & 0xFFFFFFFFFFFFFFFF
|
|
return h
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 3:
|
|
sys.exit(__doc__)
|
|
out, folders = sys.argv[1], sys.argv[2:]
|
|
files = {}
|
|
for folder in folders:
|
|
for name in os.listdir(folder):
|
|
if name.startswith("v") and name.endswith(".dxbc"):
|
|
files[name] = os.path.join(folder, name)
|
|
by_hash = {}
|
|
for name in files:
|
|
h = fnv1a(name.encode())
|
|
if h in by_hash:
|
|
sys.exit(f"{name} and {by_hash[h]}: the same hash")
|
|
by_hash[h] = name
|
|
order = sorted(by_hash)
|
|
sizes = {h: os.path.getsize(files[by_hash[h]]) for h in order}
|
|
at = 16 + 24 * len(order)
|
|
places = {}
|
|
for h in order:
|
|
at = (at + 15) & ~15
|
|
places[h] = at
|
|
at += sizes[h]
|
|
tmp = out + ".part"
|
|
with open(tmp, "wb") as f:
|
|
f.write(b"SSBUDXBC" + struct.pack("<II", 1, len(order)))
|
|
for h in order:
|
|
f.write(struct.pack("<QQII", h, places[h], sizes[h], 0))
|
|
for h in order:
|
|
f.write(b"\0" * (places[h] - f.tell()))
|
|
with open(files[by_hash[h]], "rb") as src:
|
|
data = src.read()
|
|
if len(data) != sizes[h]:
|
|
sys.exit(f"{files[by_hash[h]]} changed size")
|
|
f.write(data)
|
|
os.replace(tmp, out)
|
|
print(f"{out}: {len(order)} files, {at / 1048576:.0f} MiB")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|