blob: a6e33b821a017cac0ef038902a50fc98780a04d2 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_APP_STATE_H_
#define SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_APP_STATE_H_
//
//
//
#include <stdbool.h>
#include <vulkan/vulkan_core.h>
//
//
//
#ifdef __cplusplus
extern "C" {
#endif
//
//
//
// Helper routines to initialize a Vulkan instance and device based on
// application preferences in the most simple, though flexible way.
//
// Usage example:
//
// 1) Setup a vk_app_state_config_t struct with appropriate configuration
// data (see below for details), then call vk_app_state_init() to
// initialize a vk_app_state_t instance.
//
// This creates a single VkInstance and single VkDevice according to
// the configuration data.
//
// 2) Use the Vulkan handles / queue families returned by the vk_app_state_t
// to do your work then call vk_app_state_destroy() when everything is done.
//
// 3) If |require_swapchain| was set when creating the instance, one can
// also call vk_app_state_create_surface() to create a presenstation
// surface easily. See vk_swapchain.h to see how one can use it to
// manage a Vulkan swapchain.
//
// 4) vk_app_state_poll_events() can also be used to poll for user events
// during the application's main event loop. Note that event handling
// is essentially missing at the moment: the function returns false
// only when the user closes the display window, no mouse or key event
// handling is possible for now.
//
// One can create its own surface with a different library (e.g. glfw)
// in order to perform better event handling. This function is only
// provided as a convenience to write very simple user-facing tests
// and demos.
// Device features and extensions configurations is performed through
// distinct mechanisms in order to simplify client code:
//
// - Some features or extensions have a dedicated named flag in
// |vk_app_state_config_t| in order to enable them _if_ they are available.
//
// This is very convenient because all probing is performed directly by
// vk_app_state_init(), and availability can later be checked with a
// corresponding boolean flag in |vk_app_state_t|.
//
// For example, see |vk_app_state_config_t::enable_debug_report| and the
// corresponding |vk_app_state_t::has_debug_report| flag.
//
// - The first physical device is selected by default, but this can be
// overriden by setting |physical_device| in a |vk_device_config_t| struct,
// or by setting |vendor_id| and |device_id| instead.
//
// - It is possible to provide a callback that will be called by
// vk_app_state_init() in order to let the application probe the physical
// devices after the VkInstance is created. See |device_config_callback|
// below. If the callback pointer is NULL, the values from |device_config|
// are used directly instead, to simplify client code.
//
// Maximum number of device extensions to be listed in |vk_device_config_t|.
#define VK_DEVICE_CONFIG_MAX_EXTENSIONS 16
// A small struct describing parameters that determine which Vulkan device
// to create, which which extensions, during vk_app_state_init().
typedef struct vk_device_config_t
{
// If this is not VK_NULL_HANDLE, force the use of this specific GPU
// to create a VkDevice. This also that means the xxx_id fields below are
// will be ignored.
VkPhysicalDevice physical_device;
// Vulkan vendor and device ID. May be useful to select a GPU based on
// its vendor ID (or vendor + device IDs) instead if there are several
// installed on the current device.
// NOTE: If none of |vendor_id|, |device_id| and |physical_device| are
// set, the default is to use the first listed device.
uint32_t vendor_id; // 0, or a Vulkan vendor ID.
uint32_t device_id; // 0, or a Vulkan device ID. Ignored if |vendor_id| is 0.
// If not 0, the device should provide a single queue family that provides
// all queue flags at the same time.
// NOTE: At the moment, this only supports VK_QUEUE_GRAPHICS_BIT and VK_QUEUE_COMPUTE_BIT.
VkQueueFlags required_combined_queues;
// If not 0, the device should provide single queue families that support all bits
// in this bitmask. Only bits that are not already in |required_combined_queues|
// will actually be tested here.
// NOTE: At the moment, this only supports VK_QUEUE_GRAPHICS_BIT and VK_QUEUE_COMPUTE_BIT.
VkQueueFlags required_queues; // Set of required queue family flags;
// Specify a list of required extensions to enable for the device.
uint32_t extensions_count;
const char * extensions_names[VK_DEVICE_CONFIG_MAX_EXTENSIONS];
// The list of required features to be supported by the device.
VkPhysicalDeviceFeatures2 features;
} vk_device_config_t;
// Pointer to function that will be called once per physical device just after
// the VkInstance creation, and that will need to fill a vk_device_config_t
// for it.
//
// |opaque| is a user-provided opaque pointer. |instance| is the VkInstance
// and |physical_device| is a given physical device handle.
//
// On success, should return true and set |*device_config| appropriately.
// Note that this stops the iteration.
//
// Otherwise, return false to indicate the physical device should be ignored.
typedef bool (*vk_device_config_callback_t)(void * opaque,
VkInstance instance,
VkPhysicalDevice physical_device,
vk_device_config_t * device_config);
// Structure containing configuration information for a vk_app_state_t
// instance creation.
typedef struct vk_app_state_config_t
{
const char * app_name; // Optional application name.
const char * engine_name; // Optional engine name.
bool enable_validation; // True to enable validation layers.
bool enable_pipeline_cache; // True to enable on-disk pipeline cache.
// The following enable_xxx flags are provided as a convenience to enable
// specific extensions if they are available only. I.e. vk_app_state_init()
// will do the probing and enabling automatically for all flags set to true.
// Availability can later be tested by looking at |has_xxx| flags in
// |vk_app_state_t|.
// Having dedicated named flags for these greatly simplifies client code,
// since it avoids the need for a custom |device_config_callback| to see
// if the extensions are listed.
bool enable_debug_report; // True to enable debug report callbacks if available.
// TODO(digit): Change this to |enable_debug| and support debug_utils if available.
bool enable_tracing; // True to enable tracing support.
bool enable_amd_statistics; // True to enable VK_AMD_shader_info if available.
bool enable_subgroup_size_control; // True to enable VK_EXT_subgroup_size_control if available.
// A callback and associated opaque pointer. If not NULL, the function is
// called by vk_app_state_init() in order to return device configuration data
// from the current VkInstance handle. This allows clients to probe the
// instance and select the exact device and/or extensions they need.
//
// If NULL, then the content of |device_config| is used directly instead to
// simplify client code.
vk_device_config_callback_t device_config_callback;
void * device_config_opaque;
// A vk_device_config_t describing required device configuration. Only used
// as a convenience if |device_config_callback| is NULL.
vk_device_config_t device_config;
bool require_swapchain; // True if swapchain support is required.
bool disable_swapchain_present; // True to disable swapchain presentation.
// This may not work on all platforms, and should only be used for benchmarking!
// NOTE: This is experimental, do not rely on this in the future!
} vk_app_state_config_t;
// Simple struct to gather application-specific Vulkan state for our test
// programs. Usage is:
// 1) Use vk_app_state_init() to initialize instance.
// 2) Use the handles and structs provided to perform Vulkan operations.
// 3) Call vk_app_state_destroy() to release all Vulkan resources.
typedef struct
{
VkInstance instance;
const VkAllocationCallbacks * ac;
VkDevice d;
VkPipelineCache pc;
VkPhysicalDevice pd;
VkPhysicalDeviceProperties pdp;
VkPhysicalDeviceMemoryProperties pdmp;
uint32_t qfi; // queue family index
uint32_t compute_qfi; // UINT32_MAX if not available.
// Report available optional extensions that were part of the configuration.
bool has_debug_report;
bool has_amd_statistics;
bool has_subgroup_size_control;
// internal implementation details.
uintptr_t internal_storage[512];
} vk_app_state_t;
// Initialize vk_app_state_t instance. |vendor_id| and |device_id| should
// be pointers to uint32_t values which can be either 0 or a specific Vulkan
// vendor or device ID. If both are zero, the first device will be selected.
// If both are non-zero, only this specific device will be selected. Otherwise
// results are undefined.
//
// Returns true on success, false on failure (after printing error message to
// stderr).
extern bool
vk_app_state_init(vk_app_state_t * app_state, const vk_app_state_config_t * app_state_config);
// Destroy a vk_app_state_t instance.
extern void
vk_app_state_destroy(vk_app_state_t * app_state);
// Dump state of a vk_app_state_t to stdout for debugging.
extern void
vk_app_state_print(const vk_app_state_t * app_state);
// A small structure to list the indices of queue families initialized/used
// by a given vk_app_instance_t.
#define MAX_VK_QUEUE_FAMILIES 2
typedef struct
{
uint32_t count;
uint32_t indices[MAX_VK_QUEUE_FAMILIES];
} vk_queue_families_t;
// Return the number of queue families this instance supports.
extern vk_queue_families_t
vk_app_state_get_queue_families(const vk_app_state_t * app_state);
// Create a presentation surface. |window_width| and |window_height| will be
// ignored if presentation happens on the framebuffer. This requires that
// |enable_swapchain| was set to true when creating the vk_app_state_t
// instance.
extern VkSurfaceKHR
vk_app_state_create_surface(const vk_app_state_t * app_state,
uint32_t window_width,
uint32_t window_height);
// Poll UI events, return true on success, false if the program should quit.
// This function should be called before any frame draw call.
extern bool
vk_app_state_poll_events(vk_app_state_t * app_state);
//
//
//
#ifdef __cplusplus
}
#endif
//
//
//
#endif // SRC_GRAPHICS_LIB_COMPUTE_TESTS_COMMON_VK_APP_STATE_H_