mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 06:04:34 +00:00
Add basic Vulkan support
Added GLFW_INCLUDE_VULKAN. Added glfwVulkanSupported, glfwGetRequiredInstanceExtensions, glfwGetInstanceProcAddress, glfwGetPhysicalDevicePresentationSupport and glfwCreateWindowSurface. Added port of LunarG SDK tri example.
This commit is contained in:
parent
c2efe87cff
commit
9b75bffc88
1
.gitignore
vendored
1
.gitignore
vendored
@ -71,5 +71,6 @@ tests/tearing
|
||||
tests/threads
|
||||
tests/title
|
||||
tests/version
|
||||
tests/vulkan
|
||||
tests/windows
|
||||
|
||||
|
23
CMake/modules/FindVulkan.cmake
Normal file
23
CMake/modules/FindVulkan.cmake
Normal file
@ -0,0 +1,23 @@
|
||||
# Find Vulkan
|
||||
#
|
||||
# VULKAN_INCLUDE_DIR
|
||||
# VULKAN_LIBRARY
|
||||
# VULKAN_FOUND
|
||||
|
||||
if (WIN32)
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VK_SDK_PATH}/Include")
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
else()
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/include")
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan HINTS
|
||||
"$ENV{VULKAN_SDK}/lib")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Vulkan DEFAULT_MSG VULKAN_LIBRARY VULKAN_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(VULKAN_INCLUDE_DIR VULKAN_LIBRARY)
|
||||
|
@ -66,6 +66,7 @@ endif()
|
||||
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Vulkan)
|
||||
|
||||
if (GLFW_BUILD_DOCS)
|
||||
set(DOXYGEN_SKIP_DOT TRUE)
|
||||
|
16
README.md
16
README.md
@ -5,9 +5,9 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
GLFW is a free, Open Source, multi-platform library for OpenGL and OpenGL ES
|
||||
application development. It provides a simple, platform-independent API for
|
||||
creating windows and contexts, reading input, handling events, etc.
|
||||
GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
|
||||
Vulkan application development. It provides a simple, platform-independent API
|
||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
Version 3.2 is _not yet described_.
|
||||
|
||||
@ -50,7 +50,7 @@ This will help both us and other people experiencing the same bug.
|
||||
|
||||
GLFW itself needs only the headers and libraries for your window system. It
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
client API (OpenGL, OpenGL ES) to enable support for them.
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
|
||||
GLFW bundles a number of dependencies in the `deps/` directory. These are only
|
||||
used by the tests and examples and are not required to build the library.
|
||||
@ -64,15 +64,22 @@ used by the tests and examples and are not required to build the library.
|
||||
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
||||
examples
|
||||
|
||||
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
|
||||
will not be included in the build.
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
- Added `glfwVulkanSupported`, `glfwGetRequiredInstanceExtensions`,
|
||||
`glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and
|
||||
`glfwCreateWindowSurface` for platform independent Vulkan support
|
||||
- Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting
|
||||
absolute and relative window size limits
|
||||
- Added `glfwGetKeyName` for querying the layout-specific name of printable
|
||||
keys
|
||||
- Added `GLFW_NO_API` for creating window without contexts
|
||||
- Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
|
||||
- Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header
|
||||
- Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values
|
||||
- Added `glfwGetGLXWindow` to query the `GLXWindow` of a window
|
||||
- Added icons to examples on Windows and OS X
|
||||
@ -168,6 +175,7 @@ skills.
|
||||
- Osman Keskin
|
||||
- Cameron King
|
||||
- Peter Knut
|
||||
- Christoph Kubisch
|
||||
- Eric Larson
|
||||
- Robin Leffmann
|
||||
- Glenn Lewis
|
||||
|
127
deps/vulkan/vk_platform.h
vendored
Normal file
127
deps/vulkan/vk_platform.h
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
//
|
||||
// File: vk_platform.h
|
||||
//
|
||||
/*
|
||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __VK_PLATFORM_H__
|
||||
#define __VK_PLATFORM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
/*
|
||||
***************************************************************************************************
|
||||
* Platform-specific directives and type declarations
|
||||
***************************************************************************************************
|
||||
*/
|
||||
|
||||
/* Platform-specific calling convention macros.
|
||||
*
|
||||
* Platforms should define these so that Vulkan clients call Vulkan commands
|
||||
* with the same calling conventions that the Vulkan implementation expects.
|
||||
*
|
||||
* VKAPI_ATTR - Placed before the return type in function declarations.
|
||||
* Useful for C++11 and GCC/Clang-style function attribute syntax.
|
||||
* VKAPI_CALL - Placed after the return type in function declarations.
|
||||
* Useful for MSVC-style calling convention syntax.
|
||||
* VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
|
||||
*
|
||||
* Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
|
||||
* Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
// On Windows, Vulkan commands use the stdcall convention
|
||||
#define VKAPI_ATTR
|
||||
#define VKAPI_CALL __stdcall
|
||||
#define VKAPI_PTR VKAPI_CALL
|
||||
#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__)
|
||||
// Android does not support Vulkan in native code using the "armeabi" ABI.
|
||||
#error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs"
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
|
||||
// On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling
|
||||
// convention, even if the application's native code is compiled with the
|
||||
// armeabi-v7a calling convention.
|
||||
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
||||
#define VKAPI_CALL
|
||||
#define VKAPI_PTR VKAPI_ATTR
|
||||
#else
|
||||
// On other platforms, use the default calling convention
|
||||
#define VKAPI_ATTR
|
||||
#define VKAPI_CALL
|
||||
#define VKAPI_PTR
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if !defined(VK_NO_STDINT_H)
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#endif // !defined(VK_NO_STDINT_H)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
// Platform-specific headers required by platform window system extensions.
|
||||
// These are enabled prior to #including "vulkan.h". The same enable then
|
||||
// controls inclusion of the extension interfaces in vulkan.h.
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
#include <android/native_window.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_MIR_KHR
|
||||
#include <mir_toolkit/client_types.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
|
||||
#endif // __VK_PLATFORM_H__
|
3775
deps/vulkan/vulkan.h
vendored
Normal file
3775
deps/vulkan/vulkan.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -674,6 +674,7 @@ INPUT = @GLFW_INTERNAL_DOCS@ \
|
||||
@GLFW_SOURCE_DIR@/docs/monitor.dox \
|
||||
@GLFW_SOURCE_DIR@/docs/window.dox \
|
||||
@GLFW_SOURCE_DIR@/docs/input.dox \
|
||||
@GLFW_SOURCE_DIR@/docs/vulkan.dox \
|
||||
@GLFW_SOURCE_DIR@/docs/rift.dox \
|
||||
@GLFW_SOURCE_DIR@/docs/compat.dox
|
||||
|
||||
@ -1590,7 +1591,8 @@ PREDEFINED = GLFWAPI= \
|
||||
GLFW_EXPOSE_NATIVE_GLX \
|
||||
GLFW_EXPOSE_NATIVE_COCOA \
|
||||
GLFW_EXPOSE_NATIVE_NSGL \
|
||||
GLFW_EXPOSE_NATIVE_EGL
|
||||
GLFW_EXPOSE_NATIVE_EGL \
|
||||
VK_VERSION_1_0
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
|
@ -80,6 +80,9 @@ header instead of the regular OpenGL header.
|
||||
`GLFW_INCLUDE_ES31` makes the GLFW header include the OpenGL ES 3.1 `GLES3/gl31.h`
|
||||
header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_VULKAN` makes the GLFW header include the Vulkan `vulkan/vulkan.h`
|
||||
header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_NONE` makes the GLFW header not include any OpenGL or OpenGL ES API
|
||||
header. This is useful in combination with an extension loading library.
|
||||
|
||||
|
@ -186,4 +186,43 @@ setting the `GLFW_OPENGL_PROFILE` or `GLFW_OPENGL_FORWARD_COMPAT` hints to
|
||||
a non-default value will cause @ref glfwCreateWindow to fail and the
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
|
||||
|
||||
|
||||
@section compat_vulkan Vulkan loader and API
|
||||
|
||||
GLFW uses the standard system-wside Vulkan loader to access the Vulkan API.
|
||||
This should be installed by graphics drivers and Vulkan SDKs. If this is not
|
||||
available, @ref glfwVulkanSupported will return `GLFW_FALSE` and all other
|
||||
Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE error.
|
||||
|
||||
|
||||
@section compat_wsi Vulkan WSI extensions
|
||||
|
||||
The Vulkan WSI extensions are used to create Vulkan surfaces for GLFW windows on
|
||||
all supported platforms.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_KHR_win32_surface` extensions to create
|
||||
surfaces on Microsoft Windows. If any of these extensions are not available,
|
||||
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
||||
surface creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
|
||||
`VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface`
|
||||
or both `VK_KHR_xlib_surface` and `VK_KHR_xcb_surface` are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_KHR_wayland_surface` extensions to create
|
||||
surfaces on Wayland. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_KHR_mir_surface` extensions to create
|
||||
surfaces on Mir. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW does not support any extensions for window surface creation on OS X,
|
||||
meaning@ref glfwGetRequiredInstanceExtensions will return an empty list and
|
||||
window surface creation will fail.
|
||||
|
||||
*/
|
||||
|
@ -26,6 +26,11 @@ as the context handle.
|
||||
To test the creation of various kinds of contexts and see their properties, run
|
||||
the `glfwinfo` test program.
|
||||
|
||||
@note Vulkan does not have a context and the Vulkan instance is created via the
|
||||
Vulkan API itself. If you will be using Vulkan to render to a window, disable
|
||||
context creation by setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to
|
||||
`GLFW_NO_API`. For more information, see the @ref vulkan.
|
||||
|
||||
|
||||
@subsection context_hints Context creation hints
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
@section main_intro Introduction
|
||||
|
||||
__GLFW__ is a free, Open Source, multi-platform library for creating windows
|
||||
with OpenGL or OpenGL ES contexts and receiving many kinds of input. It is easy
|
||||
to integrate into existing applications and does not lay claim to the main loop.
|
||||
GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
|
||||
Vulkan application development. It provides a simple, platform-independent API
|
||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
See @ref news_32 for release highlights or the
|
||||
[version history](http://www.glfw.org/changelog.html) for details.
|
||||
@ -32,6 +32,8 @@ about specific functions.
|
||||
There is a section on @ref guarantees_limitations for pointer lifetimes,
|
||||
reentrancy, thread safety, event order and backward and forward compatibility.
|
||||
|
||||
The @ref vulkan guide fills in the gaps for how to use Vulkan with GLFW.
|
||||
|
||||
The @ref rift fills in the gaps for how to use LibOVR with GLFW.
|
||||
|
||||
The [FAQ](http://www.glfw.org/faq.html) answers many common questions about the
|
||||
|
@ -17,6 +17,15 @@ GLFW now supports querying the localized name of printable keys with @ref
|
||||
glfwGetKeyName, either by key token or by scancode.
|
||||
|
||||
|
||||
@subsection news_32_vulkan Support for Vulkan
|
||||
|
||||
GLFW now supports basic integration with Vulkan with @ref glfwVulkanSupported,
|
||||
@ref glfwGetRequiredInstanceExtensions, @ref glfwGetInstanceProcAddress, @ref
|
||||
glfwGetPhysicalDevicePresentationSupport and @ref glfwCreateWindowSurface.
|
||||
Vulkan header inclusion can be selected with
|
||||
[GLFW_INCLUDE_VULKAN](@ref build_macros).
|
||||
|
||||
|
||||
@section news_31 New features in 3.1
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
|
185
docs/vulkan.dox
Normal file
185
docs/vulkan.dox
Normal file
@ -0,0 +1,185 @@
|
||||
/*!
|
||||
|
||||
@page vulkan Vulkan guide
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide is intended to fill the gaps between the Vulkan documentation and the
|
||||
rest of the GLFW documentation and is not a replacement for either.
|
||||
|
||||
To develop for Vulkan you should install an SDK for your platform, for example
|
||||
the [LunarG Vulkan SDK](http://lunarg.com/vulkan-sdk/). Apart from the headers
|
||||
and libraries, it also provides the validation layers necessary for development.
|
||||
|
||||
GLFW itself does not need a Vulkan SDK to enable support for Vulkan. However,
|
||||
any Vulkan-specific test and example programs are built only if the CMake files
|
||||
find the LunarG SDK.
|
||||
|
||||
|
||||
@section vulkan_include Including the Vulkan and GLFW header files
|
||||
|
||||
To include the Vulkan header, define `GLFW_INCLUDE_VULKAN` before including the
|
||||
GLFW header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
If you want to include the Vulkan header from a custom location or use your own
|
||||
custom Vulkan header then you need to include them before the GLFW header.
|
||||
|
||||
@code
|
||||
#include <custom/path/vulkan.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
Unless a Vulkan header is included, either by the GLFW header or above it, any
|
||||
GLFW functions that use Vulkan types will not be declared.
|
||||
|
||||
The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part
|
||||
of GLFW to work.
|
||||
|
||||
|
||||
@section vulkan_support Querying for Vulkan support
|
||||
|
||||
If you are loading the Vulkan loader dynamically instead of linking directly
|
||||
against it, you can check for the availability of a loader with @ref
|
||||
glfwVulkanSupported.
|
||||
|
||||
@code
|
||||
if (glfwVulkanSupported())
|
||||
{
|
||||
// Vulkan is available, at least for compute
|
||||
}
|
||||
@endcode
|
||||
|
||||
This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is
|
||||
performed by @ref glfwInit.
|
||||
|
||||
If no loader was found, calling any other Vulkan related GLFW function will
|
||||
generate a @ref GLFW_API_UNAVAILABLE error.
|
||||
|
||||
|
||||
@subsection vulkan_proc Querying Vulkan function pointers
|
||||
|
||||
To load any Vulkan core or extension function from the found loader, call @ref
|
||||
glfwGetInstanceProcAddress.
|
||||
|
||||
@code
|
||||
PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice)
|
||||
glfwGetInstanceProcAddress(instance, "vkCreateDevice");
|
||||
@endcode
|
||||
|
||||
This is equivalent to calling `vkGetInstanceProcAddr`. If that fails, the
|
||||
function falls back to a platform-specific query of the Vulkan loader (i.e.
|
||||
`dlsym` or `GetProcAddress`). If that also fails, the function returns `NULL`.
|
||||
For more information about `vkGetInstanceProcAddr`, see the Vulkan
|
||||
documentation.
|
||||
|
||||
Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions
|
||||
of Vulkan function. This function can be retrieved from an instance with @ref
|
||||
glfwGetInstanceProcAddress.
|
||||
|
||||
@code
|
||||
PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
|
||||
glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
|
||||
@endcode
|
||||
|
||||
Device-specific functions may execute a little bit faster, due to not having to
|
||||
dispatch internally based on the device passed to them. For more information
|
||||
about `vkGetDeviceProcAddr`, see the Vulkan documentation.
|
||||
|
||||
|
||||
@section vulkan_ext Querying required Vulkan extensions
|
||||
|
||||
To do anything useful with Vulkan you need to create an instance. If you want
|
||||
to use Vulkan to render to a window, you must enable the instance extensions
|
||||
GLFW requires to create Vulkan surfaces.
|
||||
|
||||
To query the instance extensions required, call @ref
|
||||
glfwGetRequiredInstanceExtensions.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const char** extensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
@endcode
|
||||
|
||||
These extensions must all be enabled when creating instances that are going to
|
||||
be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref
|
||||
glfwCreateWindowSurface. The set of extensions will vary depending on platform
|
||||
and may also vary depending on graphics drivers and other factors.
|
||||
|
||||
If it fails it will return `NULL` and Vulkan window surface creation will not be
|
||||
possible. You may still use Vulkan for off-screen rendering and compute work.
|
||||
|
||||
The returned array will always contain `VK_KHR_surface`, so if you don't
|
||||
require any additional extensions you can pass this list directly to the
|
||||
`VkInstanceCreateInfo` struct.
|
||||
|
||||
@code
|
||||
VkInstanceCreateInfo ici;
|
||||
|
||||
memset(&ici, 0, sizeof(ici));
|
||||
ici.enabledExtensionCount = count;
|
||||
ici.ppEnabledExtensionNames = extensions;
|
||||
...
|
||||
@endcode
|
||||
|
||||
Additional extensions may be required by future versions of GLFW. You should
|
||||
check whether any extensions you wish to enable are already in the returned
|
||||
array, as it is an error to specify an extension more than once in the
|
||||
`VkInstanceCreateInfo` struct.
|
||||
|
||||
|
||||
@section vulkan_present Querying for Vulkan presentation support
|
||||
|
||||
Not every Vulkan queue family of every device can present images to surfaces.
|
||||
To check whether a specific queue family of a physical device supports image
|
||||
presentation without first having to create a window and surface, call @ref
|
||||
glfwGetPhysicalDevicePresentationSupport.
|
||||
|
||||
@code
|
||||
if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index))
|
||||
{
|
||||
// Queue family supports image presentation
|
||||
}
|
||||
@endcode
|
||||
|
||||
The `VK_KHR_surface` extension also provides the
|
||||
`vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on
|
||||
an existing Vulkan surface.
|
||||
|
||||
|
||||
@section vulkan_window Creating the window
|
||||
|
||||
Unless you will be using OpenGL or OpenGL ES in addition to Vulkan, there is no
|
||||
need to create a context for that window. You can disable context creation by
|
||||
setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to `GLFW_NO_API`.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL);
|
||||
@endcode
|
||||
|
||||
See @ref context_less for more information.
|
||||
|
||||
|
||||
@section vulkan_surface Creating a Vulkan window surface
|
||||
|
||||
You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension)
|
||||
for a GLFW window with @ref glfwCreateWindowSurface.
|
||||
|
||||
@code
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface);
|
||||
if (err)
|
||||
{
|
||||
// Window surface creation failed
|
||||
}
|
||||
@endcode
|
||||
|
||||
It is your responsibility to destroy the surface. GLFW does not destroy it for
|
||||
you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it.
|
||||
|
||||
*/
|
@ -1,6 +1,8 @@
|
||||
|
||||
link_libraries(glfw)
|
||||
|
||||
include_directories(${glfw_INCLUDE_DIRS})
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
link_libraries("${MATH_LIBRARY}")
|
||||
endif()
|
||||
|
@ -51,6 +51,11 @@ extern "C" {
|
||||
* This is the reference documentation for context related functions. For more
|
||||
* information, see the @ref context.
|
||||
*/
|
||||
/*! @defgroup vulkan Vulkan support
|
||||
*
|
||||
* This is the reference documentation for Vulkan related functions. For more
|
||||
* information, see the @ref vulkan.
|
||||
*/
|
||||
/*! @defgroup init Initialization, version and errors
|
||||
*
|
||||
* This is the reference documentation for initialization and termination of
|
||||
@ -157,6 +162,8 @@ extern "C" {
|
||||
#if defined(GLFW_INCLUDE_GLEXT)
|
||||
#include <GLES2/gl2ext.h>
|
||||
#endif
|
||||
#elif defined(GLFW_INCLUDE_VULKAN)
|
||||
#include <vulkan/vulkan.h>
|
||||
#elif !defined(GLFW_INCLUDE_NONE)
|
||||
#include <GL/gl.h>
|
||||
#if defined(GLFW_INCLUDE_GLEXT)
|
||||
@ -539,15 +546,12 @@ extern "C" {
|
||||
* to our [issue tracker](https://github.com/glfw/glfw/issues).
|
||||
*/
|
||||
#define GLFW_OUT_OF_MEMORY 0x00010005
|
||||
/*! @brief GLFW could not find support for the requested client API on the
|
||||
* system.
|
||||
/*! @brief GLFW could not find support for the requested API on the system.
|
||||
*
|
||||
* GLFW could not find support for the requested client API on the system. If
|
||||
* emitted by functions other than @ref glfwCreateWindow, no supported client
|
||||
* API was found.
|
||||
* GLFW could not find support for the requested API on the system.
|
||||
*
|
||||
* @analysis The installed graphics driver does not support the requested
|
||||
* client API, or does not support it via the chosen context creation backend.
|
||||
* API, or does not support it via the chosen context creation backend.
|
||||
* Below are a few examples.
|
||||
*
|
||||
* @par
|
||||
@ -555,7 +559,7 @@ extern "C" {
|
||||
* supports OpenGL ES via EGL, while Nvidia and Intel only support it via
|
||||
* a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
|
||||
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
|
||||
* driver.
|
||||
* driver. Older graphics drivers do not support Vulkan.
|
||||
*/
|
||||
#define GLFW_API_UNAVAILABLE 0x00010006
|
||||
/*! @brief The requested OpenGL or OpenGL ES version is not available.
|
||||
@ -738,6 +742,20 @@ extern "C" {
|
||||
*/
|
||||
typedef void (*GLFWglproc)(void);
|
||||
|
||||
/*! @brief Vulkan API function pointer type.
|
||||
*
|
||||
* Generic function pointer used for returning Vulkan API function pointers
|
||||
* without forcing a cast from a regular pointer.
|
||||
*
|
||||
* @sa @ref vulkan_proc
|
||||
* @sa glfwGetInstanceProcAddress
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup vulkan
|
||||
*/
|
||||
typedef void (*GLFWvkproc)(void);
|
||||
|
||||
/*! @brief Opaque monitor object.
|
||||
*
|
||||
* Opaque monitor object.
|
||||
@ -3656,6 +3674,204 @@ GLFWAPI int glfwExtensionSupported(const char* extension);
|
||||
*/
|
||||
GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
|
||||
|
||||
/*! @brief Returns whether the Vulkan loader has been found.
|
||||
*
|
||||
* This function returns whether the Vulkan loader has been found. This check
|
||||
* is performed by @ref glfwInit.
|
||||
*
|
||||
* The availability of a Vulkan loader does not by itself guarantee that window
|
||||
* surface creation or even device creation is possible. Call @ref
|
||||
* glfwGetRequiredInstanceExtensions to check whether the extensions necessary
|
||||
* for Vulkan surface creation are available and @ref
|
||||
* glfwGetPhysicalDevicePresentationSupport to check whether a queue family of
|
||||
* a physical device supports image presentation.
|
||||
*
|
||||
* @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread.
|
||||
*
|
||||
* @sa @ref vulkan_support
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup vulkan
|
||||
*/
|
||||
GLFWAPI int glfwVulkanSupported(void);
|
||||
|
||||
/*! @brief Returns the Vulkan instance extensions required by GLFW.
|
||||
*
|
||||
* This function returns an array of names of Vulkan instance extensions required
|
||||
* by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the
|
||||
* list will always contains `VK_KHR_surface`, so if you don't require any
|
||||
* additional extensions you can pass this list directly to the
|
||||
* `VkInstanceCreateInfo` struct.
|
||||
*
|
||||
* If Vulkan is not available on the machine, this function returns `NULL` and
|
||||
* generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
|
||||
* to check whether Vulkan is available.
|
||||
*
|
||||
* If Vulkan is available but no set of extensions allowing window surface
|
||||
* creation was found, this function returns `NULL`. You may still use Vulkan
|
||||
* for off-screen rendering and compute work.
|
||||
*
|
||||
* @param[out] count Where to store the number of extensions in the returned
|
||||
* array. This is set to zero if an error occurred.
|
||||
* @return An array of ASCII encoded extension names, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_API_UNAVAILABLE.
|
||||
*
|
||||
* @remarks Additional extensions may be required by future versions of GLFW.
|
||||
* You should check if any extensions you wish to enable are already in the
|
||||
* returned array, as it is an error to specify an extension more than once in
|
||||
* the `VkInstanceCreateInfo` struct.
|
||||
*
|
||||
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is guaranteed to be valid only until the
|
||||
* library is terminated.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread.
|
||||
*
|
||||
* @sa @ref vulkan_ext
|
||||
* @sa glfwCreateWindowSurface
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup vulkan
|
||||
*/
|
||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(int* count);
|
||||
|
||||
#if defined(VK_VERSION_1_0)
|
||||
|
||||
/*! @brief 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 @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
|
||||
* to check whether Vulkan is 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](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_API_UNAVAILABLE.
|
||||
*
|
||||
* @pointer_lifetime The returned function pointer is valid until the library
|
||||
* is terminated.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread.
|
||||
*
|
||||
* @sa @ref vulkan_proc
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup vulkan
|
||||
*/
|
||||
GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname);
|
||||
|
||||
/*! @brief Returns whether the specified queue family can present images.
|
||||
*
|
||||
* This function returns whether the specified queue family of the specified
|
||||
* physical device supports presentation to the platform GLFW was built for.
|
||||
*
|
||||
* If Vulkan or the required window surface creation instance extensions are
|
||||
* not available on the machine, or if the specified instance was not created
|
||||
* with the required extensions, this function returns `GLFW_FALSE` and
|
||||
* generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
|
||||
* to check whether Vulkan is available and @ref
|
||||
* glfwGetRequiredInstanceExtensions to check what instance extensions are
|
||||
* required.
|
||||
*
|
||||
* @param[in] instance The instance that the physical device belongs to.
|
||||
* @param[in] device The physical device that the queue family belongs to.
|
||||
* @param[in] queuefamily The index of the queue family to query.
|
||||
* @return `GLFW_TRUE` if the queue family supports presentation, or
|
||||
* `GLFW_FALSE` otherwise.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. For
|
||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
||||
*
|
||||
* @sa @ref vulkan_present
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup vulkan
|
||||
*/
|
||||
GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
|
||||
/*! @brief Creates a Vulkan surface for the specified window.
|
||||
*
|
||||
* This function creates a Vulkan surface for the specified window.
|
||||
*
|
||||
* If the Vulkan loader was not found at initialization, this function returns
|
||||
* `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE
|
||||
* error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was
|
||||
* found.
|
||||
*
|
||||
* If the required window surface creation instance extensions are not
|
||||
* available or if the specified instance was not created with these extensions
|
||||
* enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and
|
||||
* generates a @ref GLFW_API_UNAVAILABLE error. Call @ref
|
||||
* glfwGetRequiredInstanceExtensions to check what instance extensions are
|
||||
* required.
|
||||
*
|
||||
* The window surface must be destroyed before the specified Vulkan instance.
|
||||
* It is the responsibility of the caller to destroy the window surface. GLFW
|
||||
* does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the
|
||||
* surface.
|
||||
*
|
||||
* @param[in] instance The Vulkan instance to create the surface in.
|
||||
* @param[in] window The window to create the surface for.
|
||||
* @param[in] allocator The allocator to use, or `NULL` to use the default
|
||||
* allocator.
|
||||
* @param[out] surface Where to store the handle of the surface. This is set
|
||||
* to `VK_NULL_HANDLE` if an error occurred.
|
||||
* @return `VK_SUCCESS` if successful, or a Vulkan error code if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remarks If an error occurs before the creation call is made, GLFW returns
|
||||
* the Vulkan error code most appropriate for the error. Appropriate use of
|
||||
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
||||
* elminiate almost all occurences of these errors.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. For
|
||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
||||
*
|
||||
* @sa @ref vulkan_surface
|
||||
* @sa glfwGetRequiredInstanceExtensions
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup vulkan
|
||||
*/
|
||||
GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
#endif /*VK_VERSION_1_0*/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Global definition cleanup
|
||||
|
@ -3,7 +3,7 @@ set(common_HEADERS internal.h
|
||||
"${GLFW_BINARY_DIR}/src/glfw_config.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
|
||||
set(common_SOURCES context.c init.c input.c monitor.c window.c)
|
||||
set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
|
||||
|
||||
if (_GLFW_COCOA)
|
||||
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define _glfw3_cocoa_platform_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if defined(__OBJC__)
|
||||
#import <Carbon/Carbon.h>
|
||||
@ -47,6 +48,10 @@ typedef void* id;
|
||||
#error "The Cocoa backend depends on NSGL platform support"
|
||||
#endif
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
|
||||
|
@ -1322,6 +1322,27 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return _glfw.ns.clipboardString;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
|
||||
{
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
unsigned int queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
|
@ -28,17 +28,6 @@
|
||||
#ifndef _glfw3_egl_context_h_
|
||||
#define _glfw3_egl_context_h_
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
#endif
|
||||
|
||||
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
||||
#include <EGL/eglplatform.h>
|
||||
#elif defined(_GLFW_WIN32)
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifndef GLXBadProfileARB
|
||||
#define GLXBadProfileARB 13
|
||||
|
@ -130,6 +130,8 @@ GLFWAPI int glfwInit(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfwInitVulkan();
|
||||
|
||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||
_glfwInitialized = GLFW_TRUE;
|
||||
|
||||
@ -161,6 +163,8 @@ GLFWAPI void glfwTerminate(void)
|
||||
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
||||
}
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
|
||||
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
|
||||
_glfw.monitors = NULL;
|
||||
_glfw.monitorCount = 0;
|
||||
|
127
src/internal.h
127
src/internal.h
@ -47,6 +47,26 @@
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "../include/GLFW/glfw3.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
typedef unsigned __int64 GLFWuint64;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef uint64_t GLFWuint64;
|
||||
#endif
|
||||
|
||||
typedef int GLFWbool;
|
||||
|
||||
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
||||
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
||||
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
||||
typedef struct _GLFWcontext _GLFWcontext;
|
||||
typedef struct _GLFWwindow _GLFWwindow;
|
||||
typedef struct _GLFWlibrary _GLFWlibrary;
|
||||
typedef struct _GLFWmonitor _GLFWmonitor;
|
||||
typedef struct _GLFWcursor _GLFWcursor;
|
||||
|
||||
#define GL_VERSION 0x1f02
|
||||
#define GL_NONE 0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
@ -76,16 +96,66 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
|
||||
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
|
||||
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
|
||||
|
||||
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
||||
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
||||
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
||||
typedef struct _GLFWcontext _GLFWcontext;
|
||||
typedef struct _GLFWwindow _GLFWwindow;
|
||||
typedef struct _GLFWlibrary _GLFWlibrary;
|
||||
typedef struct _GLFWmonitor _GLFWmonitor;
|
||||
typedef struct _GLFWcursor _GLFWcursor;
|
||||
#define VK_NULL_HANDLE 0
|
||||
|
||||
typedef int GLFWbool;
|
||||
typedef GLFWuint64 VkInstance;
|
||||
typedef GLFWuint64 VkPhysicalDevice;
|
||||
typedef GLFWuint64 VkSurfaceKHR;
|
||||
typedef unsigned int VkFlags;
|
||||
typedef unsigned int VkBool32;
|
||||
|
||||
typedef enum VkStructureType
|
||||
{
|
||||
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
|
||||
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
|
||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkStructureType;
|
||||
|
||||
typedef enum VkResult
|
||||
{
|
||||
VK_SUCCESS = 0,
|
||||
VK_NOT_READY = 1,
|
||||
VK_TIMEOUT = 2,
|
||||
VK_EVENT_SET = 3,
|
||||
VK_EVENT_RESET = 4,
|
||||
VK_INCOMPLETE = 5,
|
||||
VK_ERROR_OUT_OF_HOST_MEMORY = -1,
|
||||
VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
|
||||
VK_ERROR_INITIALIZATION_FAILED = -3,
|
||||
VK_ERROR_DEVICE_LOST = -4,
|
||||
VK_ERROR_MEMORY_MAP_FAILED = -5,
|
||||
VK_ERROR_LAYER_NOT_PRESENT = -6,
|
||||
VK_ERROR_EXTENSION_NOT_PRESENT = -7,
|
||||
VK_ERROR_FEATURE_NOT_PRESENT = -8,
|
||||
VK_ERROR_INCOMPATIBLE_DRIVER = -9,
|
||||
VK_ERROR_TOO_MANY_OBJECTS = -10,
|
||||
VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
|
||||
VK_ERROR_SURFACE_LOST_KHR = -1000000000,
|
||||
VK_SUBOPTIMAL_KHR = 1000001003,
|
||||
VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
|
||||
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
|
||||
VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
|
||||
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
|
||||
VK_RESULT_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkResult;
|
||||
|
||||
typedef struct VkAllocationCallbacks VkAllocationCallbacks;
|
||||
|
||||
typedef struct VkExtensionProperties
|
||||
{
|
||||
char extensionName[256];
|
||||
unsigned int specVersion;
|
||||
} VkExtensionProperties;
|
||||
|
||||
typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
|
||||
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,unsigned int*,VkExtensionProperties*);
|
||||
|
||||
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
|
||||
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
#include "cocoa_platform.h"
|
||||
@ -363,6 +433,21 @@ struct _GLFWlibrary
|
||||
_GLFWmonitor** monitors;
|
||||
int monitorCount;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
void* handle;
|
||||
char** extensions;
|
||||
int extensionCount;
|
||||
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
||||
GLFWbool KHR_surface;
|
||||
GLFWbool KHR_win32_surface;
|
||||
GLFWbool KHR_xlib_surface;
|
||||
GLFWbool KHR_xcb_surface;
|
||||
GLFWbool KHR_wayland_surface;
|
||||
GLFWbool KHR_mir_surface;
|
||||
} vk;
|
||||
|
||||
struct {
|
||||
GLFWmonitorfun monitor;
|
||||
} callbacks;
|
||||
@ -686,6 +771,18 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
||||
*/
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(int* count);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, unsigned int queuefamily);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Event API functions
|
||||
@ -920,4 +1017,16 @@ void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
|
||||
*/
|
||||
GLFWbool _glfwIsPrintable(int key);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
void _glfwInitVulkan(void);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
void _glfwTerminateVulkan(void);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
const char* _glfwGetVulkanResultString(VkResult result);
|
||||
|
||||
#endif // _glfw3_internal_h_
|
||||
|
@ -29,9 +29,24 @@
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
typedef VkFlags VkMirSurfaceCreateFlagsKHR;
|
||||
|
||||
typedef struct VkMirSurfaceCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMirSurfaceCreateFlagsKHR flags;
|
||||
MirConnection* connection;
|
||||
MirSurface* mirSurface;
|
||||
} VkMirSurfaceCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMirSurfaceKHR)(VkInstance,const VkMirSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
@ -43,6 +58,10 @@
|
||||
#error "The Mir backend depends on EGL platform support"
|
||||
#endif
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.window)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
|
||||
|
||||
|
@ -706,6 +706,76 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
|
||||
{
|
||||
char** extensions;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!_glfw.vk.KHR_mir_surface)
|
||||
return NULL;
|
||||
|
||||
extensions = calloc(2, sizeof(char*));
|
||||
extensions[0] = strdup("VK_KHR_surface");
|
||||
extensions[1] = strdup("VK_KHR_mir_surface");
|
||||
|
||||
*count = 2;
|
||||
return extensions;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
unsigned int queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceMirPresentationSupportKHR(device,
|
||||
queuefamily,
|
||||
_glfw.mir.connection);
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkMirSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
|
||||
|
||||
vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");
|
||||
if (!vkCreateMirSurfaceKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
||||
sci.display = _glfw.mir.connection;
|
||||
sci.surface = window->mir.surface;
|
||||
|
||||
err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Failed to create Vulkan surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
|
287
src/vulkan.c
Normal file
287
src/vulkan.c
Normal file
@ -0,0 +1,287 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInitVulkan(void)
|
||||
{
|
||||
VkResult err;
|
||||
VkExtensionProperties* ep;
|
||||
unsigned int i, count;
|
||||
#if defined(_GLFW_WIN32)
|
||||
const char* name = "vulkan-1.dll";
|
||||
#else
|
||||
const char* name = "libvulkan.so.1";
|
||||
#endif
|
||||
|
||||
_glfw.vk.handle = _glfw_dlopen(name);
|
||||
if (!_glfw.vk.handle)
|
||||
return;
|
||||
|
||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||
if (!_glfw.vk.GetInstanceProcAddr)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||
return;
|
||||
}
|
||||
|
||||
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
||||
vkGetInstanceProcAddr(0, "vkEnumerateInstanceExtensionProperties");
|
||||
if (!_glfw.vk.EnumerateInstanceExtensionProperties)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
||||
return;
|
||||
}
|
||||
|
||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Vulkan: Failed to query instance extension count: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
return;
|
||||
}
|
||||
|
||||
ep = calloc(count, sizeof(VkExtensionProperties));
|
||||
|
||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Vulkan: Failed to query instance extensions: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
|
||||
free(ep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
||||
_glfw.vk.KHR_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
|
||||
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
|
||||
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
|
||||
}
|
||||
|
||||
free(ep);
|
||||
|
||||
_glfw.vk.available = GLFW_TRUE;
|
||||
|
||||
if (!_glfw.vk.KHR_surface)
|
||||
return;
|
||||
|
||||
_glfw.vk.extensions =
|
||||
_glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);
|
||||
}
|
||||
|
||||
void _glfwTerminateVulkan(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _glfw.vk.extensionCount; i++)
|
||||
free(_glfw.vk.extensions[i]);
|
||||
free(_glfw.vk.extensions);
|
||||
|
||||
if (_glfw.vk.handle)
|
||||
_glfw_dlclose(_glfw.vk.handle);
|
||||
}
|
||||
|
||||
const char* _glfwGetVulkanResultString(VkResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
return "Success";
|
||||
case VK_NOT_READY:
|
||||
return "A fence or query has not yet completed";
|
||||
case VK_TIMEOUT:
|
||||
return "A wait operation has not completed in the specified time";
|
||||
case VK_EVENT_SET:
|
||||
return "An event is signaled";
|
||||
case VK_EVENT_RESET:
|
||||
return "An event is unsignaled";
|
||||
case VK_INCOMPLETE:
|
||||
return "A return array was too small for the result";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
return "A host memory allocation has failed";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
return "A device memory allocation has failed";
|
||||
case VK_ERROR_INITIALIZATION_FAILED:
|
||||
return "Initialization of an object could not be completed for implementation-specific reasons";
|
||||
case VK_ERROR_DEVICE_LOST:
|
||||
return "The logical or physical device has been lost";
|
||||
case VK_ERROR_MEMORY_MAP_FAILED:
|
||||
return "Mapping of a memory object has failed";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||
return "A requested layer is not present or could not be loaded";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||
return "A requested extension is not supported";
|
||||
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||
return "A requested feature is not supported";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
|
||||
case VK_ERROR_TOO_MANY_OBJECTS:
|
||||
return "Too many objects of the type have already been created";
|
||||
case VK_ERROR_FORMAT_NOT_SUPPORTED:
|
||||
return "A requested format is not supported on this device";
|
||||
case VK_ERROR_SURFACE_LOST_KHR:
|
||||
return "A surface is no longer available";
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
return "A swapchain no longer matches the surface properties exactly, but can still be used";
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
return "A surface has changed in such a way that it is no longer compatible with the swapchain";
|
||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
||||
return "The display used by a swapchain does not use the same presentable image layout";
|
||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
||||
return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
|
||||
case VK_ERROR_VALIDATION_FAILED_EXT:
|
||||
return "A validation layer found an error";
|
||||
default:
|
||||
return "ERROR: UNKNOWN VULKAN ERROR TOKEN";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwVulkanSupported(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
return _glfw.vk.available;
|
||||
}
|
||||
|
||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(int* count)
|
||||
{
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*count = _glfw.vk.extensionCount;
|
||||
return (const char**) _glfw.vk.extensions;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
||||
const char* procname)
|
||||
{
|
||||
GLFWvkproc proc;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
||||
if (!proc)
|
||||
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfw.vk.extensions)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Window surface creation extensions not found");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
|
||||
device,
|
||||
queuefamily);
|
||||
}
|
||||
|
||||
GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
||||
GLFWwindow* handle,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window);
|
||||
|
||||
assert(surface);
|
||||
*surface = VK_NULL_HANDLE;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
if (!_glfw.vk.extensions)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Window surface creation extensions not found");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
||||
}
|
||||
|
@ -140,6 +140,20 @@ typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
|
||||
typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);
|
||||
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
|
||||
|
||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||
|
||||
typedef struct VkWin32SurfaceCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkWin32SurfaceCreateFlagsKHR flags;
|
||||
HINSTANCE hinstance;
|
||||
HWND hwnd;
|
||||
} VkWin32SurfaceCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
|
||||
|
||||
#include "win32_joystick.h"
|
||||
|
||||
#if defined(_GLFW_WGL)
|
||||
@ -154,6 +168,10 @@ typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);
|
||||
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
|
||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
||||
|
@ -1403,6 +1403,74 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return _glfw.win32.clipboardString;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
|
||||
{
|
||||
char** extensions;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!_glfw.vk.KHR_win32_surface)
|
||||
return NULL;
|
||||
|
||||
extensions = calloc(2, sizeof(char*));
|
||||
extensions[0] = strdup("VK_KHR_surface");
|
||||
extensions[1] = strdup("VK_KHR_win32_surface");
|
||||
|
||||
*count = 2;
|
||||
return extensions;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
unsigned int queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Win32: Vulkan instance missing VK_KHR_win32_surface extension");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily);
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkWin32SurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
|
||||
|
||||
vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
|
||||
if (!vkCreateWin32SurfaceKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Win32: Vulkan instance missing VK_KHR_win32_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||
sci.hinstance = GetModuleHandle(NULL);
|
||||
sci.hwnd = window->win32.handle;
|
||||
|
||||
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create Vulkan surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
|
@ -29,6 +29,21 @@
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||
|
||||
typedef struct VkWaylandSurfaceCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkWaylandSurfaceCreateFlagsKHR flags;
|
||||
struct wl_display* display;
|
||||
struct wl_surface* surface;
|
||||
} VkWaylandSurfaceCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_time.h"
|
||||
@ -41,6 +56,10 @@
|
||||
#error "The Wayland backend depends on EGL platform support"
|
||||
#endif
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->wl.native)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.wl.display)
|
||||
|
||||
@ -75,6 +94,7 @@ typedef struct _GLFWwindowWayland
|
||||
_GLFWmonitor** monitors;
|
||||
int monitorsCount;
|
||||
int monitorsSize;
|
||||
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
|
||||
|
@ -699,6 +699,76 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
|
||||
{
|
||||
char** extensions;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!_glfw.vk.KHR_wayland_surface)
|
||||
return NULL;
|
||||
|
||||
extensions = calloc(2, sizeof(char*));
|
||||
extensions[0] = strdup("VK_KHR_surface");
|
||||
extensions[1] = strdup("VK_KHR_wayland_surface");
|
||||
|
||||
*count = 2;
|
||||
return extensions;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
unsigned int queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceWaylandPresentationSupportKHR(device,
|
||||
queuefamily,
|
||||
_glfw.wl.display);
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkWaylandSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
|
||||
|
||||
vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR");
|
||||
if (!vkCreateWaylandSurfaceKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
|
||||
sci.display = _glfw.wl.display;
|
||||
sci.surface = window->wl.surface;
|
||||
|
||||
err = vkCreateWaylandSurfaceKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create Vulkan surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
|
@ -581,6 +581,13 @@ static GLFWbool initExtensions(void)
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
_glfw.x11.x11xcb.XGetXCBConnection = (XGETXCBCONNECTION_T)
|
||||
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
||||
}
|
||||
|
||||
// Update the key code LUT
|
||||
// FIXME: We should listen to XkbMapNotify events to track changes to
|
||||
// the keyboard mapping.
|
||||
@ -789,6 +796,12 @@ int _glfwPlatformInit(void)
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
if (_glfw.x11.x11xcb.handle)
|
||||
{
|
||||
dlclose(_glfw.x11.x11xcb.handle);
|
||||
_glfw.x11.x11xcb.handle = NULL;
|
||||
}
|
||||
|
||||
if (_glfw.x11.cursor)
|
||||
{
|
||||
XFreeCursor(_glfw.x11.display, _glfw.x11.cursor);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
@ -56,6 +57,37 @@
|
||||
#include <X11/extensions/xf86vmode.h>
|
||||
#endif
|
||||
|
||||
typedef XID xcb_window_t;
|
||||
typedef XID xcb_visualid_t;
|
||||
typedef struct xcb_connection_t xcb_connection_t;
|
||||
typedef xcb_connection_t* (* XGETXCBCONNECTION_T)(Display*);
|
||||
|
||||
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
||||
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
||||
|
||||
typedef struct VkXlibSurfaceCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkXlibSurfaceCreateFlagsKHR flags;
|
||||
Display* dpy;
|
||||
Window window;
|
||||
} VkXlibSurfaceCreateInfoKHR;
|
||||
|
||||
typedef struct VkXcbSurfaceCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkXcbSurfaceCreateFlagsKHR flags;
|
||||
xcb_connection_t* connection;
|
||||
xcb_window_t window;
|
||||
} VkXcbSurfaceCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateXlibSurfaceKHR)(VkInstance,const VkXlibSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice,uint32_t,Display*,VisualID);
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
@ -71,6 +103,10 @@
|
||||
#error "No supported context creation API selected"
|
||||
#endif
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
||||
@ -207,6 +243,11 @@ typedef struct _GLFWlibraryX11
|
||||
int minor;
|
||||
} xinerama;
|
||||
|
||||
struct {
|
||||
void* handle;
|
||||
XGETXCBCONNECTION_T XGetXCBConnection;
|
||||
} x11xcb;
|
||||
|
||||
#if defined(_GLFW_HAS_XINPUT)
|
||||
struct {
|
||||
GLFWbool available;
|
||||
|
160
src/x11_window.c
160
src/x11_window.c
@ -1470,6 +1470,13 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
Visual* visual;
|
||||
int depth;
|
||||
|
||||
if (ctxconfig->api == GLFW_NO_API)
|
||||
{
|
||||
visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
|
||||
depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_GLFW_GLX)
|
||||
if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth))
|
||||
return GLFW_FALSE;
|
||||
@ -1477,6 +1484,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth))
|
||||
return GLFW_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!createWindow(window, wndconfig, visual, depth))
|
||||
return GLFW_FALSE;
|
||||
@ -2109,6 +2117,158 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return _glfw.x11.clipboardString;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
|
||||
{
|
||||
char** extensions;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!_glfw.vk.KHR_xlib_surface)
|
||||
{
|
||||
if (!_glfw.vk.KHR_xcb_surface || !_glfw.x11.x11xcb.handle)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extensions = calloc(2, sizeof(char*));
|
||||
extensions[0] = strdup("VK_KHR_surface");
|
||||
|
||||
if (_glfw.vk.KHR_xlib_surface)
|
||||
extensions[1] = strdup("VK_KHR_xlib_surface");
|
||||
else
|
||||
extensions[1] = strdup("VK_KHR_xcb_surface");
|
||||
|
||||
*count = 2;
|
||||
return extensions;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
unsigned int queuefamily)
|
||||
{
|
||||
VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display,
|
||||
_glfw.x11.screen));
|
||||
|
||||
if (_glfw.vk.KHR_xlib_surface)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"X11: Vulkan instance missing VK_KHR_xlib_surface extension");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,
|
||||
queuefamily,
|
||||
_glfw.x11.display,
|
||||
visualID);
|
||||
}
|
||||
else
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"X11: Vulkan instance missing VK_KHR_xcb_surface extension");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
xcb_connection_t* connection =
|
||||
_glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);
|
||||
if (!connection)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to retrieve XCB connection");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,
|
||||
queuefamily,
|
||||
connection,
|
||||
visualID);
|
||||
}
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
if (_glfw.vk.KHR_xlib_surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkXlibSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
|
||||
|
||||
vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR");
|
||||
if (!vkCreateXlibSurfaceKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"X11: Vulkan instance missing VK_KHR_xlib_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
sci.dpy = _glfw.x11.display;
|
||||
sci.window = window->x11.handle;
|
||||
|
||||
err = vkCreateXlibSurfaceKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to create Vulkan X11 surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
VkResult err;
|
||||
VkXcbSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
|
||||
|
||||
xcb_connection_t* connection =
|
||||
_glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);
|
||||
if (!connection)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to retrieve XCB connection");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
vkCreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR");
|
||||
if (!vkCreateXcbSurfaceKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"X11: Vulkan instance missing VK_KHR_xcb_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
||||
sci.connection = connection;
|
||||
sci.window = window->x11.handle;
|
||||
|
||||
err = vkCreateXcbSurfaceKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to create Vulkan XCB surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
|
@ -43,6 +43,13 @@ set(WINDOWS_BINARIES empty sharing tearing threads title windows)
|
||||
set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo
|
||||
iconify joysticks monitors reopen cursor)
|
||||
|
||||
if (VULKAN_FOUND)
|
||||
add_executable(vulkan WIN32 vulkan.c ${ICON})
|
||||
target_include_directories(vulkan PRIVATE "${VULKAN_INCLUDE_DIR}")
|
||||
target_link_libraries(vulkan "${VULKAN_LIBRARY}")
|
||||
list(APPEND WINDOWS_BINARIES vulkan)
|
||||
endif()
|
||||
|
||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||
FOLDER "GLFW3/Tests")
|
||||
|
||||
|
254
tests/glfwinfo.c
254
tests/glfwinfo.c
@ -24,6 +24,7 @@
|
||||
//========================================================================
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -61,7 +62,8 @@ static void usage(void)
|
||||
printf(" -d, --debug request a debug context\n");
|
||||
printf(" -f, --forward require a forward-compatible context\n");
|
||||
printf(" -h, --help show this help\n");
|
||||
printf(" -l, --list-extensions list all client API extensions\n");
|
||||
printf(" -l, --list-extensions list all Vulkan and client API extensions\n");
|
||||
printf(" --list-layers list all Vulkan layers\n");
|
||||
printf(" -m, --major=MAJOR the major number of the required "
|
||||
"client API version\n");
|
||||
printf(" -n, --minor=MINOR the minor number of the required "
|
||||
@ -96,6 +98,22 @@ static void error_callback(int error, const char* description)
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
static const char* get_device_type_name(VkPhysicalDeviceType type)
|
||||
{
|
||||
if (type == VK_PHYSICAL_DEVICE_TYPE_OTHER)
|
||||
return "other";
|
||||
else if (type == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
|
||||
return "integrated GPU";
|
||||
else if (type == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||
return "discrete GPU";
|
||||
else if (type == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)
|
||||
return "virtual GPU";
|
||||
else if (type == VK_PHYSICAL_DEVICE_TYPE_CPU)
|
||||
return "CPU";
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static const char* get_api_name(int api)
|
||||
{
|
||||
if (api == GLFW_OPENGL_API)
|
||||
@ -146,13 +164,13 @@ static const char* get_strategy_name_glfw(int strategy)
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void list_extensions(int api, int major, int minor)
|
||||
static void list_context_extensions(int api, int major, int minor)
|
||||
{
|
||||
int i;
|
||||
GLint count;
|
||||
const GLubyte* extensions;
|
||||
|
||||
printf("%s context supported extensions:\n", get_api_name(api));
|
||||
printf("%s context extensions:\n", get_api_name(api));
|
||||
|
||||
if (api == GLFW_OPENGL_API && major > 2)
|
||||
{
|
||||
@ -182,6 +200,124 @@ static void list_extensions(int api, int major, int minor)
|
||||
}
|
||||
}
|
||||
|
||||
static void list_vulkan_instance_extensions(void)
|
||||
{
|
||||
uint32_t i, ep_count = 0;
|
||||
VkExtensionProperties* ep;
|
||||
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties =
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
glfwGetInstanceProcAddress(NULL, "vkEnumerateInstanceExtensionProperties");
|
||||
|
||||
printf("Vulkan instance extensions:\n");
|
||||
|
||||
if (vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL) != VK_SUCCESS)
|
||||
return;
|
||||
|
||||
ep = calloc(ep_count, sizeof(VkExtensionProperties));
|
||||
|
||||
if (vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep) != VK_SUCCESS)
|
||||
{
|
||||
free(ep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ep_count; i++)
|
||||
printf(" %s (v%u)\n", ep[i].extensionName, ep[i].specVersion);
|
||||
|
||||
free(ep);
|
||||
}
|
||||
|
||||
static void list_vulkan_instance_layers(void)
|
||||
{
|
||||
uint32_t i, lp_count = 0;
|
||||
VkLayerProperties* lp;
|
||||
PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties =
|
||||
(PFN_vkEnumerateInstanceLayerProperties)
|
||||
glfwGetInstanceProcAddress(NULL, "vkEnumerateInstanceLayerProperties");
|
||||
|
||||
printf("Vulkan instance layers:\n");
|
||||
|
||||
if (vkEnumerateInstanceLayerProperties(&lp_count, NULL) != VK_SUCCESS)
|
||||
return;
|
||||
|
||||
lp = calloc(lp_count, sizeof(VkLayerProperties));
|
||||
|
||||
if (vkEnumerateInstanceLayerProperties(&lp_count, lp) != VK_SUCCESS)
|
||||
{
|
||||
free(lp);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lp_count; i++)
|
||||
{
|
||||
printf(" %s (v%u) \"%s\"\n",
|
||||
lp[i].layerName,
|
||||
lp[i].specVersion >> 22,
|
||||
lp[i].description);
|
||||
}
|
||||
|
||||
free(lp);
|
||||
}
|
||||
|
||||
static void list_vulkan_device_extensions(VkInstance instance, VkPhysicalDevice device)
|
||||
{
|
||||
uint32_t i, ep_count;
|
||||
VkExtensionProperties* ep;
|
||||
PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties =
|
||||
(PFN_vkEnumerateDeviceExtensionProperties)
|
||||
glfwGetInstanceProcAddress(instance, "vkEnumerateDeviceExtensionProperties");
|
||||
|
||||
printf("Vulkan device extensions:\n");
|
||||
|
||||
if (vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, NULL) != VK_SUCCESS)
|
||||
return;
|
||||
|
||||
ep = calloc(ep_count, sizeof(VkExtensionProperties));
|
||||
|
||||
if (vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, ep) != VK_SUCCESS)
|
||||
{
|
||||
free(ep);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ep_count; i++)
|
||||
printf(" %s (v%u)\n", ep[i].extensionName, ep[i].specVersion);
|
||||
|
||||
free(ep);
|
||||
}
|
||||
|
||||
static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device)
|
||||
{
|
||||
uint32_t i, lp_count;
|
||||
VkLayerProperties* lp;
|
||||
PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties =
|
||||
(PFN_vkEnumerateDeviceLayerProperties)
|
||||
glfwGetInstanceProcAddress(instance, "vkEnumerateDeviceLayerProperties");
|
||||
|
||||
printf("Vulkan device layers:\n");
|
||||
|
||||
if (vkEnumerateDeviceLayerProperties(device, &lp_count, NULL) != VK_SUCCESS)
|
||||
return;
|
||||
|
||||
lp = calloc(lp_count, sizeof(VkLayerProperties));
|
||||
|
||||
if (vkEnumerateDeviceLayerProperties(device, &lp_count, lp) != VK_SUCCESS)
|
||||
{
|
||||
free(lp);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lp_count; i++)
|
||||
{
|
||||
printf(" %s (v%u) \"%s\"\n",
|
||||
lp[i].layerName,
|
||||
lp[i].specVersion >> 22,
|
||||
lp[i].description);
|
||||
}
|
||||
|
||||
free(lp);
|
||||
}
|
||||
|
||||
static int valid_version(void)
|
||||
{
|
||||
int major, minor, revision;
|
||||
@ -216,10 +352,10 @@ int main(int argc, char** argv)
|
||||
{
|
||||
int ch, api, major, minor, revision, profile;
|
||||
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
|
||||
int list = GLFW_FALSE;
|
||||
int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE;
|
||||
GLFWwindow* window;
|
||||
|
||||
enum { API, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS,
|
||||
enum { API, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS, LAYERS,
|
||||
MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
|
||||
REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
|
||||
ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
|
||||
@ -232,6 +368,7 @@ int main(int argc, char** argv)
|
||||
{ "forward", 0, NULL, FORWARD },
|
||||
{ "help", 0, NULL, HELP },
|
||||
{ "list-extensions", 0, NULL, EXTENSIONS },
|
||||
{ "list-layers", 0, NULL, LAYERS },
|
||||
{ "major", 1, NULL, MAJOR },
|
||||
{ "minor", 1, NULL, MINOR },
|
||||
{ "profile", 1, NULL, PROFILE },
|
||||
@ -314,7 +451,10 @@ int main(int argc, char** argv)
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'l':
|
||||
case EXTENSIONS:
|
||||
list = GLFW_TRUE;
|
||||
list_extensions = GLFW_TRUE;
|
||||
break;
|
||||
case LAYERS:
|
||||
list_layers = GLFW_TRUE;
|
||||
break;
|
||||
case 'm':
|
||||
case MAJOR:
|
||||
@ -564,7 +704,7 @@ int main(int argc, char** argv)
|
||||
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
}
|
||||
|
||||
printf("Framebuffer:\n");
|
||||
printf("%s framebuffer:\n", get_api_name(api));
|
||||
|
||||
if (api == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
|
||||
{
|
||||
@ -632,9 +772,103 @@ int main(int argc, char** argv)
|
||||
accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
|
||||
}
|
||||
|
||||
// Report client API extensions
|
||||
if (list)
|
||||
list_extensions(api, major, minor);
|
||||
if (list_extensions)
|
||||
list_context_extensions(api, major, minor);
|
||||
|
||||
printf("Vulkan loader: %s\n",
|
||||
glfwVulkanSupported() ? "available" : "missing");
|
||||
|
||||
if (glfwVulkanSupported())
|
||||
{
|
||||
uint32_t i, re_count, pd_count;
|
||||
const char** re;
|
||||
VkApplicationInfo ai = {0};
|
||||
VkInstanceCreateInfo ici = {0};
|
||||
VkInstance instance;
|
||||
VkPhysicalDevice* pd;
|
||||
PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)
|
||||
glfwGetInstanceProcAddress(NULL, "vkCreateInstance");
|
||||
PFN_vkDestroyInstance vkDestroyInstance;
|
||||
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
|
||||
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
|
||||
|
||||
re = glfwGetRequiredInstanceExtensions((int*) &re_count);
|
||||
|
||||
printf("Vulkan required instance extensions:");
|
||||
for (i = 0; i < re_count; i++)
|
||||
printf(" %s", re[i]);
|
||||
putchar('\n');
|
||||
|
||||
if (list_extensions)
|
||||
{
|
||||
list_vulkan_instance_extensions();
|
||||
}
|
||||
|
||||
if (list_layers)
|
||||
list_vulkan_instance_layers();
|
||||
|
||||
ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
ai.pApplicationName = "glfwinfo";
|
||||
ai.applicationVersion = GLFW_VERSION_MAJOR;
|
||||
ai.pEngineName = "GLFW";
|
||||
ai.engineVersion = GLFW_VERSION_MAJOR;
|
||||
ai.apiVersion = VK_API_VERSION;
|
||||
|
||||
ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
ici.pApplicationInfo = &ai;
|
||||
ici.enabledExtensionCount = re_count;
|
||||
ici.ppEnabledExtensionNames = re;
|
||||
|
||||
if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
vkDestroyInstance = (PFN_vkDestroyInstance)
|
||||
glfwGetInstanceProcAddress(instance, "vkDestroyInstance");
|
||||
vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)
|
||||
glfwGetInstanceProcAddress(instance, "vkEnumeratePhysicalDevices");
|
||||
vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)
|
||||
glfwGetInstanceProcAddress(instance, "vkGetPhysicalDeviceProperties");
|
||||
|
||||
if (vkEnumeratePhysicalDevices(instance, &pd_count, NULL) != VK_SUCCESS)
|
||||
{
|
||||
vkDestroyInstance(instance, NULL);
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pd = calloc(pd_count, sizeof(VkPhysicalDevice));
|
||||
|
||||
if (vkEnumeratePhysicalDevices(instance, &pd_count, pd) != VK_SUCCESS)
|
||||
{
|
||||
free(pd);
|
||||
vkDestroyInstance(instance, NULL);
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < pd_count; i++)
|
||||
{
|
||||
VkPhysicalDeviceProperties pdp;
|
||||
|
||||
vkGetPhysicalDeviceProperties(pd[i], &pdp);
|
||||
|
||||
printf("Vulkan %s device: \"%s\"\n",
|
||||
get_device_type_name(pdp.deviceType),
|
||||
pdp.deviceName);
|
||||
|
||||
if (list_extensions)
|
||||
list_vulkan_device_extensions(instance, pd[i]);
|
||||
|
||||
if (list_layers)
|
||||
list_vulkan_device_layers(instance, pd[i]);
|
||||
}
|
||||
|
||||
free(pd);
|
||||
vkDestroyInstance(instance, NULL);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
|
2240
tests/vulkan.c
Normal file
2240
tests/vulkan.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user