Skip to content

Commit

Permalink
Add Layer Settings API to framework, improve batch mode error recover…
Browse files Browse the repository at this point in the history
…y, fix macOS issues (#1084)

* Add infrastructure to support Vulkan layer settings extension and API

* shader_debugprintf: Enable debugPrintfEXT using layer settings API vs. create_instance() custom override

* descriptor_indexing: On macOS enable Metal Argument Buffers via layer settings and work-around variable descriptor counts

* Fix CMakeLists.txt find dxc logic - check for Vulkan_dxc_EXECUTABLE not DEFINED Vulkan_dxc_EXECUTABLE

* Enable VK_ENABLE_BETA_EXTENSIONS on Apple platforms for VK_KHR_portability_subset extension and features

* Batch mode: Reset target environment to default prior to each sample; permit VK_SUBOPTIMAL_KHR

* Don't create app bundle on macOS in order to match build/run documentation

* Add .DS_Store to .gitignore for macOS cleanliness

* shader_debugprintf: Override get_validation_layers() and allow layer settings to work with Release builds

* Batch mode: Improve error recovery by using throw std::runtime_error() vs. ExitCode::FatalError

* Batch mode: Improve error recovery for async_compute, fragment_shader_barycentric, and texture_mipmap_generation samples

* CMakeLists: Move project() definition before find_package(Vulkan) to setup platform default search paths for dxc

* Remove HLSL shader compilation warning when VULKAN_SDK is not found

* Modify macOS run documentation to include possibilty of arm64 hosts

* shader_debugprintf: Check for VK_EXT_layer_settings at runtime for backwards compatibilty with older SDKs

* Fix CI warnings for Doxygen and Copyright dates

* Fix CI warnings for files identified by clang-format

* Incorporate initial feedback from @asuessenbach

* Remove #if defined(VK_EXT_layer_settings) guards from layer settings code

* pipeline_cache sample: Replace VK_CHECK in destructor with explicit error handling and logging

* descriptor_indexing and shader_debugprintf: Small changes to support older Vulkan SDKs

* Incorporate subsequent feedback from @asuessenbach

* Try to fix clang-format issues with async_compute.cpp and pipeline_cache.cpp

* Use VKB_ENABLE_PORTABILITY vs. VK_ENABLE_BETA_EXTENSIONS to guard portability subset features

* Remove duplicates and reuse runtime checks for VK_KHR_portability_enumeration

* Remove descriptor_indexing sample workaround for Apple Vulkan SDKs > 1.3.283

* Update shader_debugprintf README to describe layer settings method of enabling debugPrintfEXT

* Use Vulkan_dxc_exe_FOUND where possible, use Vulkan_dxc_EXECUTABLE in sample_helper.cmake
  • Loading branch information
SRSaunders authored Aug 18, 2024
1 parent 3fcc530 commit fdce530
Show file tree
Hide file tree
Showing 33 changed files with 423 additions and 133 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ tests/system_test/tmp
output/*
.mypy_cache
tags
.DS_Store

# vim backup and temp files
*~
Expand Down
18 changes: 8 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,30 @@ endif()

cmake_minimum_required(VERSION 3.16)

project(vulkan_samples)

# search for Vulkan SDK
find_package(Vulkan)

if(VULKAN_FOUND)
if(NOT Vulkan_dxc_EXECUTABLE)
if(Vulkan_FOUND)
if(NOT Vulkan_dxc_exe_FOUND)
find_program(Vulkan_dxc_EXECUTABLE
NAMES dxc
HINTS
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VULKAN_SDK}/bin"
)
endif()
if(DEFINED Vulkan_dxc_EXECUTABLE)
message("Found DirectX Shader Compiler under ${Vulkan_dxc_EXECUTABLE}")
elseif()
message("Couldn't find DirectX Shader Compiler executable, make sure it is present in Vulkan SDK or add it manually via Vulkan_dxc_EXECUTABLE env variable")
if(Vulkan_dxc_EXECUTABLE)
message(STATUS "Found DirectX Shader Compiler under ${Vulkan_dxc_EXECUTABLE}")
else()
message(STATUS "Couldn't find DirectX Shader Compiler executable, make sure it is present in Vulkan SDK or add it manually via Vulkan_dxc_EXECUTABLE cmake variable. HLSL shaders won't be compiled.")
endif()
else()
message("VULKAN_SDK path not found, HLSL shaders won't be compiled")
endif()

# globally add VKB_DEBUG for the debug build
add_compile_definitions($<$<CONFIG:DEBUG>:VKB_DEBUG>)

project(vulkan_samples)

if(MSVC AND (DEFINED CMAKE_C_COMPILER_LAUNCHER))
message(DEBUG "Setting MSVC flags to /Z7 for ccache compatibility. Current flags: ${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
Expand Down
20 changes: 9 additions & 11 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,15 @@ if(ANDROID)
endif()

add_library(${PROJECT_NAME} SHARED ${SRC})
elseif (APPLE)
if(IOS)
list(REMOVE_AT SRC 0)
list(APPEND SRC
${CMAKE_CURRENT_SOURCE_DIR}/ios/main.mm
${CMAKE_CURRENT_SOURCE_DIR}/ios/AppDelegate.h
${CMAKE_CURRENT_SOURCE_DIR}/ios/AppDelegate.m
${CMAKE_CURRENT_SOURCE_DIR}/ios/ViewController.h
${CMAKE_CURRENT_SOURCE_DIR}/ios/ViewController.mm
)
endif ()
elseif(IOS)
list(REMOVE_AT SRC 0)
list(APPEND SRC
${CMAKE_CURRENT_SOURCE_DIR}/ios/main.mm
${CMAKE_CURRENT_SOURCE_DIR}/ios/AppDelegate.h
${CMAKE_CURRENT_SOURCE_DIR}/ios/AppDelegate.m
${CMAKE_CURRENT_SOURCE_DIR}/ios/ViewController.h
${CMAKE_CURRENT_SOURCE_DIR}/ios/ViewController.mm
)
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SRC})
else()
add_executable(${PROJECT_NAME} WIN32 ${SRC})
Expand Down
9 changes: 2 additions & 7 deletions bldsys/cmake/global_options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,10 @@ endif()

if(APPLE)
cmake_minimum_required(VERSION 3.24)
set(VKB_ENABLE_PORTABILITY ON CACHE BOOL "Enable portability enumeration and subset features in the framework. This is required to be set when running on Apple platforms." FORCE)
if(IOS)
set(CMAKE_XCODE_GENERATE_SCHEME TRUE)
endif ()
find_package(Vulkan)
if(Vulkan_VERSION GREATER_EQUAL 1.3)
set(VKB_ENABLE_PORTABILITY ON CACHE BOOL "Enable portability extension enumeration in the framework. This is required to be set if running MoltenVK and Vulkan 1.3+" FORCE)
else()
set(VKB_ENABLE_PORTABILITY OFF CACHE BOOL "Enable portability extension enumeration in the framework. This is required to be off if running Vulkan less than 1.3" FORCE)
endif()
endif()
endif()

set(VKB_WARNINGS_AS_ERRORS ON CACHE BOOL "Enable Warnings as Errors")
Expand Down
2 changes: 1 addition & 1 deletion bldsys/cmake/sample_helper.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ endif()
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_CLANG_TIDY "${VKB_DO_CLANG_TIDY}")
endif()

if(DEFINED Vulkan_dxc_EXECUTABLE AND DEFINED SHADERS_HLSL)
if(Vulkan_dxc_EXECUTABLE AND DEFINED SHADERS_HLSL)
compile_hlsl_shaders(
SHADERS_HLSL ${TARGET_SHADERS_HLSL}
DXC_ADDITIONAL_ARGUMENTS ${TARGET_DXC_ADDITIONAL_ARGUMENTS}
Expand Down
2 changes: 1 addition & 1 deletion docs/build.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ cmake --build build/mac --config Release --target vulkan_samples -j4
`Step 3.` Run the *Vulkan Samples* application to display the help message

----
./build/mac/app/bin/Release/x86_64/vulkan_samples --help
./build/mac/app/bin/Release/<x86_64|arm64>/vulkan_samples --help
----

== iOS
Expand Down
2 changes: 1 addition & 1 deletion framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ if(${VKB_VULKAN_DEBUG})
endif()

if(${VKB_ENABLE_PORTABILITY})
message(STATUS "Vulkan Portability extension is enabled")
message(STATUS "Vulkan Portability Enumeration and Portability Subset extensions are enabled")
target_compile_definitions(${PROJECT_NAME} PUBLIC VKB_ENABLE_PORTABILITY)
endif()

Expand Down
17 changes: 8 additions & 9 deletions framework/common/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,14 @@ class VulkanException : public std::runtime_error
} // namespace vkb

/// @brief Helper macro to test the result of Vulkan calls which can return an error.
#define VK_CHECK(x) \
do \
{ \
VkResult err = x; \
if (err) \
{ \
LOGE("Detected Vulkan error: {}", vkb::to_string(err)); \
abort(); \
} \
#define VK_CHECK(x) \
do \
{ \
VkResult err = x; \
if (err) \
{ \
throw std::runtime_error("Detected Vulkan error: " + vkb::to_string(err)); \
} \
} while (0)

#define ASSERT_VK_HANDLE(handle) \
Expand Down
7 changes: 7 additions & 0 deletions framework/common/strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,13 @@ const std::string to_string(VkResult result)
STR(ERROR_INCOMPATIBLE_DRIVER);
STR(ERROR_TOO_MANY_OBJECTS);
STR(ERROR_FORMAT_NOT_SUPPORTED);
STR(ERROR_FRAGMENTED_POOL);
STR(ERROR_UNKNOWN);
STR(ERROR_OUT_OF_POOL_MEMORY);
STR(ERROR_INVALID_EXTERNAL_HANDLE);
STR(ERROR_FRAGMENTATION);
STR(ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
STR(PIPELINE_COMPILE_REQUIRED);
STR(ERROR_SURFACE_LOST_KHR);
STR(ERROR_NATIVE_WINDOW_IN_USE_KHR);
STR(SUBOPTIMAL_KHR);
Expand Down
19 changes: 17 additions & 2 deletions framework/core/hpp_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +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::vector<vk::LayerSettingEXT> &required_layer_settings,
bool headless,
uint32_t api_version)
{
Expand All @@ -211,7 +212,7 @@ HPPInstance::HPPInstance(const std::string &applicati

#if (defined(VKB_ENABLE_PORTABILITY))
enable_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
enable_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
bool portability_enumeration_available = enable_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
#endif

#ifdef USE_VALIDATION_LAYER_FEATURES
Expand Down Expand Up @@ -326,7 +327,10 @@ HPPInstance::HPPInstance(const std::string &applicati
#endif

#if (defined(VKB_ENABLE_PORTABILITY))
instance_info.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
if (portability_enumeration_available)
{
instance_info.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
}
#endif

#ifdef USE_VALIDATION_LAYER_FEATURES
Expand All @@ -347,6 +351,17 @@ HPPInstance::HPPInstance(const std::string &applicati
}
#endif

vk::LayerSettingsCreateInfoEXT layerSettingsCreateInfo;

// If layer settings extension enabled by sample, then activate layer settings during instance creation
if (std::find(enabled_extensions.begin(), enabled_extensions.end(), VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) != enabled_extensions.end())
{
layerSettingsCreateInfo.settingCount = static_cast<uint32_t>(required_layer_settings.size());
layerSettingsCreateInfo.pSettings = required_layer_settings.data();
layerSettingsCreateInfo.pNext = instance_info.pNext;
instance_info.pNext = &layerSettingsCreateInfo;
}

// Create the Vulkan instance
handle = vk::createInstance(instance_info);

Expand Down
4 changes: 3 additions & 1 deletion framework/core/hpp_instance.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
/* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -53,13 +53,15 @@ class HPPInstance
* @param application_name The name of the application
* @param required_extensions The extensions requested to be enabled
* @param required_validation_layers The validation layers to be enabled
* @param required_layer_settings The layer settings to be enabled
* @param headless Whether the application is requesting a headless setup or not
* @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> &required_extensions = {},
const std::vector<const char *> &required_validation_layers = {},
const std::vector<vk::LayerSettingEXT> &required_layer_settings = {},
bool headless = false,
uint32_t api_version = VK_API_VERSION_1_0);

Expand Down
19 changes: 17 additions & 2 deletions framework/core/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,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::vector<VkLayerSettingEXT> &required_layer_settings,
bool headless,
uint32_t api_version)
{
Expand Down Expand Up @@ -215,7 +216,7 @@ Instance::Instance(const std::string &application_nam

#if (defined(VKB_ENABLE_PORTABILITY))
enable_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
enable_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
bool portability_enumeration_available = enable_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, available_instance_extensions, enabled_extensions);
#endif

#ifdef USE_VALIDATION_LAYER_FEATURES
Expand Down Expand Up @@ -350,7 +351,10 @@ Instance::Instance(const std::string &application_nam
#endif

#if (defined(VKB_ENABLE_PORTABILITY))
instance_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
if (portability_enumeration_available)
{
instance_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
}
#endif

// Some of the specialized layers need to be enabled explicitly
Expand All @@ -376,6 +380,17 @@ Instance::Instance(const std::string &application_nam
}
#endif

VkLayerSettingsCreateInfoEXT layerSettingsCreateInfo{VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT};

// If layer settings extension enabled by sample, then activate layer settings during instance creation
if (std::find(enabled_extensions.begin(), enabled_extensions.end(), VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) != enabled_extensions.end())
{
layerSettingsCreateInfo.settingCount = static_cast<uint32_t>(required_layer_settings.size());
layerSettingsCreateInfo.pSettings = required_layer_settings.data();
layerSettingsCreateInfo.pNext = instance_info.pNext;
instance_info.pNext = &layerSettingsCreateInfo;
}

// Create the Vulkan instance
VkResult result = vkCreateInstance(&instance_info, nullptr, &handle);

Expand Down
2 changes: 2 additions & 0 deletions framework/core/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ class Instance
* @param application_name The name of the application
* @param required_extensions The extensions requested to be enabled
* @param required_validation_layers The validation layers to be enabled
* @param required_layer_settings The layer settings to be enabled
* @param headless Whether the application is requesting a headless setup or not
* @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,
const std::unordered_map<const char *, bool> &required_extensions = {},
const std::vector<const char *> &required_validation_layers = {},
const std::vector<VkLayerSettingEXT> &required_layer_settings = {},
bool headless = false,
uint32_t api_version = VK_API_VERSION_1_0);

Expand Down
32 changes: 17 additions & 15 deletions framework/platform/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "core/util/logging.hpp"
#include "force_close/force_close.h"
#include "glsl_compiler.h"
#include "platform/parsers/CLI11.h"
#include "platform/plugins/plugin.h"
#include "vulkan_sample.h"
Expand Down Expand Up @@ -134,8 +135,7 @@ ExitCode Platform::main_loop_frame()
{
if (!start_app())
{
LOGE("Failed to load requested application");
return ExitCode::FatalError;
throw std::runtime_error("Failed to load requested application");
}

// Compensate for load times of the app by rendering the first frame pre-emptively
Expand All @@ -161,17 +161,17 @@ ExitCode Platform::main_loop_frame()

on_app_error(active_app->get_name());

if (app_requested())
{
LOGI("Attempting to load next application");
}
else
{
if (app_requested())
{
LOGI("Attempting to load next application");
}
else
{
set_last_error(e.what());
return ExitCode::FatalError;
}
}
}
return ExitCode::FatalError;
}
}
}

return ExitCode::Success;
}
Expand All @@ -192,8 +192,7 @@ ExitCode Platform::main_loop()
{
if (!start_app())
{
LOGE("Failed to load requested application");
return ExitCode::FatalError;
throw std::runtime_error("Failed to load requested application");
}

// Compensate for load times of the app by rendering the first frame pre-emptively
Expand Down Expand Up @@ -225,7 +224,7 @@ ExitCode Platform::main_loop()
}
else
{
set_last_error(e.what());
set_last_error(e.what());
return ExitCode::FatalError;
}
}
Expand Down Expand Up @@ -420,6 +419,9 @@ bool Platform::start_app()
active_app->finish();
}

// Reset target environment to default prior to each sample to properly support batch mode
vkb::GLSLCompiler::reset_target_environment();

active_app = requested_app_info->create();

if (!active_app)
Expand Down
5 changes: 3 additions & 2 deletions framework/rendering/hpp_render_context.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
/* Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -310,7 +310,8 @@ void HPPRenderContext::begin_frame()
}
}

if (result != vk::Result::eSuccess)
// eSuboptimalKHR can legitimately occur in batch mode when exiting certain samples (e.g. afbc, msaa, surface_rotation, swapchain_images)
if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR)
{
prev_frame.reset();
return;
Expand Down
Loading

0 comments on commit fdce530

Please sign in to comment.