Skip to content

Commit

Permalink
Support automatic dispatch for function aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
serenity4 committed Mar 10, 2022
1 parent 3236310 commit 691f02f
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 32 deletions.
4 changes: 4 additions & 0 deletions generator/src/spec/VulkanSpec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,12 @@ export
spec_spirv_extensions,
spec_spirv_capabilities,
disabled_symbols,
core_functions,
instance_functions,
device_functions,

# Alias manipulation
alias_dict,
follow_alias,
isalias,
hasalias,
Expand Down
25 changes: 25 additions & 0 deletions generator/src/spec/specs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,31 @@ parent_spec(spec::SpecHandle) = handle_by_name(parent(spec))

parent_hierarchy(spec::SpecHandle) = isnothing(spec.parent) ? [spec.name] : [parent_hierarchy(parent_spec(spec)); spec.name]


const core_functions = Symbol[]
const instance_functions = Symbol[]
const device_functions = Symbol[]

function fill_functions()
for fname in unique!([spec_funcs.name; [al.name for al in spec_aliases if isa(al.alias, SpecFunc)]])
spec = func_by_name(follow_alias(fname))
t = follow_alias(first(children(spec)).type)
h = handle_by_name(t)
if isnothing(h)
push!(core_functions, fname)
continue
end

if :VkDevice in parent_hierarchy(h)
push!(device_functions, fname)
elseif :VkInstance in parent_hierarchy(h)
push!(instance_functions, fname)
end
end
end

fill_functions()

function len(spec::Union{SpecFuncParam,SpecStructMember})
params = children(parent_spec(spec))
params[findfirst(x -> x.name == spec.len, params)]
Expand Down
48 changes: 28 additions & 20 deletions generator/src/wrapper/wrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -268,29 +268,36 @@ function VulkanWrapper(config::WrapperConfig)
exports.(constants); exports.(enums)...; exports.(bitmasks)...; exports.(handles); exports.(structs); exports.(unions); exports.(structs_hl); exports.(unions_hl); exports.(funcs); exports.(funcs_hl); :SPIRV_EXTENSIONS; :SPIRV_CAPABILITIES; :CORE_FUNCTIONS; :INSTANCE_FUNCTIONS; :DEVICE_FUNCTIONS;
]

aliases = filter(al -> al.target in exported_symbols, AliasDeclaration.(collect(VulkanSpec.alias_dict)))
append!(exported_symbols, exports.(aliases))

core_functions = Symbol[]
instance_functions = Symbol[]
device_functions = Symbol[]
fnames = unique!([spec_funcs.name; [al.name for al in spec_aliases if isa(al.alias, SpecFunc)]])
for fname in fnames
spec = func_by_name(follow_alias(fname))
t = follow_alias(first(children(spec)).type)
h = handle_by_name(t)
if isnothing(h)
push!(core_functions, fname)
continue
aliases = AliasDeclaration[]
for (source, target) in collect(alias_dict)
startswith(string(target), "vk") && continue
al = AliasDeclaration(source => target)
al.target in exported_symbols && push!(aliases, al)
end
function_aliases = Expr[]
_spec_funcs = f(spec_funcs)
for (source, target) in collect(alias_dict)
al = AliasDeclaration(source => target)
startswith(string(source), "vk") || continue
f = func_by_name(target)
handle = dispatch_handle(f)
param = @match handle begin
:(device($x)) || :(instance($x)) || x::Symbol => x
nothing => nothing
end

if :VkDevice in parent_hierarchy(h)
push!(device_functions, fname)
elseif :VkInstance in parent_hierarchy(h)
push!(instance_functions, fname)
args = Any[:(args...)]
!isnothing(param) && pushfirst!(args, param)
if f in _spec_funcs
push!(function_aliases,
# :($source(args..., fptr::FunctionPtr; kwargs...) = $target(args..., fptr; kwargs...)),
:($(al.source)($(args...); kwargs...) = @dispatch $source $handle $(al.target)($(args...); kwargs...))
)
push!(exported_symbols, al.source)
end
end

append!(exported_symbols, exports.(aliases))

