Skip to content

Improve and fix async compute sample #1366

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

Merged
merged 13 commits into from
Jul 10, 2025
Merged
4 changes: 2 additions & 2 deletions framework/common/hpp_vk_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ struct HPPImageMemoryBarrier
vk::AccessFlags dst_access_mask;
vk::ImageLayout old_layout = vk::ImageLayout::eUndefined;
vk::ImageLayout new_layout = vk::ImageLayout::eUndefined;
uint32_t old_queue_family = VK_QUEUE_FAMILY_IGNORED;
uint32_t new_queue_family = VK_QUEUE_FAMILY_IGNORED;
uint32_t src_queue_family = VK_QUEUE_FAMILY_IGNORED;
uint32_t dst_queue_family = VK_QUEUE_FAMILY_IGNORED;
};

struct HPPLoadStoreInfo
Expand Down
4 changes: 2 additions & 2 deletions framework/common/vk_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ struct ImageMemoryBarrier

VkImageLayout new_layout{VK_IMAGE_LAYOUT_UNDEFINED};

uint32_t old_queue_family{VK_QUEUE_FAMILY_IGNORED};
uint32_t src_queue_family{VK_QUEUE_FAMILY_IGNORED};

uint32_t new_queue_family{VK_QUEUE_FAMILY_IGNORED};
uint32_t dst_queue_family{VK_QUEUE_FAMILY_IGNORED};
};

