Skip to content

update to 1.4 - #52

Open
SimonDanisch wants to merge 6 commits into
masterfrom
sd/vk1.4
Open

SimonDanisch wants to merge 6 commits into
masterfrom
sd/vk1.4

Conversation

@SimonDanisch

Copy link
Copy Markdown
Member

Vulkan 1.4 has lots of nice features e.g. to use hardware accelerated matmul.

@serenity4

Copy link
Copy Markdown
Member

I remember attempting to update to even just a more recent 1.3 patch version about a year ago, and was faced with nontrivial issues in the generated code that required adjustments on the generator side (and possibly on VulkanSpec.jl to adapt to a changing representation of the contents of the specification). Support for 1.4 might require quite some thought to get it to a working state.

I have essentially moved on from Julia/Vulkan work but I'm happy to review changes in the generator parts (I will trust that you check tests pass in Vulkan.jl and most importantly in your downstream packages before we merge). If updating the generator proves to be too complex/requires to be too intimately familiar with how it works internally then feel free to let me know and I'll see if I can find some time to do it.

@serenity4

Copy link
Copy Markdown
Member

Oh wait, I thought this was a PR to Vulkan.jl, not to VulkanCore.jl, my mistake. My previous comment applies to the former.

Seems like CI has issues fetching the SDK, would be nice to get that working for at least Linux CI.

Comment thread gen/Manifest.toml
Comment on lines 24 to +28
[[deps.Clang]]
deps = ["CEnum", "Clang_jll", "Downloads", "Pkg", "TOML"]
git-tree-sha1 = "d78c2973d7a752be377fe173bc9ff2dc2d9c3ed6"
deps = ["CEnum", "Clang_unified_jll", "Downloads", "Pkg", "TOML"]
git-tree-sha1 = "abf4d804064811b1948978a4aee478ccc76d6c9d"
uuid = "40e3b903-d033-50b4-a0cc-940c62c95e31"
version = "0.17.6"
version = "0.19.3"

@serenity4 serenity4 Jul 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating to Clang 0.19.3 seems to have a fairly different representation for structs (they are generated with a single .data field that is an NTuple with getproperty/propertynames overloaded to represent the different "fields"), as in

struct VkRenderingAttachmentInfo
    sType::VkStructureType
    pNext::Ptr{Cvoid}
    imageView::VkImageView
    imageLayout::VkImageLayout
    resolveMode::VkResolveModeFlagBits
    resolveImageView::VkImageView
    resolveImageLayout::VkImageLayout
    loadOp::VkAttachmentLoadOp
    storeOp::VkAttachmentStoreOp
    clearValue::VkClearValue
end

previously and now this:

struct VkRenderingAttachmentInfo
    data::NTuple{72, UInt8}
end

function Base.getproperty(x::Ptr{VkRenderingAttachmentInfo}, f::Symbol)
    f === :sType && return Ptr{VkStructureType}(x + 0)
    f === :pNext && return Ptr{Ptr{Cvoid}}(x + 8)
    f === :imageView && return Ptr{VkImageView}(x + 16)
    f === :imageLayout && return Ptr{VkImageLayout}(x + 24)
    f === :resolveMode && return Ptr{VkResolveModeFlagBits}(x + 28)
    f === :resolveImageView && return Ptr{VkImageView}(x + 32)
    f === :resolveImageLayout && return Ptr{VkImageLayout}(x + 40)
    f === :loadOp && return Ptr{VkAttachmentLoadOp}(x + 44)
    f === :storeOp && return Ptr{VkAttachmentStoreOp}(x + 48)
    f === :clearValue && return Ptr{VkClearValue}(x + 52)
    return getfield(x, f)
end

function Base.getproperty(x::VkRenderingAttachmentInfo, f::Symbol)
    r = Ref{VkRenderingAttachmentInfo}(x)
    ptr = Base.unsafe_convert(Ptr{VkRenderingAttachmentInfo}, r)
    fptr = getproperty(ptr, f)
    GC.@preserve r unsafe_load(fptr)
end

function Base.setproperty!(x::Ptr{VkRenderingAttachmentInfo}, f::Symbol, v)
    unsafe_store!(getproperty(x, f), v)
end

function Base.propertynames(x::VkRenderingAttachmentInfo, private::Bool = false)
    (:sType, :pNext, :imageView, :imageLayout, :resolveMode, :resolveImageView, :resolveImageLayout, :loadOp, :storeOp, :clearValue, if private
            fieldnames(typeof(x))
        else
            ()
        end...)
