Octachron / olivine

Ocaml binding generator for vulkan
39 stars 2 forks source link

Undefined symbol error using Vk.Ext.Debug_utils #9

Open hja3 opened 1 month ago

hja3 commented 1 month ago

I think I may have encountered a bug while trying to use the debug utils extension in Olivine. The following code triggers an exception

(* example.ml *)

module A = Ctypes.CArray
module Vkt = Vk.Types
module Vkc = Vk.Core

module Utils = struct
  let ( <?> ) x s =
    match x with
    | Ok (r, x) ->
      Format.printf "%a: %s@." Vkt.Result.raw_pp r s;
      x
    | Error k ->
      Format.eprintf "Error %a: %s @." Vkt.Result.raw_pp k s;
      exit 1
  ;;
end

open Utils

module Instance = struct
  (** Creating a vulkan instance *)

  let extensions = A.of_list Ctypes.string [ "VK_EXT_debug_utils" ]
  let layers = A.of_list Ctypes.string [ "VK_LAYER_KHRONOS_validation" ]
  let create_info =
    Vkt.Instance_create_info.make
      ~flags:Vkt.Instance_create_flags.empty
      ~enabled_extension_names:extensions
      ~enabled_layer_names:layers
      ()
  ;;

  let x = Vkc.create_instance ~create_info () <?> "Instance"
end

(* BUG: undefined symbol: vkCmdBeginDebugUtilsLabelEXT *)
module Debug_utils = Vk.Ext.Debug_utils (Instance)

the output is

Success: Instance
Fatal error: exception Dl.DL_error("/nix/store/9xrls1mp0qpz6mbdfzx98nhqkkm5ygz8-vulkan-loader-1.3.290.0/lib/libvulkan.so.1: undefined symbol: vkCmdBeginDebugUtilsLabelEXT")

Initially, I suspected that the Nix environment might be at fault, but the C++ example from Vulkan Tutorial is able to use the debug utils extension in a similar environment.

Indeed, it appears that there is no such symbol 'vkCmdBeginDebugUtilsLabelEXT' in the library. The nearest I can find is one without the 'vk' prefix:

readelf -Ws --dyn-syms /nix/store/9xrls1mp0qpz6mbdfzx98nhqkkm5ygz8-vulkan-loader-1.3.290.0/lib/libvulkan.so.1 | grep CmdBeginDebugUtilsLabelEXT
    18: 00000000000135d0    32 FUNC    LOCAL  DEFAULT   12 terminator_CmdBeginDebugUtilsLabelEXT.part.0
   903: 00000000000137a0    45 FUNC    LOCAL  DEFAULT   12 terminator_CmdBeginDebugUtilsLabelEXT
   952: 0000000000013740    91 FUNC    LOCAL  DEFAULT   12 CmdBeginDebugUtilsLabelEXT
Octachron commented 1 month ago

I imagine that the C++ example is not using this specific function? It sounds like the generator will have to account for missing symbols in extension.

hja3 commented 1 month ago

Yes, that's right. The extension is really only used minimally in the C++ example. A custom debug messenger is created with a debug callback that prepends the string "validation layer: " to messages from the validation layer.

The Olivine equivalent I am trying to run looks like this:

(* ... example.ml continued ... *)

module Debug_messenger = struct
  let debug_callback _ _ cb_data_ptr _ =
    let cb_data = Ctypes.(!@cb_data_ptr) in
    let msg = Vkt.Debug_utils_messenger_callback_data_ext.message cb_data in
    Printf.eprintf "validation layer: %s\n" msg;
    false
  ;;

  let create_info =
    let severity_flags =
      Vkt.Debug_utils_message_severity_flags_ext.(verbose + warning + error)
    and type_flags =
      Vkt.Debug_utils_message_type_flags_ext.(general + validation + performance)
    in
    Vkt.Debug_utils_messenger_create_info_ext.make
      ~message_severity:severity_flags
      ~message_type:type_flags
      ~pfn_user_callback:debug_callback
      ()
  ;;

  let messenger =
    Debug_utils.create_debug_utils_messenger_ext ~instance:Instance.x ~create_info ()
    <?> "debug messenger"
  ;;
end