JuliaGPU / Vulkan.jl

Using Vulkan from Julia
Other
109 stars 12 forks source link

Encountering a Segmentation Fault and Exception: EXCEPTION_ACCESS_VIOLATION #36

Closed wenmana closed 2 years ago

wenmana commented 2 years ago

Hi, when I run the following code in windows:

using Vulkan, GLFW

width = 1400
height = 800
enable_validation_layers = true
required_queue_families = ["graphics", "presentation"]

GLFW.Init()
GLFW.WindowHint(GLFW.CLIENT_API, GLFW.NO_API)
GLFW.WindowHint(GLFW.RESIZABLE, false)
window = GLFW.CreateWindow(width, height, "Win")

# Vulkan Init
layers = ["VK_LAYER_KHRONOS_validation"]
alllayers = enumerate_instance_layer_properties()
alllayernames = map(i -> i.layer_name, alllayers.result.value)
enable_validation_layers && length(layers) != length(filter(i -> i in alllayernames, layers)) && error("Required Layers not available")

extensions = GLFW.GetRequiredInstanceExtensions()
enable_validation_layers && (extensions = vcat(extensions, Vulkan.VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
allextensions = enumerate_instance_extension_properties()

const application_info = ApplicationInfo(
    v"0.0.1", # application version
    v"0.0.1", # engine version
    v"1.2"; # requested API version
    application_name="Demo",
    engine_name="DemoEngine"
)

const instance = Instance(
    layers,
    extensions;
    application_info
)

# WSI 
surface = GLFW.CreateWindowSurface(instance, window)

# Physical Devices
device_extensions = ["VK_KHR_swapchain"]
function get_family_indices(device::PhysicalDevice)
    outp = Dict{String,Any}("graphics" => nothing, "compute" => nothing, "presentation" => nothing)
    families = get_physical_device_queue_family_properties(device)

    for x in 1:length(families)
        QUEUE_GRAPHICS_BIT in families[x].queue_flags && outp["graphics"] === nothing && (outp["graphics"] = x - 1)
        QUEUE_COMPUTE_BIT in families[x].queue_flags && outp["compute"] === nothing && (outp["compute"] = x - 1)
        unwrap(get_physical_device_surface_support_khr(device, x - 1, surface)) && outp["presentation"] === nothing && (outp["presentation"] = x - 1)
    end
    outp
end

function get_swapchain_support(device::PhysicalDevice)
    outp = Dict()
    outp["capabilities"] = get_physical_device_surface_capabilities_khr(device, surface) |> unwrap
    outp["formats"] = get_physical_device_surface_formats_khr(device, surface) |> unwrap
    outp["modes"] = get_physical_device_surface_present_modes_khr(device, surface) |> unwrap
    outp
end

devices = enumerate_physical_devices(instance) |> unwrap
function check_device(device)
    properties = get_physical_device_properties(device)
    features = get_physical_device_features(device)
    family_indices = get_family_indices(device)
    available_extensions = enumerate_device_extension_properties(device) |> unwrap
    has_extensions = reduce(&, [x in map(i -> i.extension_name, available_extensions) for x in device_extensions])
    has_extensions || return false
    swapchain_support = get_swapchain_support(device)

    properties.device_type == PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
        (features.vks.geometryShader |> Bool) &&
        reduce(&, [family_indices[x] !== nothing for x in required_queue_families]) &&
        length(swapchain_support["modes"]) > 0 &&
        length(swapchain_support["formats"]) > 0
end
suitable_devices = filter(i -> check_device(i), devices)
length(suitable_devices) == 0 && error("No Compatible Device Found")
physical_device = suitable_devices[1]
queue_families = get_family_indices(physical_device)
queue_indices = unique(values(queue_families))

# Logical Devices
queue_create_infos = [DeviceQueueCreateInfo(x, [1.0]) for x in queue_indices]
device_layers = enable_validation_layers ? layers : []
device_features = PhysicalDeviceFeatures()
device = Device(physical_device, queue_create_infos, device_layers, device_extensions, enabled_features=device_features)

queues = Dict()
for (key, value) in queue_families
    queues[key] = get_device_queue(device, value, 0)
end

# Swapchain
swapchain_support = get_swapchain_support(physical_device)
format = swapchain_support["formats"][1]
for j in swapchain_support["formats"]
    j == Vulkan.VK_FORMAT_B8G8R8A8_SRGB && j.colorSpace == Vulkan.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR && (global format = j)
end
mode = Vulkan.VK_PRESENT_MODE_MAILBOX_KHR in swapchain_support["modes"] ? Vulkan.VK_PRESENT_MODE_MAILBOX_KHR : Vulkan.VK_PRESENT_MODE_FIFO_KHR

# Main Loop
while !GLFW.WindowShouldClose(window)
    GLFW.PollEvents()
end

# Cleanup
destroy_device(device)
destroy_surface_khr(instance, surface)
destroy_instance(instance)
GLFW.DestroyWindow(window)
GLFW.Terminate()

It gives the follwoing output:

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5ef59b4e -- vkGetPhysicalDeviceSurfaceFormatsKHR at C:\Users\waliw\.julia\packages\VulkanCore\iP628\lib\x86_64-w64-mingw32.jl:7981 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\src\prewrap\errors.jl:25 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:55399 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\src\prewrap\errors.jl:39 [inlined]
#_get_physical_device_surface_formats_khr#1459 at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:55398
in expression starting at D:\Programming\Projects\julia\vulkan-tutorial\index.jl:82
vkGetPhysicalDeviceSurfaceFormatsKHR at C:\Users\waliw\.julia\packages\VulkanCore\iP628\lib\x86_64-w64-mingw32.jl:7981 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\src\prewrap\errors.jl:25 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:55399 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\src\prewrap\errors.jl:39 [inlined]
#_get_physical_device_surface_formats_khr#1459 at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:55398
_get_physical_device_surface_formats_khr##kw at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:55397 [inlined]
macro expansion at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\src\prewrap\errors.jl:48 [inlined]
#get_physical_device_surface_formats_khr#1747 at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:64049
get_physical_device_surface_formats_khr at C:\Users\waliw\.julia\packages\Vulkan\bHXH3\generated\windows.jl:64049
unknown function (ip: 000000005ef5a4cf)
get_swapchain_support at D:\Programming\Projects\julia\vulkan-tutorial\index.jl:61
check_device at D:\Programming\Projects\julia\vulkan-tutorial\index.jl:74
#11 at D:\Programming\Projects\julia\vulkan-tutorial\index.jl:82 [inlined]
filter at .\array.jl:2484
jl_apply at /cygdrive/c/buildbot/worker/package_win64/build/src\julia.h:1788 [inlined]
do_call at /cygdrive/c/buildbot/worker/package_win64/build/src\interpreter.c:126
eval_value at /cygdrive/c/buildbot/worker/package_win64/build/src\interpreter.c:215
eval_stmt_value at /cygdrive/c/buildbot/worker/package_win64/build/src\interpreter.c:166 [inlined]
eval_body at /cygdrive/c/buildbot/worker/package_win64/build/src\interpreter.c:583
jl_interpret_toplevel_thunk at /cygdrive/c/buildbot/worker/package_win64/build/src\interpreter.c:731
jl_toplevel_eval_flex at /cygdrive/c/buildbot/worker/package_win64/build/src\toplevel.c:885
jl_toplevel_eval_flex at /cygdrive/c/buildbot/worker/package_win64/build/src\toplevel.c:830
jl_toplevel_eval at /cygdrive/c/buildbot/worker/package_win64/build/src\toplevel.c:894 [inlined]
jl_toplevel_eval_in at /cygdrive/c/buildbot/worker/package_win64/build/src\toplevel.c:944
eval at .\boot.jl:373 [inlined]
include_string at .\loading.jl:1196
_include at .\loading.jl:1253
include at .\Base.jl:418
exec_options at .\client.jl:292
_start at .\client.jl:495
jfptr__start_21275.clone_1 at C:\Users\waliw\scoop\apps\julia\current\lib\julia\sys.dll (unknown line)
jl_apply at /cygdrive/c/buildbot/worker/package_win64/build/src\julia.h:1788 [inlined]
true_main at /cygdrive/c/buildbot/worker/package_win64/build/src\jlapi.c:559
jl_repl_entrypoint at /cygdrive/c/buildbot/worker/package_win64/build/src\jlapi.c:701
mainCRTStartup at /cygdrive/c/buildbot/worker/package_win64/build/cli\loader_exe.c:42
BaseThreadInitThunk at C:\Windows\System32\KERNEL32.DLL (unknown line)
RtlUserThreadStart at C:\Windows\SYSTEM32\ntdll.dll (unknown line)
Allocations: 9220682 (Pool: 9218356; Big: 2326); GC: 11
VUID-vkDestroyInstance-instance-00629(ERROR / SPEC): msgNum: -1958900200 - Validation Error: [ VUID-vkDestroyInstance-instance-00629 ] Object 0: handle = 0x62b74460, type = VK_OBJECT_TYPE_INSTANCE; Object 1: handle = 0xfd5b260000000001, type = VK_OBJECT_TYPE_SURFACE_KHR; | MessageID = 0x8b3d8e18 | OBJ ERROR : For VkInstance 0x62b74460[], VkSurfaceKHR 0xfd5b260000000001[] has not been destroyed. The Vulkan spec states: All child objects created using instance must have been destroyed prior to destroying instance (https://vulkan.lunarg.com/doc/view/1.3.211.0/windows/1.3-extensions/vkspec.html#VUID-vkDestroyInstance-instance-00629)
    Objects: 2
        [0] 0x62b74460, type: 1, name: NULL
        [1] 0xfd5b260000000001, type: 1000000000, name: NULL

Error when running the same code in Linux:

signal (11): Segmentation fault
in expression starting at /media/data/Programming/Projects/julia/vulkan-tutorial/index.jl:82
vkGetPhysicalDeviceSurfaceFormatsKHR at /home/wali/.julia/packages/VulkanCore/iP628/lib/x86_64-linux-gnu.jl:7961 [inlined]
macro expansion at /home/wali/.julia/packages/Vulkan/bHXH3/src/prewrap/errors.jl:25 [inlined]
macro expansion at /home/wali/.julia/packages/Vulkan/bHXH3/generated/linux.jl:54099 [inlined]
macro expansion at /home/wali/.julia/packages/Vulkan/bHXH3/src/prewrap/errors.jl:39 [inlined]
#_get_physical_device_surface_formats_khr#1433 at /home/wali/.julia/packages/Vulkan/bHXH3/generated/linux.jl:54098
_get_physical_device_surface_formats_khr##kw at /home/wali/.julia/packages/Vulkan/bHXH3/generated/linux.jl:54097 [inlined]
macro expansion at /home/wali/.julia/packages/Vulkan/bHXH3/src/prewrap/errors.jl:48 [inlined]
#get_physical_device_surface_formats_khr#1729 at /home/wali/.julia/packages/Vulkan/bHXH3/generated/linux.jl:62578
get_physical_device_surface_formats_khr at /home/wali/.julia/packages/Vulkan/bHXH3/generated/linux.jl:62578
unknown function (ip: 0x7f6777ce254d)
get_swapchain_support at /media/data/Programming/Projects/julia/vulkan-tutorial/index.jl:61
check_device at /media/data/Programming/Projects/julia/vulkan-tutorial/index.jl:74
#11 at /media/data/Programming/Projects/julia/vulkan-tutorial/index.jl:82 [inlined]
filter at ./array.jl:2484
unknown function (ip: 0x7f67f78bc7bc)
unknown function (ip: 0x7f67f78bc084)
unknown function (ip: 0x7f67f78bced4)
unknown function (ip: 0x7f67f78bdce3)
unknown function (ip: 0x7f67f78da92f)
unknown function (ip: 0x7f67f78db556)
jl_toplevel_eval_in at /usr/bin/../lib/julia/libjulia-internal.so.1 (unknown line)
unknown function (ip: 0x7f67e05a3747)
unknown function (ip: 0x7f67e06e92d1)
unknown function (ip: 0x7f67e06e8d72)
unknown function (ip: 0x7f67e080f95c)
unknown function (ip: 0x7f67e02ee472)
unknown function (ip: 0x7f67e02ee5c8)
unknown function (ip: 0x7f67f79023b2)
jl_repl_entrypoint at /usr/bin/../lib/julia/libjulia-internal.so.1 (unknown line)
main at julia (unknown line)
unknown function (ip: 0x7f67f7e4d28f)
__libc_start_main at /usr/bin/../lib/libc.so.6 (unknown line)
_start at julia (unknown line)
Allocations: 10119165 (Pool: 10116669; Big: 2496); GC: 11
[1]    3464 segmentation fault (core dumped)  julia index.jl

Julia Version: 1.7 Device: Nvidia GTX 1050 TI

serenity4 commented 2 years ago

Hi,

You are passing a raw surface pointer as second positional argument to get_physical_device_surface_formats_khr, instead you need to wrap the surface as a SurfaceKHR and pass that as a keyword argument surface = <surface>. The method with a pointer as second positional argument interprets that second argument as function pointer for vkGetPhysicalDeviceSurfaceFormatsKHR, which segfaults because it's not a function pointer. See the note in this section for more information about constructing the surface from the raw pointer.

Also you shouldn't call destroy_instance and destroy_device yourself manually, see the red note on that same section.