/**
Expand Down
6 changes: 3 additions & 3 deletions framework/core/command_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -979,13 +979,13 @@ inline void CommandBuffer<bindingType>::image_memory_barrier_impl(vkb::core::HPP
subresource_range.aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil;
}

// actively ignore queue family indices provided by memory_barrier !!
// This can cause a queue family ownership transfer. Check the async_compute sample.
vk::ImageMemoryBarrier image_memory_barrier{.srcAccessMask = memory_barrier.src_access_mask,
.dstAccessMask = memory_barrier.dst_access_mask,
.oldLayout = memory_barrier.old_layout,
.newLayout = memory_barrier.new_layout,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.srcQueueFamilyIndex = memory_barrier.src_queue_family,
.dstQueueFamilyIndex = memory_barrier.dst_queue_family,
.image = image_view.get_image().get_handle(),
.subresourceRange = subresource_range};

Expand Down
98 changes: 79 additions & 19 deletions framework/core/hpp_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,36 @@ bool enable_extension(const char *requested_exte
return is_available;
}

bool enable_layer_setting(const vk::LayerSettingEXT &requested_layer_setting,
const std::vector<const char *> &enabled_layers,
std::vector<vk::LayerSettingEXT> &enabled_layer_settings)
{
// We are checking if the layer is available.
// Vulkan does not provide a reflection API for layer settings. Layer settings are described in each layer JSON manifest.
bool is_available =
std::ranges::any_of(enabled_layers,
[&requested_layer_setting](auto const &available_layer) { return strcmp(available_layer, requested_layer_setting.pLayerName) == 0; });
if (!is_available)
{
LOGW("Layer: {} not found. Disabling layer setting: {}", requested_layer_setting.pLayerName, requested_layer_setting.pSettingName);
return false;
}

bool is_already_enabled =
std::ranges::any_of(enabled_layer_settings,
[&requested_layer_setting](VkLayerSettingEXT const &enabled_layer_setting) { return (strcmp(requested_layer_setting.pLayerName, enabled_layer_setting.pLayerName) == 0) && (strcmp(requested_layer_setting.pSettingName, enabled_layer_setting.pSettingName) == 0); });

if (is_already_enabled)
{
LOGW("Ignoring duplicated layer setting {} in layer {}.", requested_layer_setting.pSettingName, requested_layer_setting.pLayerName);
return false;
}

LOGI("Enabling layer setting {} in layer {}.", requested_layer_setting.pSettingName, requested_layer_setting.pLayerName);
enabled_layer_settings.push_back(requested_layer_setting);
return true;
}

bool enable_layer(const char *requested_layer,
const std::vector<vk::LayerProperties> &available_layers,
std::vector<const char *> &enabled_layers)
Expand Down Expand Up @@ -169,7 +199,7 @@ bool enable_layer(const char *requested_layer,
HPPInstance::HPPInstance(const std::string &application_name,
const std::unordered_map<const char *, bool> &requested_extensions,
const std::unordered_map<const char *, bool> &requested_layers,
const std::vector<vk::LayerSettingEXT> &required_layer_settings,
const std::vector<vk::LayerSettingEXT> &requested_layer_settings,
uint32_t api_version)
{
std::vector<vk::ExtensionProperties> available_instance_extensions = vk::enumerateInstanceExtensionProperties();
Expand All @@ -194,14 +224,16 @@ HPPInstance::HPPInstance(const std::string &applicati
bool portability_enumeration_available = enable_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
#endif

#ifdef USE_VALIDATION_LAYER_FEATURES
#ifdef USE_VALIDATION_LAYERS
const char *validation_layer_name = "VK_LAYER_KHRONOS_validation";
# ifdef USE_VALIDATION_LAYER_FEATURES
bool validation_features = false;
{
std::vector<vk::ExtensionProperties> available_layer_instance_extensions = vk::enumerateInstanceExtensionProperties(std::string("VK_LAYER_KHRONOS_validation"));

enable_extension(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME, available_layer_instance_extensions, enabled_extensions);
std::vector<vk::ExtensionProperties> available_layer_instance_extensions = vk::enumerateInstanceExtensionProperties(std::string(validation_layer_name));
validation_features = enable_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, available_layer_instance_extensions, enabled_extensions);
}
#endif
# endif // USE_VALIDATION_LAYER_FEATURES
#endif // USE_VALIDATION_LAYERS

// Specific surface extensions are obtained from Window::get_required_surface_extensions
// They are already added to requested_extensions by VulkanSample::prepare
Expand Down Expand Up @@ -257,7 +289,7 @@ HPPInstance::HPPInstance(const std::string &applicati
#ifdef USE_VALIDATION_LAYERS
// NOTE: It's important to have the validation layer as the last one here!!!!
// Otherwise, device creation fails !?!
enable_layer("VK_LAYER_KHRONOS_validation", supported_layers, enabled_layers);
enable_layer(validation_layer_name, supported_layers, enabled_layers);
#endif

vk::ApplicationInfo app_info{.pApplicationName = application_name.c_str(), .pEngineName = "Vulkan Samples", .apiVersion = api_version};
Expand All @@ -268,6 +300,13 @@ HPPInstance::HPPInstance(const std::string &applicati
.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size()),
.ppEnabledExtensionNames = enabled_extensions.data()};

std::vector<vk::LayerSettingEXT> enabled_layer_settings;

for (const vk::LayerSettingEXT &layer_setting : requested_layer_settings)
{
enable_layer_setting(layer_setting, enabled_layers, enabled_layer_settings);
}

#ifdef USE_VALIDATION_LAYERS
vk::DebugUtilsMessengerCreateInfoEXT debug_utils_create_info;
vk::DebugReportCallbackCreateInfoEXT debug_report_create_info;
Expand Down Expand Up @@ -297,31 +336,52 @@ HPPInstance::HPPInstance(const std::string &applicati
}
#endif

// Some of the specialized layers need to be enabled explicitly
// The validation layer does not need to be enabled in code and it can also be configured using the vulkan configurator.
#ifdef USE_VALIDATION_LAYER_FEATURES
vk::ValidationFeaturesEXT validation_features_info;
std::vector<vk::ValidationFeatureEnableEXT> enable_features{};

# if defined(VKB_VALIDATION_LAYERS_GPU_ASSISTED)
const VkBool32 setting_validate_gpuav = VK_TRUE;
if (validation_features)
{
# if defined(VKB_VALIDATION_LAYERS_GPU_ASSISTED)
enable_features.push_back(vk::ValidationFeatureEnableEXT::eGpuAssistedReserveBindingSlot);
enable_features.push_back(vk::ValidationFeatureEnableEXT::eGpuAssisted);
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "gpuav_enable", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_gpuav), enabled_layers, enabled_layer_settings);
}
# endif

# if defined(VKB_VALIDATION_LAYERS_BEST_PRACTICES)
enable_features.push_back(vk::ValidationFeatureEnableEXT::eBestPractices);
const VkBool32 setting_validate_best_practices = VK_TRUE;
const VkBool32 setting_validate_best_practices_arm = VK_TRUE;
const VkBool32 setting_validate_best_practices_amd = VK_TRUE;
const VkBool32 setting_validate_best_practices_img = VK_TRUE;
const VkBool32 setting_validate_best_practices_nvidia = VK_TRUE;
if (validation_features)
{
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "validate_best_practices", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices), enabled_layers, enabled_layer_settings);
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "validate_best_practices_arm", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_arm), enabled_layers, enabled_layer_settings);
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "validate_best_practices_amd", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_amd), enabled_layers, enabled_layer_settings);
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "validate_best_practices_img", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_img), enabled_layers, enabled_layer_settings);
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "validate_best_practices_nvidia", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_nvidia), enabled_layers, enabled_layer_settings);
}
# endif
validation_features_info.setEnabledValidationFeatures(enable_features);
validation_features_info.pNext = instance_info.pNext;
instance_info.pNext = &validation_features_info;

# if defined(VKB_VALIDATION_LAYERS_SYNCHRONIZATION)
const VkBool32 setting_validate_sync = VK_TRUE;
const VkBool32 setting_validate_sync_heuristics = VK_TRUE;
if (validation_features)
{
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "validate_sync", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_sync), enabled_layers, enabled_layer_settings);
enable_layer_setting(vk::LayerSettingEXT(validation_layer_name, "syncval_shader_accesses_heuristic", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_sync_heuristics), enabled_layers, enabled_layer_settings);
}
# endif
#endif

vk::LayerSettingsCreateInfoEXT layerSettingsCreateInfo;

// If layer settings are defined, then activate the sample's required layer settings during instance creation
if (required_layer_settings.size() > 0)
if (enabled_layer_settings.size() > 0)
{
layerSettingsCreateInfo.settingCount = static_cast<uint32_t>(required_layer_settings.size());
layerSettingsCreateInfo.pSettings = required_layer_settings.data();
layerSettingsCreateInfo.settingCount = static_cast<uint32_t>(enabled_layer_settings.size());
layerSettingsCreateInfo.pSettings = enabled_layer_settings.data();
layerSettingsCreateInfo.pNext = instance_info.pNext;
instance_info.pNext = &layerSettingsCreateInfo;
}
Expand Down
10 changes: 5 additions & 5 deletions framework/core/hpp_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ class HPPInstance
* @param application_name The name of the application
* @param requested_extensions The extensions requested to be enabled
* @param requested_layers The validation layers to be enabled
* @param required_layer_settings The layer settings to be enabled
* @param requested_layer_settings The layer settings to be enabled
* @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,
const std::unordered_map<const char *, bool> &requested_extensions = {},
const std::unordered_map<const char *, bool> &requested_layers = {},
const std::vector<vk::LayerSettingEXT> &required_layer_settings = {},
uint32_t api_version = VK_API_VERSION_1_1);
const std::unordered_map<const char *, bool> &requested_extensions = {},
const std::unordered_map<const char *, bool> &requested_layers = {},
const std::vector<vk::LayerSettingEXT> &requested_layer_settings = {},
uint32_t api_version = VK_API_VERSION_1_1);

/**
* @brief Queries the GPUs of a vk::Instance that is already created
Expand Down
Loading
Loading