VulkanWrapper(
Expr[
documented.(constants); documented.(enums); documented.(enum_converts_to_enum); documented.(enum_converts_to_integer); documented.(enum_converts_from_spec); documented.(enum_converts_to_spec); documented.(bitmasks);
Expand Down Expand Up @@ -337,12 +344,13 @@ function VulkanWrapper(config::WrapperConfig)
to_expr.(intermediate_type_mappings);

to_expr.(aliases);
function_aliases;

:(const SPIRV_EXTENSIONS = [$(spirv_exts...)]);
:(const SPIRV_CAPABILITIES = [$(spirv_caps...)]);
:(const CORE_FUNCTIONS = $core_functions);
:(const INSTANCE_FUNCTIONS = $instance_functions);
:(const DEVICE_FUNCTIONS = $device_functions);
:(const CORE_FUNCTIONS = $core_functions);
],
exported_symbols,
)
Expand Down
18 changes: 9 additions & 9 deletions generator/src/wrapper/wrap/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ function wrap_api_call(spec::SpecFunc, args; with_func_ptr = false)
ex = if with_func_ptr
ex
else
maybe_dispatch(spec, ex)
dispatch_call(spec, ex)
end
wrap_return(
ex,
Expand All @@ -12,27 +12,27 @@ function wrap_api_call(spec::SpecFunc, args; with_func_ptr = false)
)
end

function maybe_dispatch(spec::SpecFunc, ex)
maybe_handle = !isempty(children(spec)) ? innermost_type(first(children(spec)).type) : nothing
use_dispatch_macro = spec.name (:vkGetInstanceProcAddr, :vkGetDeviceProcAddr)
use_dispatch_macro || return ex
function dispatch_handle(spec::SpecFunc)
maybe_handle = !isempty(children(spec)) ? first(children(spec)).type : nothing
if maybe_handle in spec_handles.name
handle = handle_by_name(maybe_handle)
handle_id = wrap_identifier(handle)
hierarchy = parent_hierarchy(handle)
if handle.name == :VkDevice || handle.name == :VkInstance
# to avoid name conflicts
:(@dispatch $handle_id $ex)
handle_id
elseif :VkDevice in hierarchy
:(@dispatch device($handle_id) $ex)
:(device($handle_id))
elseif :VkInstance in hierarchy
:(@dispatch instance($handle_id) $ex)
:(instance($handle_id))
end
else
:(@dispatch nothing $ex)
nothing
end
end

dispatch_call(spec::SpecFunc, ex) = spec.name in (:vkGetInstanceProcAddr, :vkGetDeviceProcAddr) ? ex : :(@dispatch $(dispatch_handle(spec)) $ex)

function wrap_enumeration_api_call(spec::SpecFunc, exs::Expr...; free = [])
if must_repeat_while_incomplete(spec)
if !isempty(free)
Expand Down
20 changes: 20 additions & 0 deletions src/prewrap/handles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ macro dispatch(handle, expr)
end
end

"""
Obtain a function pointer from `source` and `handle`, and append the retrieved pointer to the function call arguments of `expr`.
No effect if the preference "USE_DISPATCH_TABLE" is not enabled.
"""
macro dispatch(source, handle, expr)
handle = esc(handle)
if @load_preference("USE_DISPATCH_TABLE", "true") == "true"
@match expr begin
:($f($(args...); $(kwargs...))) => quote
fptr = function_pointer(global_dispatcher[], $handle, $(QuoteNode(source)))
$f($(esc.(args)...), fptr; $(esc.(kwargs)...))
end
_ => error("Expected a function call, got $expr")
end
else
esc(expr)
end
end

macro fill_dispatch_table(handle)
handle = esc(handle)
@load_preference("USE_DISPATCH_TABLE", "true") "true" && return handle
Expand Down
6 changes: 3 additions & 3 deletions test/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ const debug_callback_c = @cfunction(debug_callback, UInt32, (DebugUtilsMessageSe
const API_VERSION = v"1.2"
const VALIDATION_LAYER = "VK_LAYER_KHRONOS_validation"

const INSTANCE_LAYERS = [
const INSTANCE_LAYERS = String[
]
const INSTANCE_EXTENSIONS = [
const INSTANCE_EXTENSIONS = String[
]
const DEVICE_EXTENSIONS = [
const DEVICE_EXTENSIONS = String[
]
const ENABLED_FEATURES = PhysicalDeviceFeatures(
)
Expand Down
4 changes: 4 additions & 0 deletions test/buffers.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
command_pool = CommandPool(device, 0)
cbuffer = first(unwrap(allocate_command_buffers(device, CommandBufferAllocateInfo(command_pool, COMMAND_BUFFER_LEVEL_PRIMARY, 1))))
@test cbuffer isa CommandBuffer

buffer = Buffer(device, 100, BUFFER_USAGE_TRANSFER_DST_BIT, SHARING_MODE_EXCLUSIVE, [])
@test buffer isa Buffer
@test get_buffer_memory_requirements_2_khr get_buffer_memory_requirements_2

0 comments on commit 691f02f

Please sign in to comment.