From ad7d6b405dcf19fd16e18d3f7dc902e05ec38b33 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 16 Oct 2021 17:30:56 -0700 Subject: [PATCH] glfw: add glfw.getInstanceProcAddress Signed-off-by: Stephen Gutekanst --- glfw/build.zig | 4 ++ glfw/src/c.zig | 5 ++- glfw/src/vulkan.zig | 99 +++++++++++++++++++++++++-------------------- 3 files changed, 64 insertions(+), 44 deletions(-) diff --git a/glfw/build.zig b/glfw/build.zig index 6109b38..0e87cfe 100644 --- a/glfw/build.zig +++ b/glfw/build.zig @@ -178,6 +178,10 @@ fn linkGLFW(b: *Builder, step: *std.build.LibExeObjStep, options: Options) void defer b.allocator.free(include_dir); step.addIncludeDir(include_dir); + var vulkan_include_dir = std.fs.path.join(b.allocator, &.{ thisDir(), "upstream/vulkan_headers/include" }) catch unreachable; + defer b.allocator.free(vulkan_include_dir); + step.addIncludeDir(vulkan_include_dir); + step.linkLibC(); const target = (std.zig.system.NativeTargetInfo.detect(b.allocator, step.target) catch unreachable).target; switch (target.os.tag) { diff --git a/glfw/src/c.zig b/glfw/src/c.zig index 13867b4..61a7bcc 100644 --- a/glfw/src/c.zig +++ b/glfw/src/c.zig @@ -15,4 +15,7 @@ //! pub const struct_GLFWvidmode = extern struct { //! ^ //! ``` -pub const c = @cImport(@cInclude("GLFW/glfw3.h")); +pub const c = @cImport({ + @cDefine("GLFW_INCLUDE_VULKAN", "1"); + @cInclude("GLFW/glfw3.h"); +}); diff --git a/glfw/src/vulkan.zig b/glfw/src/vulkan.zig index 4cffff8..b7a99e5 100644 --- a/glfw/src/vulkan.zig +++ b/glfw/src/vulkan.zig @@ -1,15 +1,10 @@ -// TODO(vulkan): +const std = @import("std"); -// /// Vulkan API function pointer type. -// /// -// /// Generic function pointer used for returning Vulkan API function pointers -// /// without forcing a cast from a regular pointer. -// /// -// /// see also: vulkan_proc, glfwGetInstanceProcAddress -// /// -// /// -// /// @ingroup vulkan -// typedef void (*GLFWvkproc)(void); +const c = @import("c.zig").c; +const Error = @import("errors.zig").Error; +const getError = @import("errors.zig").getError; + +// TODO(vulkan): // /// Returns whether the Vulkan loader and an ICD have been found. // /// @@ -69,38 +64,47 @@ // /// see also: vulkan_ext, glfwCreateWindowSurface // GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); -// /// Returns the address of the specified Vulkan instance function. -// /// -// /// This function returns the address of the specified Vulkan core or extension function for the -// /// specified instance. If instance is set to null it can return any function exported from the -// /// Vulkan loader, including at least the following functions: -// /// -// /// - `vkEnumerateInstanceExtensionProperties` -// /// - `vkEnumerateInstanceLayerProperties` -// /// - `vkCreateInstance` -// /// - `vkGetInstanceProcAddr` -// /// -// /// If Vulkan is not available on the machine, this function returns null and generates a -// /// glfw.Error.APIUnavailable error. Call glfw.vulkanSupported to check whether Vulkan is at least -// /// minimally available. -// /// -// /// This function is equivalent to calling `vkGetInstanceProcAddr` with a platform-specific query -// /// of the Vulkan loader as a fallback. -// /// -// /// @param[in] instance The Vulkan instance to query, or null to retrieve -// /// functions related to instance creation. -// /// @param[in] procname The ASCII encoded name of the function. -// /// @return The address of the function, or null if an -// /// error occurred. -// /// -// /// Possible errors include glfw.Error.NotInitialized and glfw.Error.APIUnavailable. -// /// -// /// @pointer_lifetime The returned function pointer is valid until the library is terminated. -// /// -// /// @thread_safety This function may be called from any thread. -// /// -// /// see also: vulkan_proc -// GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); +/// Vulkan API function pointer type. +/// +/// Generic function pointer used for returning Vulkan API function pointers. +/// +/// see also: vulkan_proc, glfw.getInstanceProcAddress +pub const VKProc = fn () callconv(.C) void; + +/// Returns the address of the specified Vulkan instance function. +/// +/// This function returns the address of the specified Vulkan core or extension function for the +/// specified instance. If instance is set to null it can return any function exported from the +/// Vulkan loader, including at least the following functions: +/// +/// - `vkEnumerateInstanceExtensionProperties` +/// - `vkEnumerateInstanceLayerProperties` +/// - `vkCreateInstance` +/// - `vkGetInstanceProcAddr` +/// +/// If Vulkan is not available on the machine, this function returns null and generates a +/// glfw.Error.APIUnavailable error. Call glfw.vulkanSupported to check whether Vulkan is at least +/// minimally available. +/// +/// This function is equivalent to calling `vkGetInstanceProcAddr` with a platform-specific query +/// of the Vulkan loader as a fallback. +/// +/// @param[in] instance The Vulkan instance to query, or null to retrieve functions related to +/// instance creation. +/// @param[in] procname The ASCII encoded name of the function. +/// @return The address of the function, or null if an error occurred. +/// +/// Possible errors include glfw.Error.NotInitialized and glfw.Error.APIUnavailable. +/// +/// @pointer_lifetime The returned function pointer is valid until the library is terminated. +/// +/// @thread_safety This function may be called from any thread. +pub inline fn getInstanceProcAddress(vk_instance: ?*opaque {}, proc_name: [*c]const u8) Error!?VKProc { + const proc_address = c.glfwGetInstanceProcAddress(if (vk_instance) |v| @ptrCast(c.VkInstance, v) else null, proc_name); + try getError(); + if (proc_address) |addr| return addr; + return null; +} // /// Returns whether the specified queue family can present images. // /// @@ -176,3 +180,12 @@ // /// // /// see also: vulkan_surface, glfw.getRequiredInstanceExtensions // GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +test "getInstanceProcAddress" { + const glfw = @import("main.zig"); + try glfw.init(); + defer glfw.terminate(); + + // syntax check only, we don't have a real vulkan instance. + _ = glfw.getInstanceProcAddress(null, "foobar") catch |err| std.debug.print("failed to get instance proc address, error={}\n", .{err}); +}