Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vk ext shader object optional layer #780

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,15 @@ jobs:
- name: Count Diff Lines
continue-on-error: true
id: count-diff
run: echo "line-count=$(echo "${{ steps.clang-diff.outputs.changes }}" | grep -c +++)" >> $GITHUB_OUTPUT
run: |
echo "line-count=$(echo "${{ steps.clang-diff.outputs.changes }}" | grep -c +++)" >> $GITHUB_OUTPUT
echo "${{ steps.clang-diff.outputs.changes }}" >> patch.txt
- if: ${{ steps.count-diff.outputs.line-count > 0 }}
uses: actions/upload-artifact@v3
with:
name: diff-output
path: patch.txt

gpx1000 marked this conversation as resolved.
Show resolved Hide resolved
- name: Assert
run: if test ${{ steps.count-diff.outputs.line-count }} -gt 0; then echo "${{ steps.clang-diff.outputs.changes }}"; exit 1; fi

Expand Down
56 changes: 37 additions & 19 deletions framework/core/hpp_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,16 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugReportFlagsEXT flags
}
#endif

bool validate_layers(const std::vector<const char *> &required,
bool validate_layers(std::unordered_map<const char *, bool> &required,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The required layers here actually are not required (they're allowed to be optional), but requested. Maybe rename the argument?

const std::vector<vk::LayerProperties> &available)
{
std::vector<const char *> remove_vec;
for (auto layer : required)
{
bool found = false;
for (auto &available_layer : available)
{
if (strcmp(available_layer.layerName, layer) == 0)
if (strcmp(available_layer.layerName, layer.first) == 0)
{
found = true;
break;
Expand All @@ -83,38 +84,48 @@ bool validate_layers(const std::vector<const char *> &required,

if (!found)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can replace the loop over the availables with this check:
if (std::none_of(available.begin(), available.end(), [&layer](vk::LayerProperties const &lp) { return lp.layerName == layer.first; }))

{
LOGE("Validation Layer {} not found", layer);
if (!layer.second)
{
LOGW("Optional Layer {} not found, removing it", layer.first)
remove_vec.push_back(layer.first);
continue;
}
LOGE("Validation Layer {} not found", layer.first)
return false;
}
}
for (auto &rem : remove_vec)
{
required.erase(rem);
}

return true;
}
} // namespace

namespace core
{
std::vector<const char *> get_optimal_validation_layers(const std::vector<vk::LayerProperties> &supported_instance_layers)
std::unordered_map<const char *, bool> get_optimal_validation_layers(const std::vector<vk::LayerProperties> &supported_instance_layers)
{
std::vector<std::vector<const char *>> validation_layer_priority_list =
std::vector<std::unordered_map<const char *, bool>> validation_layer_priority_list =
{
// The preferred validation layer is "VK_LAYER_KHRONOS_validation"
{"VK_LAYER_KHRONOS_validation"},
{{"VK_LAYER_KHRONOS_validation", true}},

// Otherwise we fallback to using the LunarG meta layer
{"VK_LAYER_LUNARG_standard_validation"},
{{"VK_LAYER_LUNARG_standard_validation", true}},

// Otherwise we attempt to enable the individual layers that compose the LunarG meta layer since it doesn't exist
{
"VK_LAYER_GOOGLE_threading",
"VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_object_tracker",
"VK_LAYER_LUNARG_core_validation",
"VK_LAYER_GOOGLE_unique_objects",
{"VK_LAYER_GOOGLE_threading", true},
{"VK_LAYER_LUNARG_parameter_validation", true},
{"VK_LAYER_LUNARG_object_tracker", true},
{"VK_LAYER_LUNARG_core_validation", true},
{"VK_LAYER_GOOGLE_unique_objects", true},
},

// Otherwise as a last resort we fallback to attempting to enable the LunarG core layer
{"VK_LAYER_LUNARG_core_validation"}};
{{"VK_LAYER_LUNARG_core_validation", true}}};

for (auto &validation_layers : validation_layer_priority_list)
{
Expand Down Expand Up @@ -175,7 +186,7 @@ bool enable_all_extensions(const std::vector<const char *> required_

HPPInstance::HPPInstance(const std::string &application_name,
const std::unordered_map<const char *, bool> &required_extensions,
const std::vector<const char *> &required_validation_layers,
const std::unordered_map<const char *, bool> &required_validation_layers,
bool headless,
uint32_t api_version)
{
Expand Down Expand Up @@ -268,30 +279,37 @@ HPPInstance::HPPInstance(const std::string &applicati

std::vector<vk::LayerProperties> supported_validation_layers = vk::enumerateInstanceLayerProperties();

std::vector<const char *> requested_validation_layers(required_validation_layers);
std::unordered_map<const char *, bool> requested_validation_layers(required_validation_layers);

#ifdef VKB_VALIDATION_LAYERS
// Determine the optimal validation layers to enable that are necessary for useful debugging
std::vector<const char *> optimal_validation_layers = get_optimal_validation_layers(supported_validation_layers);
requested_validation_layers.insert(requested_validation_layers.end(), optimal_validation_layers.begin(), optimal_validation_layers.end());
std::unordered_map<const char *, bool> optimal_validation_layers = get_optimal_validation_layers(supported_validation_layers);
requested_validation_layers.insert(optimal_validation_layers.begin(), optimal_validation_layers.end());
#endif

if (validate_layers(requested_validation_layers, supported_validation_layers))
{
LOGI("Enabled Validation Layers:")
for (const auto &layer : requested_validation_layers)
{
LOGI(" \t{}", layer);
LOGI(" \t{}", layer.first)
}
}
else
{
throw std::runtime_error("Required validation layers are missing.");
}

std::vector<const char *> final_validation_layers;
final_validation_layers.reserve(requested_validation_layers.size());
for (auto layer : requested_validation_layers)
{
final_validation_layers.push_back(layer.first);
}

vk::ApplicationInfo app_info(application_name.c_str(), 0, "Vulkan Samples", 0, api_version);

vk::InstanceCreateInfo instance_info({}, &app_info, requested_validation_layers, enabled_extensions);
vk::InstanceCreateInfo instance_info({}, &app_info, final_validation_layers, enabled_extensions);

#if defined(VKB_DEBUG) || defined(VKB_VALIDATION_LAYERS)
vk::DebugUtilsMessengerCreateInfoEXT debug_utils_create_info;
Expand Down
8 changes: 4 additions & 4 deletions framework/core/hpp_instance.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
/* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -31,7 +31,7 @@ class HPPPhysicalDevice;
* Attempting to enable them in order of preference, starting with later Vulkan SDK versions
* @param supported_instance_layers A list of validation layers to check against
*/
std::vector<const char *> get_optimal_validation_layers(const std::vector<vk::LayerProperties> &supported_instance_layers);
std::unordered_map<const char *, bool> get_optimal_validation_layers(const std::vector<vk::LayerProperties> &supported_instance_layers);

/**
* @brief A wrapper class for vk::Instance
Expand All @@ -51,9 +51,9 @@ class HPPInstance
* @param api_version The Vulkan API version that the instance will be using
* @throws runtime_error if the required extensions and validation layers are not found
*/
HPPInstance(const std::string & application_name,
HPPInstance(const std::string &application_name,
const std::unordered_map<const char *, bool> &required_extensions = {},
const std::vector<const char *> & required_validation_layers = {},
const std::unordered_map<const char *, bool> &required_validation_layers = {},
bool headless = false,
uint32_t api_version = VK_API_VERSION_1_0);

Expand Down
61 changes: 39 additions & 22 deletions framework/core/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,16 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugReportFlagsEXT flags
}
#endif

bool validate_layers(const std::vector<const char *> &required,
const std::vector<VkLayerProperties> &available)
bool validate_layers(std::unordered_map<const char *, bool> &required,
const std::vector<VkLayerProperties> &available)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same comments as for hpp_instance.cpp hold here.

{
std::vector<const char *> remove_vec;
for (auto layer : required)
{
bool found = false;
for (auto &available_layer : available)
{
if (strcmp(available_layer.layerName, layer) == 0)
if (strcmp(available_layer.layerName, layer.first) == 0)
{
found = true;
break;
Expand All @@ -85,36 +86,45 @@ bool validate_layers(const std::vector<const char *> &required,

if (!found)
{
LOGE("Validation Layer {} not found", layer);
if (!layer.second)
{
LOGW("Optional Layer {} not found, removing it", layer.first)
remove_vec.push_back(layer.first);
continue;
}
LOGE("Validation Layer {} not found", layer.first)
return false;
}
}
for (auto &rem : remove_vec)
{
required.erase(rem);
}

return true;
}
} // namespace

std::vector<const char *> get_optimal_validation_layers(const std::vector<VkLayerProperties> &supported_instance_layers)
std::unordered_map<const char *, bool> get_optimal_validation_layers(const std::vector<VkLayerProperties> &supported_instance_layers)
{
std::vector<std::vector<const char *>> validation_layer_priority_list =
std::vector<std::unordered_map<const char *, bool>> validation_layer_priority_list =
{
// The preferred validation layer is "VK_LAYER_KHRONOS_validation"
{"VK_LAYER_KHRONOS_validation"},
{{"VK_LAYER_KHRONOS_validation", true}},

// Otherwise we fallback to using the LunarG meta layer
{"VK_LAYER_LUNARG_standard_validation"},
{{"VK_LAYER_LUNARG_standard_validation", true}},

// Otherwise we attempt to enable the individual layers that compose the LunarG meta layer since it doesn't exist
{
"VK_LAYER_GOOGLE_threading",
"VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_object_tracker",
"VK_LAYER_LUNARG_core_validation",
"VK_LAYER_GOOGLE_unique_objects",
},
{"VK_LAYER_GOOGLE_threading", true},
{"VK_LAYER_LUNARG_parameter_validation", true},
{"VK_LAYER_LUNARG_object_tracker", true},
{"VK_LAYER_LUNARG_core_validation", true},
{"VK_LAYER_GOOGLE_unique_objects", true}},

// Otherwise as a last resort we fallback to attempting to enable the LunarG core layer
{"VK_LAYER_LUNARG_core_validation"}};
{{"VK_LAYER_LUNARG_core_validation", true}}};

for (auto &validation_layers : validation_layer_priority_list)
{
Expand Down Expand Up @@ -175,7 +185,7 @@ bool enable_all_extensions(const std::vector<const char *> required_ex

Instance::Instance(const std::string &application_name,
const std::unordered_map<const char *, bool> &required_extensions,
const std::vector<const char *> &required_validation_layers,
const std::unordered_map<const char *, bool> &required_validation_layers,
bool headless,
uint32_t api_version)
{
Expand Down Expand Up @@ -280,27 +290,34 @@ Instance::Instance(const std::string &application_nam
std::vector<VkLayerProperties> supported_validation_layers(instance_layer_count);
VK_CHECK(vkEnumerateInstanceLayerProperties(&instance_layer_count, supported_validation_layers.data()));

std::vector<const char *> requested_validation_layers(required_validation_layers);
std::unordered_map<const char *, bool> requested_validation_layers(required_validation_layers);

#ifdef VKB_VALIDATION_LAYERS
// Determine the optimal validation layers to enable that are necessary for useful debugging
std::vector<const char *> optimal_validation_layers = get_optimal_validation_layers(supported_validation_layers);
requested_validation_layers.insert(requested_validation_layers.end(), optimal_validation_layers.begin(), optimal_validation_layers.end());
std::unordered_map<const char *, bool> optimal_validation_layers = get_optimal_validation_layers(supported_validation_layers);
requested_validation_layers.insert(optimal_validation_layers.begin(), optimal_validation_layers.end());
#endif

if (validate_layers(requested_validation_layers, supported_validation_layers))
{
LOGI("Enabled Validation Layers:")
for (const auto &layer : requested_validation_layers)
{
LOGI(" \t{}", layer);
LOGI(" \t{}", layer.first)
}
}
else
{
throw std::runtime_error("Required validation layers are missing.");
}

std::vector<const char *> final_validation_layers;
final_validation_layers.reserve(requested_validation_layers.size());
for (auto layer : requested_validation_layers)
{
final_validation_layers.push_back(layer.first);
}

VkApplicationInfo app_info{VK_STRUCTURE_TYPE_APPLICATION_INFO};

app_info.pApplicationName = application_name.c_str();
Expand All @@ -316,8 +333,8 @@ Instance::Instance(const std::string &application_nam
instance_info.enabledExtensionCount = to_u32(enabled_extensions.size());
instance_info.ppEnabledExtensionNames = enabled_extensions.data();

instance_info.enabledLayerCount = to_u32(requested_validation_layers.size());
instance_info.ppEnabledLayerNames = requested_validation_layers.data();
instance_info.enabledLayerCount = to_u32(final_validation_layers.size());
instance_info.ppEnabledLayerNames = final_validation_layers.data();

#if defined(VKB_DEBUG) || defined(VKB_VALIDATION_LAYERS)
VkDebugUtilsMessengerCreateInfoEXT debug_utils_create_info = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
Expand Down
24 changes: 12 additions & 12 deletions framework/core/instance.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2018-2021, Arm Limited and Contributors
/* Copyright (c) 2018-2023, Arm Limited and Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -28,7 +28,7 @@ class PhysicalDevice;
* Attempting to enable them in order of preference, starting with later Vulkan SDK versions
* @param supported_instance_layers A list of validation layers to check against
*/
std::vector<const char *> get_optimal_validation_layers(const std::vector<VkLayerProperties> &supported_instance_layers);
std::unordered_map<const char *, bool> get_optimal_validation_layers(const std::vector<VkLayerProperties> &supported_instance_layers);

/**
* @brief A wrapper class for VkInstance
Expand All @@ -48,9 +48,9 @@ class Instance
* @param api_version The Vulkan API version that the instance will be using
* @throws runtime_error if the required extensions and validation layers are not found
*/
Instance(const std::string & application_name,
Instance(const std::string &application_name,
const std::unordered_map<const char *, bool> &required_extensions = {},
const std::vector<const char *> & required_validation_layers = {},
const std::unordered_map<const char *, bool> &required_validation_layers = {},
bool headless = false,
uint32_t api_version = VK_API_VERSION_1_0);

Expand Down Expand Up @@ -99,17 +99,17 @@ class Instance
const std::vector<const char *> &get_extensions();

/**
* @brief Returns a const ref to the properties of all requested layers in this instance
* @returns The VkLayerProperties for all requested layers in this instance
*/
* @brief Returns a const ref to the properties of all requested layers in this instance
* @returns The VkLayerProperties for all requested layers in this instance
*/
const std::vector<VkLayerProperties> &get_layer_properties();

/**
* @brief Finds layer properties for the layer with the given name
* @param layerName The layer to search for
* @param properties A reference to a VkLayerProperties struct to populate
* @returns True if the layer was found and populated, false otherwise
*/
* @brief Finds layer properties for the layer with the given name
* @param layerName The layer to search for
* @param properties A reference to a VkLayerProperties struct to populate
* @returns True if the layer was found and populated, false otherwise
*/
bool get_layer_properties(const char *layerName, VkLayerProperties &properties);

private:
Expand Down
4 changes: 2 additions & 2 deletions framework/hpp_vulkan_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,9 @@ vkb::rendering::HPPRenderContext &HPPVulkanSample::get_render_context()
return *render_context;
}

std::vector<const char *> const &HPPVulkanSample::get_validation_layers() const
std::unordered_map<const char *, bool> const &HPPVulkanSample::get_validation_layers() const
{
static std::vector<const char *> validation_layers;
static std::unordered_map<const char *, bool> validation_layers;
return validation_layers;
}

Expand Down
2 changes: 1 addition & 1 deletion framework/hpp_vulkan_sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class HPPVulkanSample : public vkb::Application
*
* @return Vector of additional instance layers. Default is empty vector.
*/
virtual std::vector<const char *> const &get_validation_layers() const;
virtual std::unordered_map<const char *, bool> const &get_validation_layers() const;

/**
* @brief Get sample-specific instance extensions.
Expand Down
2 changes: 1 addition & 1 deletion framework/vulkan_sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ RenderContext &VulkanSample::get_render_context()
return *render_context;
}

const std::vector<const char *> VulkanSample::get_validation_layers()
const std::unordered_map<const char *, bool> VulkanSample::get_validation_layers()
{
return {};
}
Expand Down
Loading