end

function VkRenderingAttachmentInfo(sType::VkStructureType, pNext::Ptr{Cvoid}, imageView::VkImageView, imageLayout::VkImageLayout, resolveMode::VkResolveModeFlagBits, resolveImageView::VkImageView, resolveImageLayout::VkImageLayout, loadOp::VkAttachmentLoadOp, storeOp::VkAttachmentStoreOp, clearValue::VkClearValue)
    ref = Ref{VkRenderingAttachmentInfo}()
    ptr = Base.unsafe_convert(Ptr{VkRenderingAttachmentInfo}, ref)
    ptr.sType = sType
    ptr.pNext = pNext
    ptr.imageView = imageView
    ptr.imageLayout = imageLayout
    ptr.resolveMode = resolveMode
    ptr.resolveImageView = resolveImageView
    ptr.resolveImageLayout = resolveImageLayout
    ptr.loadOp = loadOp
    ptr.storeOp = storeOp
    ptr.clearValue = clearValue
    ref[]
end

It feels like it might be working fine but at the same time it could easily break code that used to introspect into e.g. fieldnames instead of the user-facing propertynames.

It might be just fine but I'd prefer to have confirmation downstream, outside the VulkanCore.jl test suite, that the changes from updating to latest Clang don't behave unexpectedly.

Otherwise it might be preferable to keep this PR limited to updating to 1.4 bindings and keep the same version for Clang.jl as we used before. We can always do a PR later that bumps Clang.jl to the latest version if needed.

SimonDanisch and others added 5 commits September 11, 2026 12:47
A package that cannot work on this machine should not cost anything to depend
on. VulkanCore compiled 34,000 generated lines of ccall wrappers, Vulkan
127,000 more plus a dispatch table and an 8,573-name export list, and Lava a
whole Julia->SPIR-V compiler — all on every Mac in this tree, for code Mantle
declares and, under its own `@static if Sys.isapple()`, never imports.

VulkanCore probes the loader once at precompile time and exposes the answer as
HAS_LOADER; Vulkan and Lava gate their bodies on it, and Vulkan re-exposes it
outside its own gate so a dependent can ask without first checking whether
there is anything to ask. The extensions are gated too — Vk.Format does not
exist when the bindings do not, and those were the last thing still failing.

The gated text is UNCHANGED and unindented on purpose: with a loader present
each module is byte-for-byte the one it was, so the only case this can break is
the empty one.

Measured on macOS with no libvulkan: VulkanCore 3670 -> 554 ms, Vulkan 13098 ->
363 ms, and Lava now precompiles at all — gated out, it no longer evaluates the
`NativeEmitter{Out, Flats}` its body wants and this KernelAbstractions checkout
does not have. All three load in 0.4 s. `using Metal, RayMakie` takes 3.1 s
from a cold RayMakie cache, where it used to error.

A precompile-time answer, so installing a driver later needs
Pkg.precompile(; force = true).

NOT verified with a loader present — there is none on this machine.
The version tracks the Vulkan API version, and the bindings have been generated
against Vulkan_Headers_jll 1.4.321 since "update to 1.4".
"update to 1.4" regenerated thirteen platform files and added a fourteenth,
lib/x86_64-unknown-freebsd13.2.jl -- the target Clang names now -- but left
lib/x86_64-unknown-freebsd.jl untouched at 1.3.240, and that is the one this file
still included. FreeBSD therefore loaded 1.3 bindings under a 1.4 wrapper: of the
3000 Vk names Vulkan.jl's bsd.jl mentions, around a hundred did not exist.

Now 2, both Wayland, and those are a separate and older problem: the wrapper
generator enables PLATFORM_WAYLAND for BSD while no FreeBSD binding here has ever
wrapped Wayland, in this version or the previous one.

The 1.3 file is deleted rather than left beside its replacement.
`JULIA_VULKAN_LIBNAME` is read here, while the package precompiles, and an `ENV`
read is not part of the precompile hash. So setting it takes effect only if
something else happens to invalidate the cache. Observed directly on a driverless
Mac: set the variable, restart Julia, and the cache built WITHOUT it was reused --
`HAS_LOADER` stayed false on a machine that by then had a perfectly good driver
available. Only editing a source file forced the rebuild.

A preference is hashed, so changing it rebuilds the bindings against the new
library on the next load. `Vulkan.set_driver` writes it.

The environment variable still works and still comes before the system default,
but it is the fallback now rather than the mechanism.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants