perf(render3d): Vulkan device memory in blocks, and a shadow map that survives running out of it
- A block sub-allocator: 64 MB blocks per memory type, images and buffers kept apart, first fit with alignment, freed ranges merged and empty blocks given back; anything over 16 MB still gets its own allocation. The self-tests' second world holds 94 allocations instead of 8735 (the driver's limit refused a shadow map before). Camp bench unchanged, 105.3 fps. - shadow_set_res keeps the size that worked when the card has no memory for the new one, and records it in shadow_refused, instead of ending with no shadow map; gpu_tex_ok says whether a texture has an image behind it. - Image barriers skip an image that was never made (a failed allocation used to crash there), and R3D_VK_ERRLOG=<file> appends every Vulkan failure line by line, so a crash no longer takes the message with it. - R3D_VK_PROF reports draws asked for and not made, so a layer missing from a frame is never silent. Validation on (VK_INSTANCE_LAYERS): the game's self-tests 61 OK, 0 errors, on the RTX 3070 Ti. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3706920e16
commit
989bdca736
5 changed files with 255 additions and 21 deletions
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
# the size of each cascade's depth layer; shadow_set_res changes it at run time
|
||||
var shadow_res: int = 2048
|
||||
var shadow_refused: int = 0 # the last size the graphics card had no memory for (0: none)
|
||||
const SHADOW_CASCADES: int = 5
|
||||
|
||||
var sh_tex: int = 0
|
||||
|
|
@ -42,10 +43,27 @@ function shadow_init() -> void {
|
|||
# texel size from the map itself, so nothing else has to follow.
|
||||
function shadow_set_res(r: int) -> void {
|
||||
if r < 256 or r == shadow_res { return }
|
||||
let was = shadow_res
|
||||
shadow_res = r
|
||||
if sh_tex == 0 { return }
|
||||
gpu_tex_free(sh_tex)
|
||||
shadow_make_tex()
|
||||
# not enough video memory for that size: go back to the one that worked, and smaller again if even
|
||||
# that is refused now, rather than ending with no shadow map at all
|
||||
if not gpu_tex_ok(sh_tex) {
|
||||
shadow_refused = r
|
||||
print(`r3d: shadows: no memory for {r} x {r} cascades; keeping {was}`)
|
||||
var size = was
|
||||
shadow_res = size
|
||||
gpu_tex_free(sh_tex)
|
||||
shadow_make_tex()
|
||||
while not gpu_tex_ok(sh_tex) and size > 512 {
|
||||
size = size / 2
|
||||
shadow_res = size
|
||||
gpu_tex_free(sh_tex)
|
||||
shadow_make_tex()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function shadow_make_tex() -> void {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue