refactor(render3d): gpu_vk_res.ludic, and render3d compiles the Vulkan backend

The Vulkan backend is two files. gpu_vk.ludic is the device, memory and one-shot commands,
pure Vulkan, and still runs on its own (vk_device.ludic). gpu_vk_res.ludic is the resources in
the renderer's vocabulary - OpenGL's names for formats, filters and blend factors, which only
exist where Gl.* is named - starting with the format table. r3d.ludic imports both after
gpu.ludic; nothing calls them yet.

OpenGL frames byte-identical at the five viewpoints; 59 self-tests pass; VKDEVICE OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-15 11:53:07 +03:00
parent 7d93f44e53
commit eb428ba5f3
2 changed files with 41 additions and 0 deletions

View file

@ -0,0 +1,39 @@
# gpu_vk_res.ludic — the Vulkan backend's resources in the renderer's vocabulary: the formats,
# and next the textures, buffers, samplers and pipelines gpu.ludic's handles stand for.
#
# gpu.ludic speaks OpenGL's names for formats, filters and blend factors, so this half of the
# backend does too, and is only compiled inside render3d (which names Gl.*). gpu_vk.ludic - the
# device, memory and one-shot commands - is pure Vulkan and runs on its own (vk_device.ludic).
# ---- formats ------------------------------------------------------------------------------
# The renderer names formats the way OpenGL does (they are gpu.ludic's vocabulary); these turn
# one into the Vulkan image format that holds it. Three-channel formats have no widely
# supported Vulkan image format, so they are stored with four and expanded on upload.
function gvk_format(ifmt: int) -> int {
if ifmt == GL_RGBA8 or ifmt == GL_RGB8 { return VK_FORMAT_R8G8B8A8_UNORM }
if ifmt == GL_SRGB8_ALPHA8 or ifmt == GL_SRGB8 { return VK_FORMAT_R8G8B8A8_SRGB }
if ifmt == GL_R8 { return VK_FORMAT_R8_UNORM }
if ifmt == GL_RG8 { return VK_FORMAT_R8G8_UNORM }
if ifmt == GL_R16 { return VK_FORMAT_R16_UNORM }
if ifmt == GL_RG16 { return VK_FORMAT_R16G16_UNORM }
if ifmt == GL_RGBA16 or ifmt == GL_RGB16 { return VK_FORMAT_R16G16B16A16_UNORM }
if ifmt == GL_RG16F { return VK_FORMAT_R16G16_SFLOAT }
if ifmt == GL_RGBA16F or ifmt == GL_RGB16F { return VK_FORMAT_R16G16B16A16_SFLOAT }
if ifmt == GL_R32F { return VK_FORMAT_R32_SFLOAT }
if ifmt == GL_RGBA32F { return VK_FORMAT_R32G32B32A32_SFLOAT }
if ifmt == GL_DEPTH_COMPONENT32F or ifmt == GL_DEPTH_COMPONENT24 { return VK_FORMAT_D32_SFLOAT }
return VK_FORMAT_UNDEFINED
}
function gvk_is_depth(ifmt: int) -> bool { return ifmt == GL_DEPTH_COMPONENT32F or ifmt == GL_DEPTH_COMPONENT24 }
# channels the Vulkan image stores per texel
function gvk_channels(ifmt: int) -> int {
if ifmt == GL_R8 or ifmt == GL_R16 or ifmt == GL_R32F or gvk_is_depth(ifmt) { return 1 }
if ifmt == GL_RG8 or ifmt == GL_RG16 or ifmt == GL_RG16F { return 2 }
return 4
}
# bytes per channel the Vulkan image stores
function gvk_channel_bytes(ifmt: int) -> int {
if ifmt == GL_RGBA8 or ifmt == GL_RGB8 or ifmt == GL_SRGB8_ALPHA8 or ifmt == GL_SRGB8 or ifmt == GL_R8 or ifmt == GL_RG8 { return 1 }
if ifmt == GL_R32F or ifmt == GL_RGBA32F or gvk_is_depth(ifmt) { return 4 }
return 2
}