Skip to content

Commit

Permalink
Upgrade to Clang.jl new generator
Browse files Browse the repository at this point in the history
  • Loading branch information
Gnimuc committed Feb 24, 2021
1 parent c610c10 commit 3779719
Show file tree
Hide file tree
Showing 5 changed files with 12,642 additions and 61 deletions.
87 changes: 87 additions & 0 deletions gen/definitions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# X11/X.h
struct Window <: AbstractJuliaSDT end
struct VisualID <: AbstractJuliaSDT end
# X11/Xlib.h
struct Display <: AbstractJuliaSIT end
# X11/Xrandr.h
struct RROutput <: AbstractJuliaSIT end
# xcb.h
struct xcb_connection_t <: AbstractJuliaSIT end
struct xcb_window_t <: AbstractJuliaSIT end
struct xcb_visualid_t <: AbstractJuliaSIT end
# Wayland
struct wl_display <: AbstractJuliaSIT end
struct wl_surface <: AbstractJuliaSIT end
# Mir
struct MirConnection <: AbstractJuliaSIT end
struct MirSurface <: AbstractJuliaSIT end
# Android
struct ANativeWindow <: AbstractJuliaSIT end
# Windows
struct HINSTANCE <: AbstractJuliaSIT end
struct HWND <: AbstractJuliaSIT end
struct HMONITOR <: AbstractJuliaSIT end
struct HANDLE <: AbstractJuliaSIT end
struct DWORD <: AbstractJuliaSIT end
struct LPCWSTR <: AbstractJuliaSIT end
struct SECURITY_ATTRIBUTES <: AbstractJuliaSIT end
# DirectFB
struct IDirectFB <: AbstractJuliaSIT end
struct IDirectFBSurface <: AbstractJuliaSIT end
# Zircon
struct zx_handle_t <: AbstractJuliaSIT end
# GGP C
struct GgpStreamDescriptor <: AbstractJuliaSIT end
struct GgpFrameToken <: AbstractJuliaSIT end

add_definition(Dict(
:Window => Window(),
:VisualID => VisualID(),
:Display => Display(),
:RROutput => RROutput(),
:xcb_connection_t => xcb_connection_t(),
:xcb_window_t => xcb_window_t(),
:xcb_visualid_t => xcb_visualid_t(),
:wl_display => wl_display(),
:wl_surface => wl_surface(),
:MirConnection => MirConnection(),
:MirSurface => MirSurface(),
:ANativeWindow => ANativeWindow(),
:HINSTANCE => HINSTANCE(),
:HWND => HWND(),
:HMONITOR => HMONITOR(),
:HANDLE => HANDLE(),
:DWORD => DWORD(),
:LPCWSTR => LPCWSTR(),
:SECURITY_ATTRIBUTES => SECURITY_ATTRIBUTES(),
:IDirectFB => IDirectFB(),
:IDirectFBSurface => IDirectFBSurface(),
:zx_handle_t => zx_handle_t(),
:GgpStreamDescriptor => GgpStreamDescriptor(),
:GgpFrameToken => GgpFrameToken(),
))

Generators.translate(::Window, options=Dict()) = :Window
Generators.translate(::VisualID, options=Dict()) = :VisualID
Generators.translate(::Display, options=Dict()) = :Display
Generators.translate(::RROutput, options=Dict()) = :RROutput
Generators.translate(::xcb_connection_t, options=Dict()) = :xcb_connection_t
Generators.translate(::xcb_window_t, options=Dict()) = :xcb_window_t
Generators.translate(::xcb_visualid_t, options=Dict()) = :xcb_visualid_t
Generators.translate(::wl_display, options=Dict()) = :wl_display
Generators.translate(::wl_surface, options=Dict()) = :wl_surface
Generators.translate(::MirConnection, options=Dict()) = :MirConnection
Generators.translate(::MirSurface, options=Dict()) = :MirSurface
Generators.translate(::ANativeWindow, options=Dict()) = :ANativeWindow
Generators.translate(::HINSTANCE, options=Dict()) = :HINSTANCE
Generators.translate(::HWND, options=Dict()) = :HWND
Generators.translate(::HMONITOR, options=Dict()) = :HMONITOR
Generators.translate(::HANDLE, options=Dict()) = :HANDLE
Generators.translate(::DWORD, options=Dict()) = :DWORD
Generators.translate(::LPCWSTR, options=Dict()) = :LPCWSTR
Generators.translate(::SECURITY_ATTRIBUTES, options=Dict()) = :SECURITY_ATTRIBUTES
Generators.translate(::IDirectFB, options=Dict()) = :IDirectFB
Generators.translate(::IDirectFBSurface, options=Dict()) = :IDirectFBSurface
Generators.translate(::zx_handle_t, options=Dict()) = :zx_handle_t
Generators.translate(::GgpStreamDescriptor, options=Dict()) = :GgpStreamDescriptor
Generators.translate(::GgpFrameToken, options=Dict()) = :GgpFrameToken
72 changes: 37 additions & 35 deletions gen/generator.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using Clang
using Clang.Generators

import Vulkan_Headers_jll

include("definitions.jl")

# get include directory & vulkan.h
VK_INCLUDE = joinpath(Vulkan_Headers_jll.artifact_dir, "include", "vulkan")
VK_HEADERS = [joinpath(VK_INCLUDE, "vulkan.h")]

