feat(render3d): 23.3 - a .dds beside a .png is uploaded BC-compressed with its whole mip chain

The device's textureCompressionBC is asked for and remembered (gvk_has_bc). tex_load_ex prefers a
DX10 .dds with the full chain beside the .png (not for an edge-padded cut-out atlas):
texture_dds.ludic reads BC7 / BC5 / BC4, gpu_tex_compressed makes the image with every level and
no colour-attachment use (a compressed image is only sampled and copied into), and
gvk_tex_upload_blocks copies each level's blocks from one staging buffer. A colour map is BC7
sampled as sRGB, a data map BC7 read as it is. examples/rendering/bc.ludic holds it, in the suite;
ludic.lab's plate carries its .dds (its three shots render at 56-60 dB against the .png's).

ludic-dev test 307/307, no Vulkan SDK in the environment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-28 01:23:44 +03:00
parent 6c663cc87b
commit 8cc4bdf66b
16 changed files with 217 additions and 1 deletions

View file

@ -571,6 +571,18 @@ function gpu_tex_paramf(render3d_st: mut Render3dState, kind: int, pname: int, v
}
# the border colour clamp-to-border reads (four fixed values in `rgba`)
function gpu_tex_border(render3d_st: Render3dState, kind: int, rgba: pointer) -> void { }
# a block-compressed texture with its whole mip chain, into the bound 2D texture: levels as they
# are in the file (level l at offs[l]), no decoding on the CPU and no mips made here
function gpu_tex_compressed(render3d_st: mut Render3dState, ifmt: int, w: int, h: int, levels: int, data: pointer, offs: words) -> bool {
gvk_flush(render3d_st)
let tex = render3d_st.gpu_bound_2d
if not gvk_tex_storage(render3d_st, tex, false, ifmt, w, h, 1, true) { return false }
if render3d_st.gvk_tex_levels[tex] != levels { print(`r3d: a {w}x{h} compressed texture brought {levels} levels, not {render3d_st.gvk_tex_levels[tex]}`); return false }
if not gvk_tex_upload_blocks(render3d_st, tex, w, h, levels, data, offs) { return false }
let o = gpu_tx_at(render3d_st, tex)
if o >= 0 { render3d_st.gpu_tx[o] = GPU_TEX2D; render3d_st.gpu_tx[o + 1] = w; render3d_st.gpu_tx[o + 2] = h; render3d_st.gpu_tx[o + 3] = 1; render3d_st.gpu_tx[o + 4] = ifmt; render3d_st.gpu_tx[o + 10] = 1 }
return true
}
function gpu_tex_mips(render3d_st: mut Render3dState, kind: int) -> void {
let mt = gpu_bound(render3d_st, kind)
let mo = gpu_tx_at(render3d_st, mt)