mirror of
https://github.com/lbgos/rift-s-linux.git
synced 2026-10-17 14:00:55 +02:00
u/extension_list: Refactor and rename from u_string_list
Co-authored-by: Korcan Hussein <korcan.hussein@collabora.com> Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2693>
This commit is contained in:
1 parent
ea9d89dae0
commit
f874b12e43
25 files changed
+1275
-886
No files matched your search
@@ -1,5 +1,5 @@
|
||||
# Copyright 2019-2024, Collabora, Ltd.
|
||||
# Copyright 2024-2025, NVIDIA CORPORATION.
|
||||
# Copyright 2024-2026, NVIDIA CORPORATION.
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
####
|
||||
@@ -89,9 +89,9 @@ add_library(
|
||||
u_session.h
|
||||
u_space_overseer.c
|
||||
u_space_overseer.h
|
||||
u_string_list.cpp
|
||||
u_string_list.h
|
||||
u_string_list.hpp
|
||||
u_extension_list.cpp
|
||||
u_extension_list.h
|
||||
u_extension_list.hpp
|
||||
u_system.c
|
||||
u_system.h
|
||||
u_system_helpers.c
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
// Copyright 2021-2026, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings for extensions.
|
||||
*
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
|
||||
#include "u_extension_list.h"
|
||||
#include "u_extension_list.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Defines and structs.
|
||||
*
|
||||
*/
|
||||
|
||||
using xrt::auxiliary::util::ExtensionList;
|
||||
using xrt::auxiliary::util::ExtensionListBuilder;
|
||||
|
||||
struct u_extension_list
|
||||
{
|
||||
u_extension_list() = default;
|
||||
u_extension_list(ExtensionList &&extension_list) : list(std::move(extension_list)) {}
|
||||
|
||||
ExtensionList list;
|
||||
};
|
||||
|
||||
struct u_extension_list_builder
|
||||
{
|
||||
u_extension_list_builder() = default;
|
||||
u_extension_list_builder(size_t capacity) : builder(capacity) {}
|
||||
|
||||
u_extension_list_builder(u_extension_list_builder &&) = delete;
|
||||
u_extension_list_builder(u_extension_list_builder const &) = delete;
|
||||
|
||||
u_extension_list_builder &
|
||||
operator=(u_extension_list_builder &&) = delete;
|
||||
u_extension_list_builder &
|
||||
operator=(u_extension_list_builder const &) = delete;
|
||||
|
||||
ExtensionListBuilder builder;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Helpers
|
||||
*
|
||||
*/
|
||||
|
||||
enum class ExtensionType
|
||||
{
|
||||
KHR = 0, // Khronos extensions
|
||||
EXT = 1, // Multi-vendor extensions
|
||||
VENDOR = 2, // Vendor-specific extensions (AMD, NV, INTEL, etc.)
|
||||
EXPERIMENTAL = 3 // Experimental extensions
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Helper class for sorting extension names.
|
||||
*
|
||||
* Encapsulates the sort key with comparison operators for cleaner sorting.
|
||||
*/
|
||||
struct ExtensionSortKey
|
||||
{
|
||||
std::string_view api_prefix;
|
||||
ExtensionType type;
|
||||
std::string_view name;
|
||||
|
||||
/*!
|
||||
* Sorts in field declaration order:
|
||||
*
|
||||
* 1. API prefix (VK, XR, etc.)
|
||||
* 2. Extension type (KHR < EXT < VENDOR < EXPERIMENTAL)
|
||||
* 3. Alphabetically by full name
|
||||
*/
|
||||
auto
|
||||
operator<=>(const ExtensionSortKey &other) const = default;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Check if a vendor string represents an experimental extension.
|
||||
*
|
||||
* Experimental extensions have vendor codes ending with 'X' optionally followed
|
||||
* by digits.
|
||||
*
|
||||
* Examples: NVX, AMDX, NVX1, NVX2, INTELX
|
||||
*
|
||||
* Special case: QNX is a legitimate vendor (QNX operating system), not
|
||||
* experimental.
|
||||
*/
|
||||
static bool
|
||||
is_experimental_vendor(std::string_view vendor)
|
||||
{
|
||||
// Special case: QNX is a legitimate vendor, not experimental
|
||||
if (vendor == "QNX") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if vendor ends with 'X' optionally followed by digits
|
||||
if (vendor.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t len = vendor.length();
|
||||
size_t i = len - 1;
|
||||
|
||||
// Skip trailing digits
|
||||
while (i > 0 && std::isdigit(vendor[i])) {
|
||||
i--;
|
||||
}
|
||||
|
||||
// Check if we found an 'X' and there's something before it
|
||||
return (vendor[i] == 'X' && i > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the extension type and API prefix for sorting purposes.
|
||||
*
|
||||
* Returns an ExtensionSortKey for comparison.
|
||||
*/
|
||||
static ExtensionSortKey
|
||||
get_extension_sort_key(std::string_view name)
|
||||
{
|
||||
// Find the first underscore to separate API prefix (e.g., "VK", "XR")
|
||||
size_t first_underscore = name.find('_');
|
||||
if (first_underscore == std::string::npos) {
|
||||
// No underscore, treat as is
|
||||
return {name, ExtensionType::VENDOR, name};
|
||||
}
|
||||
|
||||
std::string_view api_prefix = name.substr(0, first_underscore);
|
||||
|
||||
// Find the second underscore to get the vendor/type part
|
||||
size_t second_underscore = name.find('_', first_underscore + 1);
|
||||
if (second_underscore == std::string::npos) {
|
||||
// Only one underscore, treat as vendor
|
||||
return {api_prefix, ExtensionType::VENDOR, name};
|
||||
}
|
||||
|
||||
std::string_view vendor = name.substr(first_underscore + 1, second_underscore - first_underscore - 1);
|
||||
|
||||
// Determine extension type based on vendor string
|
||||
ExtensionType type;
|
||||
if (vendor == "KHR") {
|
||||
type = ExtensionType::KHR;
|
||||
} else if (vendor == "EXT") {
|
||||
type = ExtensionType::EXT;
|
||||
} else if (is_experimental_vendor(vendor)) {
|
||||
type = ExtensionType::EXPERIMENTAL;
|
||||
} else {
|
||||
type = ExtensionType::VENDOR;
|
||||
}
|
||||
|
||||
return {api_prefix, type, name};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 'Exported' functions - Immutable Extension List
|
||||
*
|
||||
*/
|
||||
|
||||
struct u_extension_list *
|
||||
u_extension_list_create()
|
||||
{
|
||||
try {
|
||||
auto ret = std::make_unique<u_extension_list>();
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_extension_list *
|
||||
u_extension_list_create_from_array(const char *const *arr, uint32_t size)
|
||||
{
|
||||
if (arr == nullptr || size == 0) {
|
||||
return u_extension_list_create();
|
||||
}
|
||||
try {
|
||||
ExtensionListBuilder builder(size);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
if (arr[i] != nullptr) {
|
||||
builder.append(arr[i]);
|
||||
}
|
||||
}
|
||||
auto ret = std::make_unique<u_extension_list>(std::move(builder).build());
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
u_extension_list_get_size(const struct u_extension_list *uel)
|
||||
{
|
||||
if (uel == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return uel->list.size();
|
||||
}
|
||||
|
||||
const char *const *
|
||||
u_extension_list_get_data(const struct u_extension_list *uel)
|
||||
{
|
||||
if (uel == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return uel->list.data();
|
||||
}
|
||||
|
||||
bool
|
||||
u_extension_list_contains(const struct u_extension_list *uel, const char *str)
|
||||
{
|
||||
if (uel == nullptr || str == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return uel->list.contains(str);
|
||||
}
|
||||
|
||||
bool
|
||||
u_extension_list_contains_len(const struct u_extension_list *uel, const char *str, size_t len)
|
||||
{
|
||||
if (uel == nullptr || str == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return uel->list.contains(std::string_view(str, len));
|
||||
}
|
||||
|
||||
void
|
||||
u_extension_list_destroy(struct u_extension_list **list_ptr)
|
||||
{
|
||||
if (list_ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
u_extension_list *list = *list_ptr;
|
||||
if (list == nullptr) {
|
||||
return;
|
||||
}
|
||||
delete list;
|
||||
*list_ptr = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Extension List Builder Methods
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
ExtensionListBuilder::sortForExtensions()
|
||||
{
|
||||
if (strings.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort using our custom comparison function that works with std::string
|
||||
auto cmp = [](const std::string &a, const std::string &b) {
|
||||
return get_extension_sort_key(a) < get_extension_sort_key(b);
|
||||
};
|
||||
std::sort(strings.begin(), strings.end(), cmp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 'Exported' functions - Extension List Builder
|
||||
*
|
||||
*/
|
||||
|
||||
struct u_extension_list_builder *
|
||||
u_extension_list_builder_create()
|
||||
{
|
||||
try {
|
||||
auto ret = std::make_unique<u_extension_list_builder>();
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_extension_list_builder *
|
||||
u_extension_list_builder_create_with_capacity(uint32_t capacity)
|
||||
{
|
||||
try {
|
||||
auto ret = std::make_unique<u_extension_list_builder>(capacity);
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_extension_list_builder *
|
||||
u_extension_list_builder_create_from_array(const char *const *arr, uint32_t size)
|
||||
{
|
||||
if (arr == nullptr || size == 0) {
|
||||
return u_extension_list_builder_create();
|
||||
}
|
||||
try {
|
||||
auto ret = std::make_unique<u_extension_list_builder>();
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
if (arr[i] != nullptr) {
|
||||
ret->builder.append(arr[i]);
|
||||
}
|
||||
}
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_extension_list_builder_append(struct u_extension_list_builder *uelb, const char *str)
|
||||
{
|
||||
if (uelb == nullptr || str == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
uelb->builder.append(str);
|
||||
return 1;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_extension_list_builder_append_len(struct u_extension_list_builder *uelb, const char *str, size_t len)
|
||||
{
|
||||
if (uelb == nullptr || str == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
uelb->builder.append(std::string_view(str, len));
|
||||
return 1;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_extension_list_builder_append_array(struct u_extension_list_builder *uelb, const char *const *arr, uint32_t size)
|
||||
{
|
||||
if (uelb == nullptr || arr == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
if (arr[i] != nullptr) {
|
||||
uelb->builder.append(arr[i]);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_extension_list_builder_append_unique(struct u_extension_list_builder *uelb, const char *str)
|
||||
{
|
||||
if (uelb == nullptr || str == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
auto added = uelb->builder.appendUnique(str);
|
||||
return added ? 1 : 0;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_extension_list_builder_append_unique_len(struct u_extension_list_builder *uelb, const char *str, size_t len)
|
||||
{
|
||||
if (uelb == nullptr || str == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
auto added = uelb->builder.appendUnique(std::string_view(str, len));
|
||||
return added ? 1 : 0;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_extension_list *
|
||||
u_extension_list_builder_build(struct u_extension_list_builder **builder_ptr)
|
||||
{
|
||||
u_extension_list_builder *builder = *builder_ptr;
|
||||
if (builder == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
auto ret = std::make_unique<u_extension_list>(std::move(builder->builder).build());
|
||||
delete builder;
|
||||
*builder_ptr = nullptr;
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_extension_list *
|
||||
u_extension_list_builder_build_sorted_for_extensions(struct u_extension_list_builder **builder_ptr)
|
||||
{
|
||||
u_extension_list_builder *builder = *builder_ptr;
|
||||
if (builder == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
// Sort the builder in-place before building
|
||||
builder->builder.sortForExtensions();
|
||||
|
||||
// Now build the sorted list
|
||||
auto ret = std::make_unique<u_extension_list>(std::move(builder->builder).build());
|
||||
delete builder;
|
||||
*builder_ptr = nullptr;
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
u_extension_list_builder_destroy(struct u_extension_list_builder **builder_ptr)
|
||||
{
|
||||
u_extension_list_builder *builder = *builder_ptr;
|
||||
if (builder == nullptr) {
|
||||
return;
|
||||
}
|
||||
delete builder;
|
||||
*builder_ptr = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
// Copyright 2021, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "xrt/xrt_compiler.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
* @brief An immutable collection of extension strings, these are used to
|
||||
* interface with APIs such as Vulkan and OpenXR who use strings for extensions.
|
||||
*
|
||||
* This structure stores copies of strings internally and provides read-only access.
|
||||
*
|
||||
* @see xrt::auxiliary::util::ExtensionList
|
||||
*/
|
||||
struct u_extension_list;
|
||||
|
||||
/*!
|
||||
* @brief A builder for constructing immutable extension lists.
|
||||
*
|
||||
* This structure allows write-only operations to build up a list of extension
|
||||
* strings.
|
||||
*
|
||||
* @see xrt::auxiliary::util::ExtensionListBuilder
|
||||
*/
|
||||
struct u_extension_list_builder;
|
||||
|
||||
/*
|
||||
*
|
||||
* Immutable Extension List API
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Create an empty extension list, some APIs might require an extension
|
||||
* list to be passed in so there is some utility for this function.
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
struct u_extension_list *
|
||||
u_extension_list_create(void);
|
||||
|
||||
/*!
|
||||
* @brief Create a new extension list from an array of strings.
|
||||
*
|
||||
* The strings are copied into the list.
|
||||
*
|
||||
* @param arr an array of zero or more non-null, null-terminated strings.
|
||||
* @param size the number of elements in the array.
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
struct u_extension_list *
|
||||
u_extension_list_create_from_array(const char *const *arr, uint32_t size);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the number of elements in the list
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
uint32_t
|
||||
u_extension_list_get_size(const struct u_extension_list *uel);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the data pointer of the list
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
const char *const *
|
||||
u_extension_list_get_data(const struct u_extension_list *uel);
|
||||
|
||||
/*!
|
||||
* @brief Check if the string is in the list.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a non-null, null-terminated string.
|
||||
*
|
||||
* @return true if the string is in the list.
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
bool
|
||||
u_extension_list_contains(const struct u_extension_list *uel, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Check if the string is in the list.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a string pointer.
|
||||
* @param len the length of the string.
|
||||
*
|
||||
* @return true if the string is in the list.
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
bool
|
||||
u_extension_list_contains_len(const struct u_extension_list *uel, const char *str, size_t len);
|
||||
|
||||
/*!
|
||||
* @brief Destroy an extension list.
|
||||
*
|
||||
* Performs null checks and sets your pointer to zero.
|
||||
*
|
||||
* @public @memberof u_extension_list
|
||||
*/
|
||||
void
|
||||
u_extension_list_destroy(struct u_extension_list **list_ptr);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Extension List Builder API
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Create an extension list builder.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
struct u_extension_list_builder *
|
||||
u_extension_list_builder_create(void);
|
||||
|
||||
/*!
|
||||
* @brief Create an extension list builder with room for at least the given number of strings.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
struct u_extension_list_builder *
|
||||
u_extension_list_builder_create_with_capacity(uint32_t capacity);
|
||||
|
||||
/*!
|
||||
* @brief Create an extension list builder from an array of strings.
|
||||
*
|
||||
* The strings are copied into the builder.
|
||||
*
|
||||
* @param arr an array of zero or more non-null, null-terminated strings.
|
||||
* @param size the number of elements in the array.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
struct u_extension_list_builder *
|
||||
u_extension_list_builder_create_from_array(const char *const *arr, uint32_t size);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the builder.
|
||||
*
|
||||
* The string is copied into the builder.
|
||||
*
|
||||
* @param uslb self pointer
|
||||
* @param str a non-null, null-terminated string.
|
||||
* @return 1 if successfully added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
int
|
||||
u_extension_list_builder_append(struct u_extension_list_builder *uelb, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the builder.
|
||||
*
|
||||
* The string is copied into the builder.
|
||||
*
|
||||
* @param uslb self pointer
|
||||
* @param str a string pointer.
|
||||
* @param len the length of the string.
|
||||
* @return 1 if successfully added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
int
|
||||
u_extension_list_builder_append_len(struct u_extension_list_builder *uelb, const char *str, size_t len);
|
||||
|
||||
/*!
|
||||
* @brief Append an array of new strings to the builder.
|
||||
*
|
||||
* The strings are copied into the builder.
|
||||
*
|
||||
* @param uslb self pointer
|
||||
* @param arr an array of zero or more non-null, null-terminated strings.
|
||||
* @param size the number of elements in the array.
|
||||
* @return 1 if successfully added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
int
|
||||
u_extension_list_builder_append_array(struct u_extension_list_builder *uelb, const char *const *arr, uint32_t size);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the builder, if it's not the same as a string already in the builder.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* The string is copied into the builder.
|
||||
*
|
||||
* @param uslb self pointer
|
||||
* @param str a non-null, null-terminated string.
|
||||
* @return 1 if successfully added, 0 if already existing so not added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
int
|
||||
u_extension_list_builder_append_unique(struct u_extension_list_builder *uelb, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the builder, if it's not the same as a string already in the builder.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* The string is copied into the builder.
|
||||
*
|
||||
* @param uslb self pointer
|
||||
* @param str a string pointer.
|
||||
* @param len the length of the string.
|
||||
* @return 1 if successfully added, 0 if already existing so not added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
int
|
||||
u_extension_list_builder_append_unique_len(struct u_extension_list_builder *uelb, const char *str, size_t len);
|
||||
|
||||
/*!
|
||||
* @brief Build an immutable extension list from the builder.
|
||||
*
|
||||
* After calling this, the builder is destroyed and the pointer is set to NULL.
|
||||
*
|
||||
* @param builder_ptr pointer to self pointer
|
||||
* @return a new immutable extension list, or NULL on error.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
XRT_NONNULL_ALL struct u_extension_list *
|
||||
u_extension_list_builder_build(struct u_extension_list_builder **builder_ptr);
|
||||
|
||||
/*!
|
||||
* @brief Build an immutable extension list from the builder and sort it for
|
||||
* extension lists.
|
||||
*
|
||||
* The list will be sorted first by API (VK, XR, etc.), then all KHR extensions,
|
||||
* then all EXT extensions, then all Vendor extensions, then all experimental
|
||||
* extensions. (Alphabetical within each group.)
|
||||
*
|
||||
* After calling this, the builder is destroyed and the pointer is set to NULL.
|
||||
*
|
||||
* @param builder_ptr pointer to self pointer
|
||||
* @return a new immutable extension list, sorted for extension lists, or NULL on error.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
XRT_NONNULL_ALL struct u_extension_list *
|
||||
u_extension_list_builder_build_sorted_for_extensions(struct u_extension_list_builder **builder_ptr);
|
||||
|
||||
/*!
|
||||
* @brief Destroy an extension list builder.
|
||||
*
|
||||
* Performs null checks and sets your pointer to zero.
|
||||
*
|
||||
* @public @memberof u_extension_list_builder
|
||||
*/
|
||||
XRT_NONNULL_ALL void
|
||||
u_extension_list_builder_destroy(struct u_extension_list_builder **builder_ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -0,0 +1,249 @@
|
||||
// Copyright 2021, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "u_extension_list.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace xrt::auxiliary::util {
|
||||
|
||||
// Forward declaration
|
||||
class ExtensionListBuilder;
|
||||
|
||||
/*!
|
||||
* @brief An immutable collection of strings, like a list of extensions to enable.
|
||||
*
|
||||
* This class stores copies of strings internally and provides read-only access.
|
||||
*
|
||||
* Size is limited to one less than the max value of uint32_t which shouldn't be a problem,
|
||||
* the size really should be much smaller.
|
||||
*/
|
||||
class ExtensionList
|
||||
{
|
||||
public:
|
||||
//! Default constructor - creates an empty list
|
||||
ExtensionList() = default;
|
||||
|
||||
//! Move constructor
|
||||
ExtensionList(ExtensionList &&) = default;
|
||||
|
||||
//! Copy constructor, makes sure to do a deep copy.
|
||||
ExtensionList(ExtensionList const &other) : ExtensionList({other.strings.begin(), other.strings.end()}) {}
|
||||
|
||||
//! Move assignment
|
||||
ExtensionList &
|
||||
operator=(ExtensionList &&) = default;
|
||||
|
||||
//! Copy assignment
|
||||
ExtensionList &
|
||||
operator=(ExtensionList const &other)
|
||||
{
|
||||
/*
|
||||
* This uses the move assignment to set this to a deep copy of
|
||||
* the other list. We need to do a deep copy of the other list
|
||||
* so that the set and pointers are correctly recalculated using
|
||||
* the new strings.
|
||||
*/
|
||||
return *this = ExtensionList(other);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the size of the array (the number of strings)
|
||||
*/
|
||||
uint32_t
|
||||
size() const noexcept
|
||||
{
|
||||
return static_cast<uint32_t>(ptrs.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the data pointer of the array (array of const char*)
|
||||
*/
|
||||
const char *const *
|
||||
data() const noexcept
|
||||
{
|
||||
return ptrs.data();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Check if the string is in the list.
|
||||
*
|
||||
* (Comparing string contents)
|
||||
*
|
||||
* @param str a string view to search for.
|
||||
*
|
||||
* @return true if the string is in the list.
|
||||
*/
|
||||
bool
|
||||
contains(std::string_view str) const
|
||||
{
|
||||
return set.find(str) != set.end();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
friend class ExtensionListBuilder;
|
||||
|
||||
//! Main storage of strings.
|
||||
std::vector<std::string> strings;
|
||||
|
||||
/*!
|
||||
* Internal set of strings for fast lookup, memory kept alive by the
|
||||
* strings vector. Used to quickly check if a string is in the list.
|
||||
*/
|
||||
std::unordered_set<std::string_view> set;
|
||||
|
||||
/*!
|
||||
* Internal vector of pointers to the strings, memory kept alive by the
|
||||
* strings vector.
|
||||
*/
|
||||
std::vector<const char *> ptrs;
|
||||
|
||||
|
||||
private:
|
||||
// Internal constructor used by ExtensionListBuilder
|
||||
ExtensionList(std::vector<std::string> &&strings_) : strings(std::move(strings_))
|
||||
{
|
||||
ptrs.reserve(strings.size());
|
||||
for (const auto &s : strings) {
|
||||
set.insert(s);
|
||||
ptrs.push_back(s.c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief A builder for constructing ExtensionList objects.
|
||||
*
|
||||
* This class allows write-only operations to build up an extension list,
|
||||
* which can then be converted to an immutable ExtensionList.
|
||||
*/
|
||||
class ExtensionListBuilder
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
ExtensionListBuilder() = default;
|
||||
|
||||
//! Construct with capacity hint
|
||||
explicit ExtensionListBuilder(uint32_t capacity)
|
||||
{
|
||||
strings.reserve(capacity);
|
||||
}
|
||||
|
||||
//! Construct from an array of strings
|
||||
template <uint32_t N> explicit ExtensionListBuilder(const char *(&arr)[N])
|
||||
{
|
||||
strings.reserve(N);
|
||||
for (auto &&elt : arr) {
|
||||
append(elt);
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionListBuilder(ExtensionListBuilder &&) = delete;
|
||||
ExtensionListBuilder(ExtensionListBuilder const &) = delete;
|
||||
|
||||
ExtensionListBuilder &
|
||||
operator=(ExtensionListBuilder &&) = delete;
|
||||
ExtensionListBuilder &
|
||||
operator=(ExtensionListBuilder const &) = delete;
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the builder.
|
||||
*
|
||||
* @param str a string view to append.
|
||||
*
|
||||
* @throws std::out_of_range if you have a ridiculous number of strings in your list already.
|
||||
*/
|
||||
void
|
||||
append(std::string_view str)
|
||||
{
|
||||
if (strings.size() > (std::numeric_limits<uint32_t>::max)() - 1) {
|
||||
throw std::out_of_range("Size limit reached");
|
||||
}
|
||||
strings.emplace_back(str);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the builder if it doesn't match any existing string.
|
||||
*
|
||||
* (Comparing string contents)
|
||||
*
|
||||
* @param str a string view to append.
|
||||
*
|
||||
* @return true if we added it
|
||||
*
|
||||
* @throws std::out_of_range if you have a ridiculous number of strings in your list already.
|
||||
*/
|
||||
bool
|
||||
appendUnique(std::string_view str)
|
||||
{
|
||||
if (strings.size() > (std::numeric_limits<uint32_t>::max)() - 1) {
|
||||
throw std::out_of_range("Size limit reached");
|
||||
}
|
||||
auto it =
|
||||
std::find_if(strings.begin(), strings.end(), [str](const std::string &elt) { return str == elt; });
|
||||
if (it != strings.end()) {
|
||||
// already have it
|
||||
return false;
|
||||
}
|
||||
strings.emplace_back(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sort the strings in the builder suitable for extension lists.
|
||||
*
|
||||
* The list will be sorted first by API (VK, XR, etc.), then all KHR extensions,
|
||||
* then all EXT extensions, then all Vendor extensions, then all experimental
|
||||
* extensions. (Alphabetical within each group.)
|
||||
*
|
||||
* This modifies the builder in-place.
|
||||
*/
|
||||
void
|
||||
sortForExtensions();
|
||||
|
||||
/*!
|
||||
* @brief Build and return an immutable ExtensionList.
|
||||
*
|
||||
* This function consumes the builder by moving its internal data into
|
||||
* the returned ExtensionList. After calling this, the builder is left in a
|
||||
* valid but empty state.
|
||||
*
|
||||
* The && qualifier (rvalue reference qualifier) means this can only be
|
||||
* called on rvalue references, i.e. on:
|
||||
* - Temporaries: `ExtensionListBuilder().build()`
|
||||
* - Moved objects: `std::move(builder).build()`
|
||||
*
|
||||
* This prevents accidentally calling build() twice on the same builder,
|
||||
* which would be a bug.
|
||||
*/
|
||||
ExtensionList
|
||||
build() &&
|
||||
{
|
||||
return ExtensionList(std::move(strings));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<std::string> strings;
|
||||
};
|
||||
|
||||
} // namespace xrt::auxiliary::util
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "xrt/xrt_macro_lists.h"
|
||||
#include "util/u_misc.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
#include "util/u_pretty_print.h"
|
||||
|
||||
#include <assert.h>
|
||||
@@ -87,14 +87,14 @@ stack_only_sink(void *ptr, const char *str, size_t length)
|
||||
}
|
||||
|
||||
int
|
||||
update_longest_extension_name_length(struct u_string_list *list, int current_longest_extension)
|
||||
update_longest_extension_name_length(struct u_extension_list *list, int current_longest_extension)
|
||||
{
|
||||
if (list == NULL) {
|
||||
return current_longest_extension;
|
||||
}
|
||||
|
||||
size_t count = u_string_list_get_size(list);
|
||||
const char *const *data = u_string_list_get_data(list);
|
||||
size_t count = u_extension_list_get_size(list);
|
||||
const char *const *data = u_extension_list_get_data(list);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
int len = (int)strlen(data[i]);
|
||||
@@ -498,15 +498,15 @@ u_pp_array2d_f64(u_pp_delegate_t dg, const double *arr, size_t n, size_t m, cons
|
||||
|
||||
/*
|
||||
*
|
||||
* String list printers.
|
||||
* Extension list printers.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
u_pp_string_list(struct u_pp_delegate dg, struct u_string_list *usl, const char *prefix)
|
||||
u_pp_string_list(struct u_pp_delegate dg, struct u_extension_list *usl, const char *prefix)
|
||||
{
|
||||
uint32_t count = u_string_list_get_size(usl);
|
||||
const char *const *data = u_string_list_get_data(usl);
|
||||
uint32_t count = u_extension_list_get_size(usl);
|
||||
const char *const *data = u_extension_list_get_data(usl);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
u_pp(dg, "%s%s", prefix, data[i]);
|
||||
@@ -515,15 +515,15 @@ u_pp_string_list(struct u_pp_delegate dg, struct u_string_list *usl, const char
|
||||
|
||||
void
|
||||
u_pp_string_list_extensions(struct u_pp_delegate dg,
|
||||
struct u_string_list *enabled_list,
|
||||
struct u_string_list *optional_list,
|
||||
struct u_string_list *skipped_list)
|
||||
struct u_extension_list *enabled_list,
|
||||
struct u_extension_list *optional_list,
|
||||
struct u_extension_list *skipped_list)
|
||||
{
|
||||
assert(optional_list != NULL);
|
||||
assert(skipped_list != NULL);
|
||||
|
||||
uint32_t count = u_string_list_get_size(enabled_list);
|
||||
const char *const *data = u_string_list_get_data(enabled_list);
|
||||
uint32_t count = u_extension_list_get_size(enabled_list);
|
||||
const char *const *data = u_extension_list_get_data(enabled_list);
|
||||
|
||||
// Find the longest extension name for alignment
|
||||
int longest_extension = update_longest_extension_name_length(enabled_list, 0);
|
||||
@@ -536,7 +536,7 @@ u_pp_string_list_extensions(struct u_pp_delegate dg,
|
||||
uint32_t optional_enabled_count = 0;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
const char *ext = data[i];
|
||||
bool is_optional = u_string_list_contains(optional_list, ext);
|
||||
bool is_optional = u_extension_list_contains(optional_list, ext);
|
||||
if (is_optional) {
|
||||
optional_enabled_count++;
|
||||
}
|
||||
@@ -545,22 +545,22 @@ u_pp_string_list_extensions(struct u_pp_delegate dg,
|
||||
}
|
||||
|
||||
// All optional extensions have been enabled.
|
||||
uint32_t optional_count = u_string_list_get_size(optional_list);
|
||||
uint32_t optional_count = u_extension_list_get_size(optional_list);
|
||||
if (optional_enabled_count == optional_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print optional extensions that were not enabled
|
||||
u_pp(dg, "\n\tNot enabled optional extensions:");
|
||||
const char *const *optional_data = u_string_list_get_data(optional_list);
|
||||
const char *const *optional_data = u_extension_list_get_data(optional_list);
|
||||
for (uint32_t i = 0; i < optional_count; i++) {
|
||||
const char *ext = optional_data[i];
|
||||
if (u_string_list_contains(enabled_list, ext)) {
|
||||
if (u_extension_list_contains(enabled_list, ext)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this extension was skipped or unsupported
|
||||
bool was_skipped = u_string_list_contains(skipped_list, ext);
|
||||
bool was_skipped = u_extension_list_contains(skipped_list, ext);
|
||||
const char *reason = was_skipped ? "skipped" : "unsupported";
|
||||
|
||||
u_pp(dg, "\n\t\t%-*s %s", longest_extension, ext, reason);
|
||||
|
||||
@@ -238,11 +238,11 @@ u_pp_array2d_f64(u_pp_delegate_t dg, const double *arr, size_t n, size_t m, cons
|
||||
|
||||
/*
|
||||
*
|
||||
* String list printers.
|
||||
* Extension list printers.
|
||||
*
|
||||
*/
|
||||
|
||||
struct u_string_list;
|
||||
struct u_extension_list;
|
||||
|
||||
/*!
|
||||
* @brief Print all the strings in the list with the given prefix.
|
||||
@@ -253,10 +253,10 @@ struct u_string_list;
|
||||
* @ingroup aux_pretty
|
||||
*/
|
||||
XRT_NONNULL_ALL void
|
||||
u_pp_string_list(struct u_pp_delegate dg, struct u_string_list *usl, const char *prefix);
|
||||
u_pp_string_list(struct u_pp_delegate dg, struct u_extension_list *usl, const char *prefix);
|
||||
|
||||
/*!
|
||||
* @brief Pretty print the string list with extension information.
|
||||
* @brief Pretty print the extension list with extension information.
|
||||
*
|
||||
* It will start on a new line with the enabled extensions, showing which are
|
||||
* required vs optional. Then if there are optional extensions not enabled it
|
||||
@@ -270,9 +270,9 @@ u_pp_string_list(struct u_pp_delegate dg, struct u_string_list *usl, const char
|
||||
*/
|
||||
XRT_NONNULL_ALL void
|
||||
u_pp_string_list_extensions(struct u_pp_delegate dg,
|
||||
struct u_string_list *enabled_list,
|
||||
struct u_string_list *optional_list,
|
||||
struct u_string_list *skipped_list);
|
||||
struct u_extension_list *enabled_list,
|
||||
struct u_extension_list *optional_list,
|
||||
struct u_extension_list *skipped_list);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,311 +0,0 @@
|
||||
// Copyright 2021, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
|
||||
#include "u_string_list.h"
|
||||
#include "u_string_list.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Defines and structs.
|
||||
*
|
||||
*/
|
||||
|
||||
using xrt::auxiliary::util::StringList;
|
||||
|
||||
struct u_string_list
|
||||
{
|
||||
u_string_list() = default;
|
||||
u_string_list(StringList &&sl) : list(std::move(sl)) {}
|
||||
|
||||
StringList list;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Helpers
|
||||
*
|
||||
*/
|
||||
|
||||
enum class ExtensionType
|
||||
{
|
||||
KHR = 0, // Khronos extensions
|
||||
EXT = 1, // Multi-vendor extensions
|
||||
VENDOR = 2, // Vendor-specific extensions (AMD, NV, INTEL, etc.)
|
||||
EXPERIMENTAL = 3 // Experimental extensions
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Helper class for sorting extension names.
|
||||
*
|
||||
* Encapsulates the sort key with comparison operators for cleaner sorting.
|
||||
*/
|
||||
struct ExtensionSortKey
|
||||
{
|
||||
std::string api_prefix;
|
||||
ExtensionType type;
|
||||
std::string name;
|
||||
|
||||
/*!
|
||||
* Sorts in field declaration order:
|
||||
*
|
||||
* 1. API prefix (VK, XR, etc.)
|
||||
* 2. Extension type (KHR < EXT < VENDOR < EXPERIMENTAL)
|
||||
* 3. Alphabetically by full name
|
||||
*/
|
||||
auto
|
||||
operator<=>(const ExtensionSortKey &other) const = default;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Check if a vendor string represents an experimental extension.
|
||||
*
|
||||
* Experimental extensions have vendor codes ending with 'X' optionally followed
|
||||
* by digits.
|
||||
*
|
||||
* Examples: NVX, AMDX, NVX1, NVX2, INTELX
|
||||
*
|
||||
* Special case: QNX is a legitimate vendor (QNX operating system), not
|
||||
* experimental.
|
||||
*/
|
||||
static bool
|
||||
is_experimental_vendor(const std::string &vendor)
|
||||
{
|
||||
// Special case: QNX is a legitimate vendor, not experimental
|
||||
if (vendor == "QNX") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if vendor ends with 'X' optionally followed by digits
|
||||
if (vendor.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t len = vendor.length();
|
||||
size_t i = len - 1;
|
||||
|
||||
// Skip trailing digits
|
||||
while (i > 0 && std::isdigit(vendor[i])) {
|
||||
i--;
|
||||
}
|
||||
|
||||
// Check if we found an 'X' and there's something before it
|
||||
return (vendor[i] == 'X' && i > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the extension type and API prefix for sorting purposes.
|
||||
*
|
||||
* Returns an ExtensionSortKey for comparison.
|
||||
*/
|
||||
static ExtensionSortKey
|
||||
get_extension_sort_key(const char *ext)
|
||||
{
|
||||
std::string name(ext);
|
||||
|
||||
// Find the first underscore to separate API prefix (e.g., "VK", "XR")
|
||||
size_t first_underscore = name.find('_');
|
||||
if (first_underscore == std::string::npos) {
|
||||
// No underscore, treat as is
|
||||
return {name, ExtensionType::VENDOR, name};
|
||||
}
|
||||
|
||||
std::string api_prefix = name.substr(0, first_underscore);
|
||||
|
||||
// Find the second underscore to get the vendor/type part
|
||||
size_t second_underscore = name.find('_', first_underscore + 1);
|
||||
if (second_underscore == std::string::npos) {
|
||||
// Only one underscore, treat as vendor
|
||||
return {api_prefix, ExtensionType::VENDOR, name};
|
||||
}
|
||||
|
||||
std::string vendor = name.substr(first_underscore + 1, second_underscore - first_underscore - 1);
|
||||
|
||||
// Determine extension type based on vendor string
|
||||
ExtensionType type;
|
||||
if (vendor == "KHR") {
|
||||
type = ExtensionType::KHR;
|
||||
} else if (vendor == "EXT") {
|
||||
type = ExtensionType::EXT;
|
||||
} else if (is_experimental_vendor(vendor)) {
|
||||
type = ExtensionType::EXPERIMENTAL;
|
||||
} else {
|
||||
type = ExtensionType::VENDOR;
|
||||
}
|
||||
|
||||
return {api_prefix, type, name};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 'Exported' functions.
|
||||
*
|
||||
*/
|
||||
|
||||
struct u_string_list *
|
||||
u_string_list_create()
|
||||
{
|
||||
try {
|
||||
auto ret = std::make_unique<u_string_list>();
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_string_list *
|
||||
u_string_list_create_with_capacity(uint32_t capacity)
|
||||
{
|
||||
|
||||
try {
|
||||
auto ret = std::make_unique<u_string_list>(xrt::auxiliary::util::StringList{capacity});
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_string_list *
|
||||
u_string_list_create_from_list(struct u_string_list *usl)
|
||||
{
|
||||
try {
|
||||
auto ret = std::make_unique<u_string_list>(xrt::auxiliary::util::StringList{usl->list});
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
struct u_string_list *
|
||||
u_string_list_create_from_array(const char *const *arr, uint32_t size)
|
||||
{
|
||||
if (arr == nullptr || size == 0) {
|
||||
return u_string_list_create();
|
||||
}
|
||||
try {
|
||||
auto ret = std::make_unique<u_string_list>(xrt::auxiliary::util::StringList{size});
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
ret->list.push_back(arr[i]);
|
||||
}
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
u_string_list_get_size(const struct u_string_list *usl)
|
||||
{
|
||||
if (usl == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return usl->list.size();
|
||||
}
|
||||
|
||||
const char *const *
|
||||
u_string_list_get_data(const struct u_string_list *usl)
|
||||
{
|
||||
|
||||
if (usl == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return usl->list.data();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
u_string_list_append(struct u_string_list *usl, const char *str)
|
||||
{
|
||||
if (usl == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
usl->list.push_back(str);
|
||||
return 1;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_string_list_append_array(struct u_string_list *usl, const char *const *arr, uint32_t size)
|
||||
{
|
||||
|
||||
if (usl == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
usl->list.push_back(arr[i]);
|
||||
}
|
||||
return 1;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_string_list_append_unique(struct u_string_list *usl, const char *str)
|
||||
{
|
||||
if (usl == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
auto added = usl->list.push_back_unique(str);
|
||||
return added ? 1 : 0;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
u_string_list_contains(struct u_string_list *usl, const char *str)
|
||||
{
|
||||
return usl->list.contains(str);
|
||||
}
|
||||
|
||||
void
|
||||
u_string_list_sort_extensions(struct u_string_list *usl)
|
||||
{
|
||||
if (usl == nullptr || usl->list.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the data pointer and size from the StringList
|
||||
// We need to const_cast because std::sort needs non-const iterators
|
||||
auto data_ptr = const_cast<const char **>(usl->list.data());
|
||||
auto count = usl->list.size();
|
||||
auto cmp = [](const char *a, const char *b) { return get_extension_sort_key(a) < get_extension_sort_key(b); };
|
||||
|
||||
// Sort using our custom comparison function
|
||||
std::sort(data_ptr, data_ptr + count, cmp);
|
||||
}
|
||||
|
||||
void
|
||||
u_string_list_destroy(struct u_string_list **list_ptr)
|
||||
{
|
||||
if (list_ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
u_string_list *list = *list_ptr;
|
||||
if (list == nullptr) {
|
||||
return;
|
||||
}
|
||||
delete list;
|
||||
*list_ptr = nullptr;
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
// Copyright 2021, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "xrt/xrt_compiler.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
* @brief A collection of string literals (const char *), such as used for extension name lists.
|
||||
*
|
||||
* @see xrt::auxiliary::util::StringList
|
||||
*/
|
||||
struct u_string_list;
|
||||
|
||||
/*!
|
||||
* @brief Create a string list with room for at least the given number of strings.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
struct u_string_list *
|
||||
u_string_list_create(void);
|
||||
|
||||
/*!
|
||||
* @brief Create a string list with room for at least the given number of strings.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
struct u_string_list *
|
||||
u_string_list_create_with_capacity(uint32_t capacity);
|
||||
|
||||
/*!
|
||||
* @brief Create a new string list from an existing string list.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
struct u_string_list *
|
||||
u_string_list_create_from_list(struct u_string_list *usl);
|
||||
|
||||
/*!
|
||||
* @brief Create a new string list from an array of suitable strings.
|
||||
*
|
||||
* @param arr an array of zero or more non-null, null-terminated string that must live at least as long as the list,
|
||||
* preferably string literals.
|
||||
* @param size the number of elements in the array.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
struct u_string_list *
|
||||
u_string_list_create_from_array(const char *const *arr, uint32_t size);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the number of elements in the list
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
uint32_t
|
||||
u_string_list_get_size(const struct u_string_list *usl);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the data pointer of the list
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
const char *const *
|
||||
u_string_list_get_data(const struct u_string_list *usl);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string literal to the list.
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list, preferably a string
|
||||
* literal.
|
||||
* @return 1 if successfully added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
int
|
||||
u_string_list_append(struct u_string_list *usl, const char *str);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Append an array of new string literals to the list.
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param arr an array of zero or more non-null, null-terminated string that must live at least as long as the list,
|
||||
* preferably string literals.
|
||||
* @param size the number of elements in the array.
|
||||
* @return 1 if successfully added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
int
|
||||
u_string_list_append_array(struct u_string_list *usl, const char *const *arr, uint32_t size);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string literal to the list, if it's not the same as a string already in the list.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list, preferably a string
|
||||
* literal.
|
||||
* @return 1 if successfully added, 0 if already existing so not added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
int
|
||||
u_string_list_append_unique(struct u_string_list *usl, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Check if the string is in the list.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a non-null, null-terminated string.
|
||||
*
|
||||
* @return true if the string is in the list.
|
||||
*/
|
||||
bool
|
||||
u_string_list_contains(struct u_string_list *usl, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Sort the list of strings suitable for extension lists.
|
||||
*
|
||||
* The list will be sorted first by API (VK, XR, etc.), then all KHR extensions,
|
||||
* then all EXT extensions, then all Vendor extensions, then all experimental
|
||||
* extensions. (Alphabetical within each group.)
|
||||
*
|
||||
* @param usl self pointer
|
||||
*/
|
||||
void
|
||||
u_string_list_sort_extensions(struct u_string_list *usl);
|
||||
|
||||
/*!
|
||||
* @brief Destroy a string list.
|
||||
*
|
||||
* Performs null checks and sets your pointer to zero.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
void
|
||||
u_string_list_destroy(struct u_string_list **list_ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
// Copyright 2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Rylie Pavlik <rylie.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "u_string_list.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace xrt::auxiliary::util {
|
||||
|
||||
/*!
|
||||
* @brief A collection of strings (const char *), like a list of extensions to enable.
|
||||
*
|
||||
* This version is only for use with strings that will outlive this object, preferably string literals.
|
||||
*
|
||||
* Size is limited to one less than the max value of uint32_t which shouldn't be a problem,
|
||||
* the size really should be much smaller (especially if you use push_back_unique()).
|
||||
*/
|
||||
class StringList
|
||||
{
|
||||
public:
|
||||
/// Construct a string list.
|
||||
StringList() = default;
|
||||
/// Construct a string list with the given capacity.
|
||||
StringList(uint32_t capacity) : vec(capacity, nullptr)
|
||||
{
|
||||
// best way I know to create with capacity
|
||||
vec.clear();
|
||||
}
|
||||
StringList(StringList &&) = default;
|
||||
StringList(StringList const &) = default;
|
||||
|
||||
StringList &
|
||||
operator=(StringList &&) = default;
|
||||
StringList &
|
||||
operator=(StringList const &) = default;
|
||||
|
||||
/// Construct a string list with the given items
|
||||
template <uint32_t N> StringList(const char *(&arr)[N]) : StringList(N)
|
||||
{
|
||||
for (auto &&elt : arr) {
|
||||
push_back(elt);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the size of the array (the number of strings)
|
||||
*/
|
||||
uint32_t
|
||||
size() const noexcept
|
||||
{
|
||||
return static_cast<uint32_t>(vec.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the data pointer of the array
|
||||
*/
|
||||
const char *const *
|
||||
data() const noexcept
|
||||
{
|
||||
return vec.data();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the list.
|
||||
*
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list,
|
||||
* preferably a string literal.
|
||||
*
|
||||
* @throws std::out_of_range if you have a ridiculous number of strings in your list already,
|
||||
* std::invalid_argument if you pass a null pointer.
|
||||
*/
|
||||
void
|
||||
push_back(const char *str)
|
||||
{
|
||||
|
||||
if (vec.size() > (std::numeric_limits<uint32_t>::max)() - 1) {
|
||||
throw std::out_of_range("Size limit reached");
|
||||
}
|
||||
if (str == nullptr) {
|
||||
throw std::invalid_argument("Cannot pass a null pointer");
|
||||
}
|
||||
vec.push_back(str);
|
||||
}
|
||||
|
||||
/// Add all given items
|
||||
/// @throws the same as what push_back() throws
|
||||
template <uint32_t N>
|
||||
void
|
||||
push_back_all(const char *(&arr)[N])
|
||||
{
|
||||
for (auto &&elt : arr) {
|
||||
push_back(elt);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Check if the string is in the list.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* @param str a non-null, null-terminated string.
|
||||
*
|
||||
* @return true if the string is in the list.
|
||||
*/
|
||||
bool
|
||||
contains(const char *str)
|
||||
{
|
||||
if (str == nullptr) {
|
||||
throw std::invalid_argument("Cannot pass a null pointer");
|
||||
}
|
||||
std::string needle{str};
|
||||
auto it = std::find_if(vec.begin(), vec.end(), [needle](const char *elt) { return needle == elt; });
|
||||
return it != vec.end();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the list if it doesn't match any existing string.
|
||||
*
|
||||
* (Comparing string contents, not pointers)
|
||||
*
|
||||
* This does a simple linear search, because it is assumed that the size of this list is fairly small.
|
||||
*
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list,
|
||||
* preferably a string literal.
|
||||
*
|
||||
* @return true if we added it
|
||||
*
|
||||
* @throws std::out_of_range if you have a ridiculous number of strings in your list already,
|
||||
* std::invalid_argument if you pass a null pointer.
|
||||
*/
|
||||
bool
|
||||
push_back_unique(const char *str)
|
||||
{
|
||||
if (vec.size() > (std::numeric_limits<uint32_t>::max)() - 1) {
|
||||
throw std::out_of_range("Size limit reached");
|
||||
}
|
||||
if (str == nullptr) {
|
||||
throw std::invalid_argument("Cannot pass a null pointer");
|
||||
}
|
||||
std::string needle{str};
|
||||
auto it = std::find_if(vec.begin(), vec.end(), [needle](const char *elt) { return needle == elt; });
|
||||
if (it != vec.end()) {
|
||||
// already have it
|
||||
return false;
|
||||
}
|
||||
vec.push_back(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<const char *> vec;
|
||||
};
|
||||
|
||||
} // namespace xrt::auxiliary::util
|
||||
@@ -31,14 +31,14 @@
|
||||
|
||||
static bool
|
||||
should_skip_optional_instance_ext(struct vk_bundle *vk,
|
||||
struct u_string_list *required_instance_ext_list,
|
||||
struct u_string_list *optional_instance_ext_list,
|
||||
struct u_extension_list *required_instance_ext_list,
|
||||
struct u_extension_list *optional_instance_ext_list,
|
||||
const char *ext)
|
||||
{
|
||||
#ifdef VK_EXT_display_surface_counter
|
||||
if (strcmp(ext, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME) == 0) {
|
||||
// it does not make sense to enable surface counter on anything that does not use a VkDisplayKHR
|
||||
if (!u_string_list_contains(required_instance_ext_list, VK_KHR_DISPLAY_EXTENSION_NAME)) {
|
||||
if (!u_extension_list_contains(required_instance_ext_list, VK_KHR_DISPLAY_EXTENSION_NAME)) {
|
||||
VK_DEBUG(vk, "Skipping optional instance extension %s because %s is not enabled", ext,
|
||||
VK_KHR_DISPLAY_EXTENSION_NAME);
|
||||
return true;
|
||||
@@ -52,8 +52,8 @@ should_skip_optional_instance_ext(struct vk_bundle *vk,
|
||||
|
||||
static bool
|
||||
should_skip_optional_device_ext(struct vk_bundle *vk,
|
||||
struct u_string_list *required_device_ext_list,
|
||||
struct u_string_list *optional_device_ext_list,
|
||||
struct u_extension_list *required_device_ext_list,
|
||||
struct u_extension_list *optional_device_ext_list,
|
||||
const char *ext)
|
||||
{
|
||||
#ifdef VK_EXT_display_control
|
||||
@@ -80,9 +80,9 @@ should_skip_optional_device_ext(struct vk_bundle *vk,
|
||||
|
||||
VkResult
|
||||
vk_build_instance_extensions(struct vk_bundle *vk,
|
||||
struct u_string_list *required_instance_ext_list,
|
||||
struct u_string_list *optional_instance_ext_list,
|
||||
struct u_string_list **out_instance_ext_list)
|
||||
struct u_extension_list *required_instance_ext_list,
|
||||
struct u_extension_list *optional_instance_ext_list,
|
||||
struct u_extension_list **out_instance_ext_list)
|
||||
{
|
||||
return vk_build_instance_extensions_with_skip( //
|
||||
vk, //
|
||||
@@ -93,7 +93,7 @@ vk_build_instance_extensions(struct vk_bundle *vk,
|
||||
}
|
||||
|
||||
VkResult
|
||||
vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_string_list *required_instance_ext_list)
|
||||
vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_extension_list *required_instance_ext_list)
|
||||
{
|
||||
VkExtensionProperties *props = NULL;
|
||||
uint32_t prop_count = 0;
|
||||
@@ -109,8 +109,8 @@ vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_string_list
|
||||
return ret; // Already logged.
|
||||
}
|
||||
|
||||
// Convert to string list for easier checking.
|
||||
struct u_string_list *available_ext_list = vk_convert_extension_properties_to_string_list(props, prop_count);
|
||||
// Convert to extension list for easier checking.
|
||||
struct u_extension_list *available_ext_list = vk_convert_extension_properties_to_string_list(props, prop_count);
|
||||
|
||||
// Clean up props.
|
||||
free(props);
|
||||
@@ -119,13 +119,13 @@ vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_string_list
|
||||
ret = vk_check_required_extensions(vk, available_ext_list, required_instance_ext_list, "instance");
|
||||
|
||||
// Clean up.
|
||||
u_string_list_destroy(&available_ext_list);
|
||||
u_extension_list_destroy(&available_ext_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
vk_fill_in_has_instance_extensions(struct vk_bundle *vk, struct u_string_list *ext_list)
|
||||
vk_fill_in_has_instance_extensions(struct vk_bundle *vk, struct u_extension_list *ext_list)
|
||||
{
|
||||
// Include the generated extension detection code.
|
||||
#include "vk_bundle_init_instance_ext.c.inc"
|
||||
@@ -651,7 +651,7 @@ err_free:
|
||||
}
|
||||
|
||||
static void
|
||||
fill_in_has_device_extensions(struct vk_bundle *vk, struct u_string_list *ext_list)
|
||||
fill_in_has_device_extensions(struct vk_bundle *vk, struct u_extension_list *ext_list)
|
||||
{
|
||||
#include "vk_bundle_init_device_ext.c.inc"
|
||||
}
|
||||
@@ -931,11 +931,11 @@ vk_create_device(struct vk_bundle *vk,
|
||||
int forced_index,
|
||||
bool only_compute,
|
||||
VkQueueGlobalPriorityEXT global_priority,
|
||||
struct u_string_list *required_device_ext_list,
|
||||
struct u_string_list *optional_device_ext_list,
|
||||
struct u_extension_list *required_device_ext_list,
|
||||
struct u_extension_list *optional_device_ext_list,
|
||||
const struct vk_device_features *optional_device_features)
|
||||
{
|
||||
struct u_string_list *device_ext_list = NULL;
|
||||
struct u_extension_list *device_ext_list = NULL;
|
||||
VkResult ret;
|
||||
|
||||
ret = select_physical_device(vk, forced_index);
|
||||
@@ -1021,7 +1021,7 @@ vk_create_device(struct vk_bundle *vk,
|
||||
#ifdef VK_KHR_video_encode_queue
|
||||
// Video encode queue
|
||||
struct vk_queue_pair encode_queue = VK_NULL_QUEUE_PAIR;
|
||||
if (u_string_list_contains(device_ext_list, VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME)) {
|
||||
if (u_extension_list_contains(device_ext_list, VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME)) {
|
||||
struct vk_queue_family encode_queue_family = {0};
|
||||
ret = find_queue_family(vk, VK_QUEUE_VIDEO_ENCODE_BIT_KHR, &encode_queue_family);
|
||||
if (ret == VK_SUCCESS) {
|
||||
@@ -1131,8 +1131,8 @@ vk_create_device(struct vk_bundle *vk,
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.queueCreateInfoCount = queue_create_info_count,
|
||||
.pQueueCreateInfos = queue_create_info,
|
||||
.enabledExtensionCount = u_string_list_get_size(device_ext_list),
|
||||
.ppEnabledExtensionNames = u_string_list_get_data(device_ext_list),
|
||||
.enabledExtensionCount = u_extension_list_get_size(device_ext_list),
|
||||
.ppEnabledExtensionNames = u_extension_list_get_data(device_ext_list),
|
||||
.pEnabledFeatures = &enabled_features,
|
||||
};
|
||||
|
||||
@@ -1191,7 +1191,7 @@ vk_create_device(struct vk_bundle *vk,
|
||||
ret = vk->vkCreateDevice(vk->physical_device, &device_create_info, NULL, &vk->device);
|
||||
|
||||
// Destroy the list now.
|
||||
u_string_list_destroy(&device_ext_list);
|
||||
u_extension_list_destroy(&device_ext_list);
|
||||
|
||||
if (ret == VK_ERROR_NOT_PERMITTED_EXT) {
|
||||
// Don't spam the not permitted returns as we try all of the different priorities.
|
||||
@@ -1230,7 +1230,7 @@ err_destroy:
|
||||
}
|
||||
|
||||
// Safe to call even if null.
|
||||
u_string_list_destroy(&device_ext_list);
|
||||
u_extension_list_destroy(&device_ext_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static struct u_string_list *
|
||||
static struct u_extension_list *
|
||||
build_extension_list(struct vk_bundle *vk,
|
||||
struct u_string_list *available_ext_list,
|
||||
struct u_string_list *required_ext_list,
|
||||
struct u_string_list *optional_ext_list,
|
||||
struct u_extension_list *available_ext_list,
|
||||
struct u_extension_list *required_ext_list,
|
||||
struct u_extension_list *optional_ext_list,
|
||||
vk_should_skip_ext_func_t skip_func,
|
||||
struct u_string_list **out_skipped_ext_list)
|
||||
struct u_extension_list **out_skipped_ext_list)
|
||||
{
|
||||
assert(available_ext_list != NULL);
|
||||
assert(required_ext_list != NULL);
|
||||
@@ -34,14 +34,18 @@ build_extension_list(struct vk_bundle *vk,
|
||||
assert(out_skipped_ext_list != NULL);
|
||||
|
||||
// Start with required extensions (assumed to be supported).
|
||||
struct u_string_list *list = u_string_list_create_from_list(required_ext_list);
|
||||
uint32_t required_ext_count = u_extension_list_get_size(required_ext_list);
|
||||
struct u_extension_list_builder *builder =
|
||||
u_extension_list_builder_create_with_capacity(required_ext_count + 16);
|
||||
u_extension_list_builder_append_array(builder, u_extension_list_get_data(required_ext_list),
|
||||
required_ext_count);
|
||||
|
||||
// Create skipped list.
|
||||
struct u_string_list *skipped_list = u_string_list_create();
|
||||
// Create skipped list builder.
|
||||
struct u_extension_list_builder *skipped_builder = u_extension_list_builder_create();
|
||||
|
||||
// Check any supported optional extensions.
|
||||
uint32_t optional_ext_count = u_string_list_get_size(optional_ext_list);
|
||||
const char *const *optional_exts = u_string_list_get_data(optional_ext_list);
|
||||
uint32_t optional_ext_count = u_extension_list_get_size(optional_ext_list);
|
||||
const char *const *optional_exts = u_extension_list_get_data(optional_ext_list);
|
||||
|
||||
for (uint32_t i = 0; i < optional_ext_count; i++) {
|
||||
const char *optional_ext = optional_exts[i];
|
||||
@@ -50,25 +54,26 @@ build_extension_list(struct vk_bundle *vk,
|
||||
bool skip = skip_func(vk, required_ext_list, optional_ext_list, optional_ext);
|
||||
if (skip) {
|
||||
// Track skipped extensions.
|
||||
u_string_list_append_unique(skipped_list, optional_ext);
|
||||
u_extension_list_builder_append_unique(skipped_builder, optional_ext);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the extension is available.
|
||||
if (!u_string_list_contains(available_ext_list, optional_ext)) {
|
||||
if (!u_extension_list_contains(available_ext_list, optional_ext)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int added = u_string_list_append_unique(list, optional_ext);
|
||||
int added = u_extension_list_builder_append_unique(builder, optional_ext);
|
||||
if (added != 1) {
|
||||
VK_WARN(vk, "Duplicate extension %s not added twice", optional_ext);
|
||||
}
|
||||
}
|
||||
|
||||
// Return skipped list.
|
||||
*out_skipped_ext_list = skipped_list;
|
||||
// Build and return skipped list (sorted for consistent output).
|
||||
*out_skipped_ext_list = u_extension_list_builder_build_sorted_for_extensions(&skipped_builder);
|
||||
|
||||
return list;
|
||||
// Build and return the extension list (sorted for consistent output).
|
||||
return u_extension_list_builder_build_sorted_for_extensions(&builder);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,28 +83,27 @@ build_extension_list(struct vk_bundle *vk,
|
||||
*
|
||||
*/
|
||||
|
||||
struct u_string_list *
|
||||
struct u_extension_list *
|
||||
vk_convert_extension_properties_to_string_list(VkExtensionProperties *props, uint32_t prop_count)
|
||||
{
|
||||
struct u_string_list *list = u_string_list_create();
|
||||
struct u_extension_list_builder *builder = u_extension_list_builder_create_with_capacity(prop_count);
|
||||
for (uint32_t i = 0; i < prop_count; i++) {
|
||||
u_string_list_append_unique(list, props[i].extensionName);
|
||||
u_extension_list_builder_append_unique(builder, props[i].extensionName);
|
||||
}
|
||||
return list;
|
||||
return u_extension_list_builder_build_sorted_for_extensions(&builder);
|
||||
}
|
||||
|
||||
void
|
||||
vk_log_extension_list(struct vk_bundle *vk,
|
||||
struct u_string_list *ext_list,
|
||||
struct u_string_list *optional_ext_list,
|
||||
struct u_string_list *skipped_ext_list,
|
||||
struct u_extension_list *ext_list,
|
||||
struct u_extension_list *optional_ext_list,
|
||||
struct u_extension_list *skipped_ext_list,
|
||||
const char *ext_type_name,
|
||||
enum u_logging_level log_level)
|
||||
{
|
||||
struct u_pp_sink_stack_only sink;
|
||||
u_pp_delegate_t dg = u_pp_sink_stack_only_init(&sink);
|
||||
|
||||
u_string_list_sort_extensions(ext_list);
|
||||
u_pp_string_list_extensions(dg, ext_list, optional_ext_list, skipped_ext_list);
|
||||
|
||||
U_LOG_IFL(log_level, vk->log_level, "Vulkan %s extensions list(s):%s", ext_type_name, sink.buffer);
|
||||
@@ -107,8 +111,8 @@ vk_log_extension_list(struct vk_bundle *vk,
|
||||
|
||||
VkResult
|
||||
vk_check_required_extensions(struct vk_bundle *vk,
|
||||
struct u_string_list *available_ext_list,
|
||||
struct u_string_list *required_ext_list,
|
||||
struct u_extension_list *available_ext_list,
|
||||
struct u_extension_list *required_ext_list,
|
||||
const char *ext_type_name)
|
||||
{
|
||||
struct u_pp_sink_stack_only sink;
|
||||
@@ -118,12 +122,12 @@ vk_check_required_extensions(struct vk_bundle *vk,
|
||||
u_pp_delegate_t dg = u_pp_sink_stack_only_init(&sink);
|
||||
|
||||
// Check if required extensions are supported.
|
||||
uint32_t required_ext_count = u_string_list_get_size(required_ext_list);
|
||||
const char *const *required_exts = u_string_list_get_data(required_ext_list);
|
||||
uint32_t required_ext_count = u_extension_list_get_size(required_ext_list);
|
||||
const char *const *required_exts = u_extension_list_get_data(required_ext_list);
|
||||
for (uint32_t i = 0; i < required_ext_count; i++) {
|
||||
const char *required_ext = required_exts[i];
|
||||
|
||||
if (u_string_list_contains(available_ext_list, required_ext)) {
|
||||
if (u_extension_list_contains(available_ext_list, required_ext)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -148,10 +152,10 @@ vk_check_required_extensions(struct vk_bundle *vk,
|
||||
|
||||
VkResult
|
||||
vk_build_instance_extensions_with_skip(struct vk_bundle *vk,
|
||||
struct u_string_list *required_instance_ext_list,
|
||||
struct u_string_list *optional_instance_ext_list,
|
||||
struct u_extension_list *required_instance_ext_list,
|
||||
struct u_extension_list *optional_instance_ext_list,
|
||||
vk_should_skip_ext_func_t skip_func,
|
||||
struct u_string_list **out_instance_ext_list)
|
||||
struct u_extension_list **out_instance_ext_list)
|
||||
{
|
||||
VkExtensionProperties *props = NULL;
|
||||
uint32_t prop_count = 0;
|
||||
@@ -165,8 +169,8 @@ vk_build_instance_extensions_with_skip(struct vk_bundle *vk,
|
||||
&props); // out_props
|
||||
VK_CHK_AND_RET(ret, "vk_enumerate_instance_extensions_properties");
|
||||
|
||||
// Convert to string list for easier checking.
|
||||
struct u_string_list *available_ext_list = vk_convert_extension_properties_to_string_list(props, prop_count);
|
||||
// Convert to extension list for easier checking.
|
||||
struct u_extension_list *available_ext_list = vk_convert_extension_properties_to_string_list(props, prop_count);
|
||||
|
||||
// Clean up props.
|
||||
free(props);
|
||||
@@ -174,28 +178,28 @@ vk_build_instance_extensions_with_skip(struct vk_bundle *vk,
|
||||
// Check if all required extensions are available.
|
||||
ret = vk_check_required_extensions(vk, available_ext_list, required_instance_ext_list, "instance");
|
||||
if (ret != VK_SUCCESS) {
|
||||
u_string_list_destroy(&available_ext_list);
|
||||
u_extension_list_destroy(&available_ext_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Build the extension list and track skipped extensions.
|
||||
struct u_string_list *skipped_list = NULL;
|
||||
struct u_string_list *list = build_extension_list( //
|
||||
vk, //
|
||||
available_ext_list, //
|
||||
required_instance_ext_list, //
|
||||
optional_instance_ext_list, //
|
||||
skip_func, //
|
||||
&skipped_list); //
|
||||
struct u_extension_list *skipped_list = NULL;
|
||||
struct u_extension_list *list = build_extension_list( //
|
||||
vk, //
|
||||
available_ext_list, //
|
||||
required_instance_ext_list, //
|
||||
optional_instance_ext_list, //
|
||||
skip_func, //
|
||||
&skipped_list); //
|
||||
|
||||
// Clean up available list.
|
||||
u_string_list_destroy(&available_ext_list);
|
||||
u_extension_list_destroy(&available_ext_list);
|
||||
|
||||
// Log the result.
|
||||
vk_log_extension_list(vk, list, optional_instance_ext_list, skipped_list, "instance", U_LOGGING_INFO);
|
||||
|
||||
// Clean up skipped list.
|
||||
u_string_list_destroy(&skipped_list);
|
||||
u_extension_list_destroy(&skipped_list);
|
||||
|
||||
// Return the list.
|
||||
*out_instance_ext_list = list;
|
||||
@@ -213,10 +217,10 @@ vk_build_instance_extensions_with_skip(struct vk_bundle *vk,
|
||||
VkResult
|
||||
vk_build_device_extensions_with_skip(struct vk_bundle *vk,
|
||||
VkPhysicalDevice physical_device,
|
||||
struct u_string_list *required_device_ext_list,
|
||||
struct u_string_list *optional_device_ext_list,
|
||||
struct u_extension_list *required_device_ext_list,
|
||||
struct u_extension_list *optional_device_ext_list,
|
||||
vk_should_skip_ext_func_t skip_func,
|
||||
struct u_string_list **out_device_ext_list)
|
||||
struct u_extension_list **out_device_ext_list)
|
||||
{
|
||||
VkExtensionProperties *props = NULL;
|
||||
uint32_t prop_count = 0;
|
||||
@@ -230,8 +234,8 @@ vk_build_device_extensions_with_skip(struct vk_bundle *vk,
|
||||
&props); // out_props
|
||||
VK_CHK_AND_RET(ret, "vk_enumerate_physical_device_extension_properties");
|
||||
|
||||
// Convert to string list for easier checking.
|
||||
struct u_string_list *available_ext_list = vk_convert_extension_properties_to_string_list(props, prop_count);
|
||||
// Convert to extension list for easier checking.
|
||||
struct u_extension_list *available_ext_list = vk_convert_extension_properties_to_string_list(props, prop_count);
|
||||
|
||||
// Clean up props.
|
||||
free(props);
|
||||
@@ -239,28 +243,28 @@ vk_build_device_extensions_with_skip(struct vk_bundle *vk,
|
||||
// Check if all required extensions are available.
|
||||
ret = vk_check_required_extensions(vk, available_ext_list, required_device_ext_list, "device");
|
||||
if (ret != VK_SUCCESS) {
|
||||
u_string_list_destroy(&available_ext_list);
|
||||
u_extension_list_destroy(&available_ext_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Build the extension list and track skipped extensions.
|
||||
struct u_string_list *skipped_list = NULL;
|
||||
struct u_string_list *list = build_extension_list( //
|
||||
vk, //
|
||||
available_ext_list, //
|
||||
required_device_ext_list, //
|
||||
optional_device_ext_list, //
|
||||
skip_func, //
|
||||
&skipped_list); //
|
||||
struct u_extension_list *skipped_list = NULL;
|
||||
struct u_extension_list *list = build_extension_list( //
|
||||
vk, //
|
||||
available_ext_list, //
|
||||
required_device_ext_list, //
|
||||
optional_device_ext_list, //
|
||||
skip_func, //
|
||||
&skipped_list); //
|
||||
|
||||
// Clean up available list.
|
||||
u_string_list_destroy(&available_ext_list);
|
||||
u_extension_list_destroy(&available_ext_list);
|
||||
|
||||
// Log the result.
|
||||
vk_log_extension_list(vk, list, optional_device_ext_list, skipped_list, "device", U_LOGGING_DEBUG);
|
||||
|
||||
// Clean up skipped list.
|
||||
u_string_list_destroy(&skipped_list);
|
||||
u_extension_list_destroy(&skipped_list);
|
||||
|
||||
// Return the list.
|
||||
*out_device_ext_list = list;
|
||||
|
||||
@@ -22,15 +22,15 @@ extern "C" {
|
||||
* Callback type for checking if an optional extension should be skipped.
|
||||
*/
|
||||
typedef bool (*vk_should_skip_ext_func_t)(struct vk_bundle *vk,
|
||||
struct u_string_list *required_ext_list,
|
||||
struct u_string_list *optional_ext_list,
|
||||
struct u_extension_list *required_ext_list,
|
||||
struct u_extension_list *optional_ext_list,
|
||||
const char *ext);
|
||||
|
||||
|
||||
/*!
|
||||
* Convert VkExtensionProperties array to u_string_list.
|
||||
* Convert VkExtensionProperties array to u_extension_list.
|
||||
*/
|
||||
struct u_string_list *
|
||||
struct u_extension_list *
|
||||
vk_convert_extension_properties_to_string_list(VkExtensionProperties *props, uint32_t prop_count);
|
||||
|
||||
/*!
|
||||
@@ -41,9 +41,9 @@ vk_convert_extension_properties_to_string_list(VkExtensionProperties *props, uin
|
||||
*/
|
||||
void
|
||||
vk_log_extension_list(struct vk_bundle *vk,
|
||||
struct u_string_list *ext_list,
|
||||
struct u_string_list *optional_ext_list,
|
||||
struct u_string_list *skipped_ext_list,
|
||||
struct u_extension_list *ext_list,
|
||||
struct u_extension_list *optional_ext_list,
|
||||
struct u_extension_list *skipped_ext_list,
|
||||
const char *ext_type_name,
|
||||
enum u_logging_level log_level);
|
||||
|
||||
@@ -55,8 +55,8 @@ vk_log_extension_list(struct vk_bundle *vk,
|
||||
*/
|
||||
VkResult
|
||||
vk_check_required_extensions(struct vk_bundle *vk,
|
||||
struct u_string_list *available_ext_list,
|
||||
struct u_string_list *required_ext_list,
|
||||
struct u_extension_list *available_ext_list,
|
||||
struct u_extension_list *required_ext_list,
|
||||
const char *ext_type_name);
|
||||
|
||||
/*!
|
||||
@@ -74,10 +74,10 @@ vk_check_required_extensions(struct vk_bundle *vk,
|
||||
*/
|
||||
VkResult
|
||||
vk_build_instance_extensions_with_skip(struct vk_bundle *vk,
|
||||
struct u_string_list *required_instance_ext_list,
|
||||
struct u_string_list *optional_instance_ext_list,
|
||||
struct u_extension_list *required_instance_ext_list,
|
||||
struct u_extension_list *optional_instance_ext_list,
|
||||
vk_should_skip_ext_func_t skip_func,
|
||||
struct u_string_list **out_instance_ext_list);
|
||||
struct u_extension_list **out_instance_ext_list);
|
||||
|
||||
/*!
|
||||
* Build device extensions from required and optional device extensions with
|
||||
@@ -92,10 +92,10 @@ vk_build_instance_extensions_with_skip(struct vk_bundle *vk,
|
||||
VkResult
|
||||
vk_build_device_extensions_with_skip(struct vk_bundle *vk,
|
||||
VkPhysicalDevice physical_device,
|
||||
struct u_string_list *required_device_ext_list,
|
||||
struct u_string_list *optional_device_ext_list,
|
||||
struct u_extension_list *required_device_ext_list,
|
||||
struct u_extension_list *optional_device_ext_list,
|
||||
vk_should_skip_ext_func_t skip_func,
|
||||
struct u_string_list **out_device_ext_list);
|
||||
struct u_extension_list **out_device_ext_list);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -465,7 +465,7 @@ def generate_ext_check(exts):
|
||||
condition_line = conditional.process_condition(compute_condition((ext,)))
|
||||
if condition_line:
|
||||
yield condition_line
|
||||
yield "\tvk->{} = u_string_list_contains(ext_list, {});".format(
|
||||
yield "\tvk->{} = u_extension_list_contains(ext_list, {});".format(
|
||||
make_ext_member_name(ext), make_ext_name_define(ext))
|
||||
# close any trailing conditions
|
||||
condition_line = conditional.finish()
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "xrt/xrt_vulkan_includes.h"
|
||||
#include "xrt/xrt_handles.h"
|
||||
#include "util/u_logging.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
#include "os/os_threading.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -781,7 +781,7 @@ vk_get_device_functions(struct vk_bundle *vk);
|
||||
* @ingroup aux_vk
|
||||
*/
|
||||
VkResult
|
||||
vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_string_list *required_instance_ext_list);
|
||||
vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_extension_list *required_instance_ext_list);
|
||||
|
||||
/*!
|
||||
* Build instance extensions from required and optional instance extensions.
|
||||
@@ -793,15 +793,15 @@ vk_check_required_instance_extensions(struct vk_bundle *vk, struct u_string_list
|
||||
*/
|
||||
VkResult
|
||||
vk_build_instance_extensions(struct vk_bundle *vk,
|
||||
struct u_string_list *required_instance_ext_list,
|
||||
struct u_string_list *optional_instance_ext_list,
|
||||
struct u_string_list **out_instance_ext_list);
|
||||
struct u_extension_list *required_instance_ext_list,
|
||||
struct u_extension_list *optional_instance_ext_list,
|
||||
struct u_extension_list **out_instance_ext_list);
|
||||
|
||||
/*!
|
||||
* Fills in has_* in vk_bundle given a string of prefiltered instance extensions
|
||||
*/
|
||||
void
|
||||
vk_fill_in_has_instance_extensions(struct vk_bundle *vk, struct u_string_list *ext_list);
|
||||
vk_fill_in_has_instance_extensions(struct vk_bundle *vk, struct u_extension_list *ext_list);
|
||||
|
||||
/*!
|
||||
* Setup the physical device, this is called by vk_create_device but has uses
|
||||
@@ -843,8 +843,8 @@ vk_create_device(struct vk_bundle *vk,
|
||||
int forced_index,
|
||||
bool only_compute,
|
||||
VkQueueGlobalPriorityEXT global_priority,
|
||||
struct u_string_list *required_device_ext_list,
|
||||
struct u_string_list *optional_device_ext_list,
|
||||
struct u_extension_list *required_device_ext_list,
|
||||
struct u_extension_list *optional_device_ext_list,
|
||||
const struct vk_device_features *optional_device_features);
|
||||
|
||||
/*!
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2022, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -19,7 +20,7 @@
|
||||
#include "xrt/xrt_vulkan_includes.h"
|
||||
|
||||
#include "util/u_logging.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
|
||||
#include "vk/vk_helpers.h"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2019-2024, Collabora, Ltd.
|
||||
// Copyright 2025, NVIDIA CORPORATION.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -613,10 +613,12 @@ static const char *optional_device_extensions[] = {
|
||||
};
|
||||
|
||||
static bool
|
||||
select_instances_extensions(struct comp_compositor *c, struct u_string_list *required, struct u_string_list *optional)
|
||||
select_instances_extensions(struct comp_compositor *c,
|
||||
struct u_extension_list_builder *required_builder,
|
||||
struct u_extension_list_builder *optional_builder)
|
||||
{
|
||||
#ifdef XRT_FEATURE_WINDOW_PEEK
|
||||
if (!comp_window_peek_get_vk_instance_exts(required)) {
|
||||
if (!comp_window_peek_get_vk_instance_exts(required_builder)) {
|
||||
COMP_ERROR(c, "Failed to get required vulkan instance extensions for peek window.");
|
||||
return false;
|
||||
}
|
||||
@@ -638,62 +640,76 @@ compositor_init_vulkan(struct comp_compositor *c)
|
||||
* Instance extensions.
|
||||
*/
|
||||
|
||||
struct u_string_list *required_instance_ext_list = u_string_list_create();
|
||||
struct u_string_list *optional_instance_ext_list = u_string_list_create();
|
||||
struct u_extension_list_builder *required_instance_ext_builder = u_extension_list_builder_create();
|
||||
struct u_extension_list_builder *optional_instance_ext_builder = u_extension_list_builder_create();
|
||||
|
||||
// Every backend needs at least the common extensions.
|
||||
u_string_list_append_array( //
|
||||
required_instance_ext_list, //
|
||||
u_extension_list_builder_append_array( //
|
||||
required_instance_ext_builder, //
|
||||
instance_extensions_common, //
|
||||
ARRAY_SIZE(instance_extensions_common)); //
|
||||
|
||||
// Add per target required extensions.
|
||||
u_string_list_append_array( //
|
||||
required_instance_ext_list, //
|
||||
u_extension_list_builder_append_array( //
|
||||
required_instance_ext_builder, //
|
||||
c->target_factory->required_instance_extensions, //
|
||||
c->target_factory->required_instance_extension_count); //
|
||||
|
||||
// Optional instance extensions.
|
||||
u_string_list_append_array( //
|
||||
optional_instance_ext_list, //
|
||||
u_extension_list_builder_append_array( //
|
||||
optional_instance_ext_builder, //
|
||||
optional_instance_extensions, //
|
||||
ARRAY_SIZE(optional_instance_extensions)); //
|
||||
|
||||
if (!select_instances_extensions(c, required_instance_ext_list, optional_instance_ext_list)) {
|
||||
if (!select_instances_extensions(c, required_instance_ext_builder, optional_instance_ext_builder)) {
|
||||
COMP_ERROR(c, "Failed to select additional instance extensions.");
|
||||
u_string_list_destroy(&required_instance_ext_list);
|
||||
u_string_list_destroy(&optional_instance_ext_list);
|
||||
u_extension_list_builder_destroy(&required_instance_ext_builder);
|
||||
u_extension_list_builder_destroy(&optional_instance_ext_builder);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Consumes the builder and returns a new list.
|
||||
struct u_extension_list *required_instance_ext_list =
|
||||
u_extension_list_builder_build(&required_instance_ext_builder);
|
||||
struct u_extension_list *optional_instance_ext_list =
|
||||
u_extension_list_builder_build(&optional_instance_ext_builder);
|
||||
|
||||
|
||||
/*
|
||||
* Device extensions.
|
||||
*/
|
||||
|
||||
struct u_string_list *required_device_extension_list = u_string_list_create();
|
||||
struct u_string_list *optional_device_extension_list = u_string_list_create();
|
||||
struct u_extension_list_builder *required_device_ext_builder = u_extension_list_builder_create();
|
||||
struct u_extension_list_builder *optional_device_ext_builder = u_extension_list_builder_create();
|
||||
|
||||
// Required device extensions.
|
||||
u_string_list_append_array( //
|
||||
required_device_extension_list, //
|
||||
u_extension_list_builder_append_array( //
|
||||
required_device_ext_builder, //
|
||||
required_device_extensions, //
|
||||
ARRAY_SIZE(required_device_extensions)); //
|
||||
|
||||
// Optional device extensions.
|
||||
u_string_list_append_array( //
|
||||
optional_device_extension_list, //
|
||||
u_extension_list_builder_append_array( //
|
||||
optional_device_ext_builder, //
|
||||
optional_device_extensions, //
|
||||
ARRAY_SIZE(optional_device_extensions)); //
|
||||
|
||||
// Add per target optional device extensions.
|
||||
u_string_list_append_array( //
|
||||
optional_device_extension_list, //
|
||||
u_extension_list_builder_append_array( //
|
||||
optional_device_ext_builder, //
|
||||
c->target_factory->optional_device_extensions, //
|
||||
c->target_factory->optional_device_extension_count); //
|
||||
|
||||
// Consumes the builder and returns a new list.
|
||||
struct u_extension_list *required_device_ext_list =
|
||||
u_extension_list_builder_build(&required_device_ext_builder);
|
||||
struct u_extension_list *optional_device_ext_list =
|
||||
u_extension_list_builder_build(&optional_device_ext_builder);
|
||||
|
||||
// Select required Vulkan version, suitable for both compositor and target
|
||||
uint32_t required_instance_version = MAX(c->target_factory->required_instance_version, VK_API_VERSION_1_0);
|
||||
|
||||
|
||||
/*
|
||||
* Create the device.
|
||||
*/
|
||||
@@ -703,8 +719,8 @@ compositor_init_vulkan(struct comp_compositor *c)
|
||||
.required_instance_version = required_instance_version,
|
||||
.required_instance_extensions = required_instance_ext_list,
|
||||
.optional_instance_extensions = optional_instance_ext_list,
|
||||
.required_device_extensions = required_device_extension_list,
|
||||
.optional_device_extensions = optional_device_extension_list,
|
||||
.required_device_extensions = required_device_ext_list,
|
||||
.optional_device_extensions = optional_device_ext_list,
|
||||
.log_level = c->settings.log_level,
|
||||
.only_compute_queue = c->settings.use_compute,
|
||||
.selected_gpu_index = c->settings.selected_gpu_index,
|
||||
@@ -715,10 +731,10 @@ compositor_init_vulkan(struct comp_compositor *c)
|
||||
struct comp_vulkan_results vk_res = {0};
|
||||
bool bundle_ret = comp_vulkan_init_bundle(vk, &vk_args, &vk_res);
|
||||
|
||||
u_string_list_destroy(&required_instance_ext_list);
|
||||
u_string_list_destroy(&optional_instance_ext_list);
|
||||
u_string_list_destroy(&required_device_extension_list);
|
||||
u_string_list_destroy(&optional_device_extension_list);
|
||||
u_extension_list_destroy(&required_instance_ext_list);
|
||||
u_extension_list_destroy(&optional_instance_ext_list);
|
||||
u_extension_list_destroy(&required_device_ext_list);
|
||||
u_extension_list_destroy(&optional_device_ext_list);
|
||||
|
||||
if (!bundle_ret) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright 2022, Simon Zeni <simon@bl4ckb0ne.ca>
|
||||
// Copyright 2022-2023, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -13,7 +14,7 @@
|
||||
#include "main/comp_window_peek.h"
|
||||
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
|
||||
#ifdef XRT_HAVE_SDL2
|
||||
#include <SDL2/SDL.h>
|
||||
@@ -473,10 +474,10 @@ comp_window_peek_get_eye(struct comp_window_peek *w)
|
||||
}
|
||||
|
||||
bool
|
||||
comp_window_peek_get_vk_instance_exts(struct u_string_list *out_required_list)
|
||||
comp_window_peek_get_vk_instance_exts(struct u_extension_list_builder *out_required_builder)
|
||||
{
|
||||
if (out_required_list == NULL) {
|
||||
U_LOG_E("comp_window_peek: out_required_list is null.");
|
||||
if (out_required_builder == NULL) {
|
||||
U_LOG_E("comp_window_peek: out_required_builder is null.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -532,7 +533,7 @@ comp_window_peek_get_vk_instance_exts(struct u_string_list *out_required_list)
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
if (u_string_list_append_unique(out_required_list, instance_ext_names[i]) == 0) {
|
||||
if (u_extension_list_builder_append_unique(out_required_builder, instance_ext_names[i]) == 0) {
|
||||
U_LOG_T("comp_window_peek: required instance extension: %s already exits, ignored.",
|
||||
instance_ext_names[i]);
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2022, Simon Zeni <simon@bl4ckb0ne.ca>
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -56,12 +57,12 @@ comp_window_peek_get_eye(struct comp_window_peek *w);
|
||||
/*!
|
||||
* Gets the required vulkan instance extensions for comp_window_peek support
|
||||
*
|
||||
* @param[inout] out_required_list list of string containing the required instance extensions to enable,
|
||||
* the list may already contain some/all of the required, duplicates will
|
||||
* not be added.
|
||||
* @param[inout] out_required_builder builder for the list of required instance extensions to enable,
|
||||
* the builder may already contain some/all of the required, duplicates will
|
||||
* not be added.
|
||||
*/
|
||||
bool
|
||||
comp_window_peek_get_vk_instance_exts(struct u_string_list *out_required_list);
|
||||
comp_window_peek_get_vk_instance_exts(struct u_extension_list_builder *out_required_builder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2019-2024, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -146,10 +147,12 @@ static const char *optional_device_extensions[] = {
|
||||
};
|
||||
|
||||
static VkResult
|
||||
select_instances_extensions(struct null_compositor *c, struct u_string_list *required, struct u_string_list *optional)
|
||||
select_instances_extensions(struct null_compositor *c,
|
||||
struct u_extension_list_builder *required_builder,
|
||||
struct u_extension_list_builder *optional_builder)
|
||||
{
|
||||
#ifdef VK_EXT_display_surface_counter
|
||||
u_string_list_append(optional, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME);
|
||||
u_extension_list_builder_append(optional_builder, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME);
|
||||
#endif
|
||||
|
||||
return VK_SUCCESS;
|
||||
@@ -162,25 +165,32 @@ compositor_init_vulkan(struct null_compositor *c)
|
||||
VkResult ret;
|
||||
|
||||
// every backend needs at least the common extensions
|
||||
struct u_string_list *required_instance_ext_list =
|
||||
u_string_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common));
|
||||
struct u_extension_list_builder *required_instance_ext_builder = u_extension_list_builder_create_from_array( //
|
||||
instance_extensions_common, //
|
||||
ARRAY_SIZE(instance_extensions_common)); //
|
||||
|
||||
struct u_string_list *optional_instance_ext_list = u_string_list_create();
|
||||
struct u_extension_list_builder *optional_instance_ext_builder = u_extension_list_builder_create();
|
||||
|
||||
ret = select_instances_extensions(c, required_instance_ext_list, optional_instance_ext_list);
|
||||
ret = select_instances_extensions(c, required_instance_ext_builder, optional_instance_ext_builder);
|
||||
if (ret != VK_SUCCESS) {
|
||||
VK_ERROR(vk, "select_instances_extensions: %s\n\tFailed to select instance extensions.",
|
||||
vk_result_string(ret));
|
||||
u_string_list_destroy(&required_instance_ext_list);
|
||||
u_string_list_destroy(&optional_instance_ext_list);
|
||||
u_extension_list_builder_destroy(&required_instance_ext_builder);
|
||||
u_extension_list_builder_destroy(&optional_instance_ext_builder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct u_string_list *required_device_extension_list =
|
||||
u_string_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions));
|
||||
// Consumes the builder and returns a new list.
|
||||
struct u_extension_list *required_instance_ext_list =
|
||||
u_extension_list_builder_build(&required_instance_ext_builder);
|
||||
struct u_extension_list *optional_instance_ext_list =
|
||||
u_extension_list_builder_build(&optional_instance_ext_builder);
|
||||
|
||||
struct u_string_list *optional_device_extension_list =
|
||||
u_string_list_create_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions));
|
||||
struct u_extension_list *required_device_extension_list =
|
||||
u_extension_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions));
|
||||
|
||||
struct u_extension_list *optional_device_extension_list =
|
||||
u_extension_list_create_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions));
|
||||
|
||||
struct comp_vulkan_arguments vk_args = {
|
||||
.get_instance_proc_address = vkGetInstanceProcAddr,
|
||||
@@ -199,10 +209,10 @@ compositor_init_vulkan(struct null_compositor *c)
|
||||
struct comp_vulkan_results vk_res = {0};
|
||||
bool bundle_ret = comp_vulkan_init_bundle(vk, &vk_args, &vk_res);
|
||||
|
||||
u_string_list_destroy(&required_instance_ext_list);
|
||||
u_string_list_destroy(&optional_instance_ext_list);
|
||||
u_string_list_destroy(&required_device_extension_list);
|
||||
u_string_list_destroy(&optional_device_extension_list);
|
||||
u_extension_list_destroy(&required_instance_ext_list);
|
||||
u_extension_list_destroy(&optional_instance_ext_list);
|
||||
u_extension_list_destroy(&required_device_extension_list);
|
||||
u_extension_list_destroy(&optional_device_extension_list);
|
||||
|
||||
if (!bundle_ret) {
|
||||
return false;
|
||||
|
||||
@@ -178,7 +178,7 @@ fill_in_results(struct vk_bundle *vk, const struct comp_vulkan_arguments *vk_arg
|
||||
static VkResult
|
||||
create_instance(struct vk_bundle *vk, const struct comp_vulkan_arguments *vk_args)
|
||||
{
|
||||
struct u_string_list *instance_ext_list = NULL;
|
||||
struct u_extension_list *instance_ext_list = NULL;
|
||||
VkResult ret;
|
||||
|
||||
assert(vk_args->required_instance_version != 0);
|
||||
@@ -217,8 +217,8 @@ create_instance(struct vk_bundle *vk, const struct comp_vulkan_arguments *vk_arg
|
||||
VkInstanceCreateInfo instance_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pApplicationInfo = &app_info,
|
||||
.enabledExtensionCount = u_string_list_get_size(instance_ext_list),
|
||||
.ppEnabledExtensionNames = u_string_list_get_data(instance_ext_list),
|
||||
.enabledExtensionCount = u_extension_list_get_size(instance_ext_list),
|
||||
.ppEnabledExtensionNames = u_extension_list_get_data(instance_ext_list),
|
||||
};
|
||||
|
||||
ret = vk->vkCreateInstance(&instance_info, NULL, &vk->instance);
|
||||
@@ -239,7 +239,7 @@ create_instance(struct vk_bundle *vk, const struct comp_vulkan_arguments *vk_arg
|
||||
// Needs to be filled in before getting functions.
|
||||
vk_fill_in_has_instance_extensions(vk, instance_ext_list);
|
||||
|
||||
u_string_list_destroy(&instance_ext_list);
|
||||
u_extension_list_destroy(&instance_ext_list);
|
||||
|
||||
ret = vk_get_instance_functions(vk);
|
||||
if (ret != VK_SUCCESS) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2019-2021, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -11,7 +12,7 @@
|
||||
|
||||
#include "xrt/xrt_compositor.h"
|
||||
#include "util/u_logging.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
#include "vk/vk_helpers.h"
|
||||
|
||||
|
||||
@@ -32,16 +33,16 @@ struct comp_vulkan_arguments
|
||||
PFN_vkGetInstanceProcAddr get_instance_proc_address;
|
||||
|
||||
//! Extensions that the instance is created with.
|
||||
struct u_string_list *required_instance_extensions;
|
||||
struct u_extension_list *required_instance_extensions;
|
||||
|
||||
//! Extensions that the instance is created with.
|
||||
struct u_string_list *optional_instance_extensions;
|
||||
struct u_extension_list *optional_instance_extensions;
|
||||
|
||||
//! Extensions that the device is created with.
|
||||
struct u_string_list *required_device_extensions;
|
||||
struct u_extension_list *required_device_extensions;
|
||||
|
||||
//! Extensions that the device is created with.
|
||||
struct u_string_list *optional_device_extensions;
|
||||
struct u_extension_list *optional_device_extensions;
|
||||
|
||||
//! Logging level to be set on the @ref vk_bundle.
|
||||
enum u_logging_level log_level;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright 2018-2024, Collabora, Ltd.
|
||||
// Copyright 2024-2025, NVIDIA CORPORATION.
|
||||
// Copyright 2024-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "util/u_misc.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
|
||||
#include "vk/vk_helpers.h"
|
||||
|
||||
@@ -249,7 +249,7 @@ oxr_vk_create_vulkan_instance(struct oxr_logger *log,
|
||||
return res;
|
||||
}
|
||||
|
||||
struct u_string_list *instance_ext_list = u_string_list_create_from_array(
|
||||
struct u_extension_list_builder *instance_ext_builder = u_extension_list_builder_create_from_array(
|
||||
required_vk_instance_extensions, ARRAY_SIZE(required_vk_instance_extensions));
|
||||
|
||||
#if defined(VK_EXT_debug_utils)
|
||||
@@ -263,7 +263,7 @@ oxr_vk_create_vulkan_instance(struct oxr_logger *log,
|
||||
continue;
|
||||
}
|
||||
|
||||
u_string_list_append_unique(instance_ext_list, optional_vk_instance_extensions[i]);
|
||||
u_extension_list_builder_append_unique(instance_ext_builder, optional_vk_instance_extensions[i]);
|
||||
|
||||
#if defined(VK_EXT_debug_utils)
|
||||
if (strcmp(optional_vk_instance_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
|
||||
@@ -273,13 +273,15 @@ oxr_vk_create_vulkan_instance(struct oxr_logger *log,
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < createInfo->vulkanCreateInfo->enabledExtensionCount; i++) {
|
||||
u_string_list_append_unique(instance_ext_list,
|
||||
createInfo->vulkanCreateInfo->ppEnabledExtensionNames[i]);
|
||||
u_extension_list_builder_append_unique(instance_ext_builder,
|
||||
createInfo->vulkanCreateInfo->ppEnabledExtensionNames[i]);
|
||||
}
|
||||
|
||||
struct u_extension_list *instance_ext_list = u_extension_list_builder_build(&instance_ext_builder);
|
||||
|
||||
VkInstanceCreateInfo modified_info = *createInfo->vulkanCreateInfo;
|
||||
modified_info.ppEnabledExtensionNames = u_string_list_get_data(instance_ext_list);
|
||||
modified_info.enabledExtensionCount = u_string_list_get_size(instance_ext_list);
|
||||
modified_info.ppEnabledExtensionNames = u_extension_list_get_data(instance_ext_list);
|
||||
modified_info.enabledExtensionCount = u_extension_list_get_size(instance_ext_list);
|
||||
|
||||
*vulkanResult = loaded_CreateInstance(&modified_info, createInfo->vulkanAllocator, vulkanInstance);
|
||||
|
||||
@@ -305,7 +307,7 @@ oxr_vk_create_vulkan_instance(struct oxr_logger *log,
|
||||
}
|
||||
#endif
|
||||
|
||||
u_string_list_destroy(&instance_ext_list);
|
||||
u_extension_list_destroy(&instance_ext_list);
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
@@ -400,12 +402,12 @@ oxr_vk_create_vulkan_device(struct oxr_logger *log,
|
||||
|
||||
VkPhysicalDevice physical_device = createInfo->vulkanPhysicalDevice;
|
||||
|
||||
struct u_string_list *device_extension_list =
|
||||
u_string_list_create_from_array(required_vk_device_extensions, ARRAY_SIZE(required_vk_device_extensions));
|
||||
struct u_extension_list_builder *device_extension_builder = u_extension_list_builder_create_from_array(
|
||||
required_vk_device_extensions, ARRAY_SIZE(required_vk_device_extensions));
|
||||
|
||||
for (uint32_t i = 0; i < createInfo->vulkanCreateInfo->enabledExtensionCount; i++) {
|
||||
u_string_list_append_unique(device_extension_list,
|
||||
createInfo->vulkanCreateInfo->ppEnabledExtensionNames[i]);
|
||||
u_extension_list_builder_append_unique(device_extension_builder,
|
||||
createInfo->vulkanCreateInfo->ppEnabledExtensionNames[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -431,7 +433,7 @@ oxr_vk_create_vulkan_device(struct oxr_logger *log,
|
||||
continue;
|
||||
}
|
||||
|
||||
u_string_list_append_unique(device_extension_list, optional_device_extensions[i]);
|
||||
u_extension_list_builder_append_unique(device_extension_builder, optional_device_extensions[i]);
|
||||
|
||||
#if defined(XRT_GRAPHICS_SYNC_HANDLE_IS_FD)
|
||||
if (strcmp(optional_device_extensions[i], VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME) == 0) {
|
||||
@@ -449,6 +451,7 @@ oxr_vk_create_vulkan_device(struct oxr_logger *log,
|
||||
|
||||
free(props);
|
||||
|
||||
struct u_extension_list *device_extension_list = u_extension_list_builder_build(&device_extension_builder);
|
||||
|
||||
VkPhysicalDeviceFeatures2KHR physical_device_features = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
|
||||
@@ -462,7 +465,7 @@ oxr_vk_create_vulkan_device(struct oxr_logger *log,
|
||||
.timelineSemaphore = VK_FALSE,
|
||||
};
|
||||
|
||||
if (u_string_list_contains(device_extension_list, VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)) {
|
||||
if (u_extension_list_contains(device_extension_list, VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME)) {
|
||||
physical_device_features.pNext = &timeline_semaphore_info;
|
||||
}
|
||||
#endif
|
||||
@@ -475,8 +478,8 @@ oxr_vk_create_vulkan_device(struct oxr_logger *log,
|
||||
|
||||
|
||||
VkDeviceCreateInfo modified_info = *createInfo->vulkanCreateInfo;
|
||||
modified_info.ppEnabledExtensionNames = u_string_list_get_data(device_extension_list);
|
||||
modified_info.enabledExtensionCount = u_string_list_get_size(device_extension_list);
|
||||
modified_info.ppEnabledExtensionNames = u_extension_list_get_data(device_extension_list);
|
||||
modified_info.enabledExtensionCount = u_extension_list_get_size(device_extension_list);
|
||||
|
||||
#ifdef VK_KHR_timeline_semaphore
|
||||
VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore = {
|
||||
@@ -554,7 +557,7 @@ oxr_vk_create_vulkan_device(struct oxr_logger *log,
|
||||
}
|
||||
#endif
|
||||
|
||||
u_string_list_destroy(&device_extension_list);
|
||||
u_extension_list_destroy(&device_extension_list);
|
||||
|
||||
return XR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2019-2023, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -133,10 +134,12 @@ static const char *optional_device_extensions[] = {
|
||||
};
|
||||
|
||||
static VkResult
|
||||
select_instances_extensions(struct sdl_compositor *c, struct u_string_list *required, struct u_string_list *optional)
|
||||
select_instances_extensions(struct sdl_compositor *c,
|
||||
struct u_extension_list_builder *required_builder,
|
||||
struct u_extension_list_builder *optional_builder)
|
||||
{
|
||||
#ifdef VK_EXT_display_surface_counter
|
||||
u_string_list_append(optional, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME);
|
||||
u_extension_list_builder_append(optional_builder, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME);
|
||||
#endif
|
||||
|
||||
return VK_SUCCESS;
|
||||
@@ -149,25 +152,32 @@ compositor_init_vulkan(struct sdl_compositor *c, enum u_logging_level log_level)
|
||||
VkResult ret;
|
||||
|
||||
// every backend needs at least the common extensions
|
||||
struct u_string_list *required_instance_ext_list =
|
||||
u_string_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common));
|
||||
struct u_extension_list_builder *required_instance_ext_builder = u_extension_list_builder_create_from_array( //
|
||||
instance_extensions_common, //
|
||||
ARRAY_SIZE(instance_extensions_common)); //
|
||||
|
||||
struct u_string_list *optional_instance_ext_list = u_string_list_create();
|
||||
struct u_extension_list_builder *optional_instance_ext_builder = u_extension_list_builder_create();
|
||||
|
||||
ret = select_instances_extensions(c, required_instance_ext_list, optional_instance_ext_list);
|
||||
ret = select_instances_extensions(c, required_instance_ext_builder, optional_instance_ext_builder);
|
||||
if (ret != VK_SUCCESS) {
|
||||
VK_ERROR(vk, "select_instances_extensions: %s\n\tFailed to select instance extensions.",
|
||||
vk_result_string(ret));
|
||||
u_string_list_destroy(&required_instance_ext_list);
|
||||
u_string_list_destroy(&optional_instance_ext_list);
|
||||
u_extension_list_builder_destroy(&required_instance_ext_builder);
|
||||
u_extension_list_builder_destroy(&optional_instance_ext_builder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct u_string_list *required_device_extension_list =
|
||||
u_string_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions));
|
||||
// Consumes the builder and returns a new list.
|
||||
struct u_extension_list *required_instance_ext_list =
|
||||
u_extension_list_builder_build(&required_instance_ext_builder);
|
||||
struct u_extension_list *optional_instance_ext_list =
|
||||
u_extension_list_builder_build(&optional_instance_ext_builder);
|
||||
|
||||
struct u_string_list *optional_device_extension_list =
|
||||
u_string_list_create_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions));
|
||||
struct u_extension_list *required_device_extension_list =
|
||||
u_extension_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions));
|
||||
|
||||
struct u_extension_list *optional_device_extension_list =
|
||||
u_extension_list_create_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions));
|
||||
|
||||
struct comp_vulkan_arguments vk_args = {
|
||||
.get_instance_proc_address = vkGetInstanceProcAddr,
|
||||
@@ -186,10 +196,10 @@ compositor_init_vulkan(struct sdl_compositor *c, enum u_logging_level log_level)
|
||||
struct comp_vulkan_results vk_res = {0};
|
||||
bool bundle_ret = comp_vulkan_init_bundle(vk, &vk_args, &vk_res);
|
||||
|
||||
u_string_list_destroy(&required_instance_ext_list);
|
||||
u_string_list_destroy(&optional_instance_ext_list);
|
||||
u_string_list_destroy(&required_device_extension_list);
|
||||
u_string_list_destroy(&optional_device_extension_list);
|
||||
u_extension_list_destroy(&required_instance_ext_list);
|
||||
u_extension_list_destroy(&optional_instance_ext_list);
|
||||
u_extension_list_destroy(&required_device_extension_list);
|
||||
u_extension_list_destroy(&optional_device_extension_list);
|
||||
|
||||
if (!bundle_ret) {
|
||||
return false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2022-2024, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -20,7 +21,7 @@
|
||||
#include "catch_amalgamated.hpp"
|
||||
#include "util/comp_vulkan.h"
|
||||
#include "util/u_logging.h"
|
||||
#include "util/u_string_list.h"
|
||||
#include "util/u_extension_list.h"
|
||||
#include "vk/vk_helpers.h"
|
||||
#include "xrt/xrt_compositor.h"
|
||||
#include <xrt/xrt_deleters.hpp>
|
||||
@@ -85,7 +86,7 @@ static const char *required_device_extensions[] = {
|
||||
|
||||
|
||||
using unique_string_list =
|
||||
std::unique_ptr<u_string_list, xrt::deleters::ptr_ptr_deleter<u_string_list, &u_string_list_destroy>>;
|
||||
std::unique_ptr<u_extension_list, xrt::deleters::ptr_ptr_deleter<u_extension_list, &u_extension_list_destroy>>;
|
||||
|
||||
static void
|
||||
xrt_comp_vk_destroy(struct xrt_compositor_vk **ptr_xcvk)
|
||||
@@ -108,14 +109,14 @@ TEST_CASE("client_compositor", "[.][needgpu]")
|
||||
|
||||
// every backend needs at least the common extensions
|
||||
unique_string_list required_instance_ext_list{
|
||||
u_string_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common))};
|
||||
u_extension_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common))};
|
||||
|
||||
unique_string_list optional_instance_ext_list{u_string_list_create()};
|
||||
unique_string_list optional_instance_ext_list{u_extension_list_create()};
|
||||
|
||||
unique_string_list required_device_extension_list{
|
||||
u_string_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions))};
|
||||
u_extension_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions))};
|
||||
|
||||
unique_string_list optional_device_extension_list{u_string_list_create()};
|
||||
unique_string_list optional_device_extension_list{u_extension_list_create()};
|
||||
|
||||
comp_vulkan_arguments args{VK_MAKE_VERSION(1, 0, 0),
|
||||
vkGetInstanceProcAddr,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2019-2022, Collabora, Ltd.
|
||||
// Copyright 2025-2026, NVIDIA CORPORATION.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
@@ -18,7 +19,7 @@
|
||||
#include <xrt/xrt_vulkan_includes.h>
|
||||
#include <vk/vk_helpers.h>
|
||||
#include <util/comp_vulkan.h>
|
||||
#include <util/u_string_list.hpp>
|
||||
#include <util/u_extension_list.hpp>
|
||||
|
||||
|
||||
static const char *instance_extensions_common[] = {
|
||||
@@ -71,7 +72,7 @@ static const char *optional_device_extensions[] = {
|
||||
#endif
|
||||
};
|
||||
using unique_string_list =
|
||||
std::unique_ptr<u_string_list, xrt::deleters::ptr_ptr_deleter<u_string_list, &u_string_list_destroy>>;
|
||||
std::unique_ptr<u_extension_list, xrt::deleters::ptr_ptr_deleter<u_extension_list, &u_extension_list_destroy>>;
|
||||
|
||||
struct VkBundleDestroyer
|
||||
{
|
||||
@@ -119,15 +120,15 @@ vktest_init_bundle(struct vk_bundle *vk)
|
||||
{
|
||||
// every backend needs at least the common extensions
|
||||
unique_string_list required_instance_ext_list{
|
||||
u_string_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common))};
|
||||
u_extension_list_create_from_array(instance_extensions_common, ARRAY_SIZE(instance_extensions_common))};
|
||||
|
||||
unique_string_list optional_instance_ext_list{u_string_list_create()};
|
||||
unique_string_list optional_instance_ext_list{u_extension_list_create()};
|
||||
|
||||
unique_string_list required_device_extension_list{
|
||||
u_string_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions))};
|
||||
u_extension_list_create_from_array(required_device_extensions, ARRAY_SIZE(required_device_extensions))};
|
||||
|
||||
unique_string_list optional_device_extension_list{
|
||||
u_string_list_create_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions))};
|
||||
u_extension_list_create_from_array(optional_device_extensions, ARRAY_SIZE(optional_device_extensions))};
|
||||
|
||||
U_ZERO(vk);
|
||||
comp_vulkan_arguments args{VK_MAKE_VERSION(1, 0, 0),
|
||||
|
||||
Reference in new issue
Block a user