# include all extensions
VK_EXTENSIONS = [
VK_EXTENSIONS = String[
"VK_USE_PLATFORM_DIRECTFB_EXT",
"VK_USE_PLATFORM_ANDROID_KHR",
"VK_USE_PLATFORM_FUCHSIA",
Expand All @@ -22,38 +23,39 @@ VK_EXTENSIONS = [
"VK_USE_PLATFORM_XLIB_KHR",
"VK_USE_PLATFORM_XLIB_XRANDR_EXT",
"VK_USE_PLATFORM_GGP",
"VK_ENABLE_BETA_EXTENSIONS",
# "VK_ENABLE_BETA_EXTENSIONS",
]

common_file = joinpath(@__DIR__, "vk_common.jl")
api_file = joinpath(@__DIR__, "vk_api.jl")

wc = init(; headers=VK_HEADERS,
output_file=api_file,
common_file=common_file,
clang_includes=vcat(VK_INCLUDE, CLANG_INCLUDE),
clang_args="-D" .* VK_EXTENSIONS,
header_wrapped=(root, current) -> (startswith(current, VK_INCLUDE) ? true : false),
header_library=x -> "libvulkan",
clang_diagnostics=true,
)

# it should complain that some header files are not present (zircon/types.h, wayland-client.h...) but it should be OK since nothing from those files is actually wrapped
run(wc)

api_str = join(readlines(api_file), "\n")

# add an additional method which uses a function pointer for each API function
wrapped_funcs = String[]
for func eachmatch(r"function (.*)\((.*)\)\n (ccall.*)\nend", api_str)
name, args, body = func.captures
wrapped_func = """
function $name($args, fun_ptr)
$(replace(body, "(:$name, libvulkan)" => "fun_ptr"))
end
"""
push!(wrapped_funcs, wrapped_func)
end
open(api_file, "a+") do io
write(io, "\n" * join(wrapped_funcs, "\n"))
end
options = load_options(joinpath(@__DIR__, "generator.toml"))

args = vcat("-I$VK_INCLUDE", "-D" .* VK_EXTENSIONS)

ctx = create_context(VK_HEADERS, args, options)

build!(ctx)

# api_str = join(readlines(api_file), "\n")

# # add an additional method which uses a function pointer for each API function
# wrapped_funcs = String[]
# for func ∈ eachmatch(r"function (.*)\((.*)\)\n (ccall.*)\nend", api_str)
# name, args, body = func.captures
# wrapped_func = """
# function $name($args, fun_ptr)
# $(replace(body, "(:$name, libvulkan)" => "fun_ptr"))
# end
# """
# push!(wrapped_funcs, wrapped_func)
# end
# open(api_file, "a+") do io
# write(io, "\n" * join(wrapped_funcs, "\n"))
# end

1
# collect_top = ctx.passes[1]

# collect_top(ctx.dag, options)

# ctx.dag.nodes

# filter(x->x.id == :VkResult, ctx.dag.nodes)
11 changes: 11 additions & 0 deletions gen/generator.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[general]
library_name = "libvulkan"

output_file_path = "./src/LibVulkan.jl"

module_name = "LibVulkan"

export_symbol_prefixes = ["VK_", "Vk", "vk"]

prologue_file_path = "./gen/prologue.jl"
epilogue_file_path = ""
78 changes: 78 additions & 0 deletions gen/prologue.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using Libdl: Libdl

@static if !isempty(get(ENV, "JULIA_VULKAN_LIBNAME", ""))
const libvulkan = ENV["JULIA_VULKAN_LIBNAME"]
elseif Sys.iswindows()
const libvulkan = "vulkan-1.dll"
elseif Sys.isapple()
const libvulkan = "libvulkan.dylib"
elseif Sys.islinux()
const libvulkan = "libvulkan.so.1"
else
const libvulkan = "libvulkan"
end

const libvulkan_handle = Ref{Ptr{Cvoid}}(0)

function __init__()
libname = Libdl.find_library(libvulkan)
if isempty(libname)
error("""
Failed to retrieve a valid Vulkan library called '$libvulkan'.
If you configure the `JULIA_VULKAN_LIBNAME` environment variable before precompiling
VulkanCore, it will be used instead of '$libvulkan'. You may also manually add search
paths by appending them to Lidbl.DL_LOAD_PATH, but note that this may have repercussions
beyond this package.
""")
end
return libvulkan_handle[] = Libdl.dlopen(libname)
end

#### External definitions

# X11/X.h
const Window = Culong
const VisualID = Culong
# X11/Xlib.h
const Display = Cvoid # opaque struct
# X11/Xrandr.h
const RROutput = UInt32
# xcb.h
const xcb_connection_t = Cvoid # opaque struct
const xcb_window_t = UInt32
const xcb_visualid_t = UInt32
# Wayland
const wl_display = Cvoid # opaque struct
const wl_surface = Cvoid # opaque struct
# Mir
const MirConnection = Cvoid # opaque struct
const MirSurface = Cvoid # opaque struct
# Android
const ANativeWindow = Cvoid # opaque struct
# Windows
const HINSTANCE = Ptr{Cvoid}
const HWND = Ptr{Cvoid}
const HMONITOR = Ptr{Cvoid}
const HANDLE = HMONITOR
const DWORD = UInt32
const LPCWSTR = UInt16
const SECURITY_ATTRIBUTES = Cvoid # opaque struct
# DirectFB
const IDirectFB = Cvoid # opaque struct
const IDirectFBSurface = Cvoid # opaque struct
# Zircon
const zx_handle_t = UInt32
# GGP C
const GgpStreamDescriptor = UInt32
const GgpFrameToken = UInt32

# TODO: Clang.jl should support this kinda macros
VK_MAKE_VERSION(major, minor, patch) = (Cuint(major) << 22) | (Cuint(minor) << 12) | patch

VK_VERSION_MAJOR(version) = Cuint(version) >> 22
VK_VERSION_MINOR(version) = (Cuint(version) >> 12) & 0x3ff
VK_VERSION_PATCH(version) = Cuint(version) & 0xfff

const VK_API_VERSION_1_0 = VK_MAKE_VERSION(1, 0, 0)
const VK_API_VERSION_1_1 = VK_MAKE_VERSION(1, 1, 0)
const VK_API_VERSION_1_2 = VK_MAKE_VERSION(1, 2, 0)
Loading

0 comments on commit 3779719

Please sign in to comment.