Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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: 8 additions & 2 deletions framework/core/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,17 @@ Device::Device(PhysicalDevice &gpu,
if (is_extension_supported("VK_KHR_performance_query") &&
is_extension_supported("VK_EXT_host_query_reset"))
{
auto perf_counter_features = gpu.request_extension_features<VkPhysicalDevicePerformanceQueryFeaturesKHR>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR);
auto host_query_reset_features = gpu.request_extension_features<VkPhysicalDeviceHostQueryResetFeatures>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES);
auto perf_counter_features =
gpu.get_extension_features<VkPhysicalDevicePerformanceQueryFeaturesKHR>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR);
auto host_query_reset_features =
gpu.get_extension_features<VkPhysicalDeviceHostQueryResetFeatures>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES);

if (perf_counter_features.performanceCounterQueryPools && host_query_reset_features.hostQueryReset)
{
gpu.add_extension_features<VkPhysicalDevicePerformanceQueryFeaturesKHR>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR)
.performanceCounterQueryPools = VK_TRUE;
gpu.add_extension_features<VkPhysicalDeviceHostQueryResetFeatures>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES).hostQueryReset =
VK_TRUE;
enabled_extensions.push_back("VK_KHR_performance_query");
enabled_extensions.push_back("VK_EXT_host_query_reset");
LOGI("Performance query enabled");
Expand Down
6 changes: 4 additions & 2 deletions framework/core/hpp_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,13 @@ HPPDevice::HPPDevice(vkb::core::HPPPhysicalDevice &gpu,
// live in the same command buffer as beginQuery
if (is_extension_supported(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME) && is_extension_supported(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME))
{
auto perf_counter_features = gpu.request_extension_features<vk::PhysicalDevicePerformanceQueryFeaturesKHR>();
auto host_query_reset_features = gpu.request_extension_features<vk::PhysicalDeviceHostQueryResetFeatures>();
auto perf_counter_features = gpu.get_extension_features<vk::PhysicalDevicePerformanceQueryFeaturesKHR>();
auto host_query_reset_features = gpu.get_extension_features<vk::PhysicalDeviceHostQueryResetFeatures>();

if (perf_counter_features.performanceCounterQueryPools && host_query_reset_features.hostQueryReset)
{
gpu.add_extension_features<vk::PhysicalDevicePerformanceQueryFeaturesKHR>().performanceCounterQueryPools = true;
gpu.add_extension_features<vk::PhysicalDeviceHostQueryResetFeatures>().hostQueryReset = true;
enabled_extensions.push_back(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME);
enabled_extensions.push_back(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME);
LOGI("Performance query enabled");
Expand Down
102 changes: 79 additions & 23 deletions framework/core/hpp_physical_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,29 @@ class HPPPhysicalDevice
vk::PhysicalDeviceFeatures &get_mutable_requested_features();

/**
* @brief Requests a third party extension to be used by the framework
* @brief Get an extension features struct
*
* Gets the actual extension features struct with the supported flags set.
* The flags you're interested in can be set in a corresponding struct in the structure chain
* by calling PhysicalDevice::add_extension_features()
* @returns The extension feature struct
*/
template <typename HPPStructureType>
HPPStructureType get_extension_features()
{
// We cannot request extension features if the physical device properties 2 instance extension isn't enabled
if (!instance.is_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
throw std::runtime_error("Couldn't request feature from device as " + std::string(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) +
" isn't enabled!");
}

// Get the extension feature
return handle.getFeatures2KHR<vk::PhysicalDeviceFeatures2KHR, HPPStructureType>().template get<HPPStructureType>();
}

/**
* @brief Add an extension features struct to the structure chain used for device creation
*
* To have the features enabled, this function must be called before the logical device
* is created. To do this request sample specific features inside
Expand All @@ -100,43 +122,73 @@ class HPPPhysicalDevice
* If the feature extension requires you to ask for certain features to be enabled, you can
* modify the struct returned by this function, it will propagate the changes to the logical
* device.
* @returns The extension feature struct
* @returns A reference to the extension feature struct in the structure chain
*/
template <typename HPPStructureType>
HPPStructureType &request_extension_features()
HPPStructureType &add_extension_features()
{
// We cannot request extension features if the physical device properties 2 instance extension isn't enabled
if (!instance.is_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
throw std::runtime_error("Couldn't request feature from device as " + std::string(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) + " isn't enabled!");
throw std::runtime_error("Couldn't request feature from device as " + std::string(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) +
" isn't enabled!");
}

// If the type already exists in the map, return a casted pointer to get the extension feature struct
vk::StructureType structureType = HPPStructureType::structureType; // need to instantiate this value to be usable in find()!
auto extension_features_it = extension_features.find(structureType);
if (extension_features_it != extension_features.end())
// Add an (empty) extension features into the map of extension features
auto [it, added] = extension_features.insert({HPPStructureType::structureType, std::make_shared<HPPStructureType>()});
if (added)
{
return *static_cast<HPPStructureType *>(extension_features_it->second.get());
// if it was actually added, also add it to the structure chain
if (last_requested_extension_feature)
{
static_cast<HPPStructureType *>(it->second.get())->pNext = last_requested_extension_feature;
}
last_requested_extension_feature = it->second.get();
}

// Get the extension feature
vk::StructureChain<vk::PhysicalDeviceFeatures2KHR, HPPStructureType> featureChain = handle.getFeatures2KHR<vk::PhysicalDeviceFeatures2KHR, HPPStructureType>();

// Insert the extension feature into the extension feature map so its ownership is held
extension_features.insert({structureType, std::make_shared<HPPStructureType>(featureChain.template get<HPPStructureType>())});

// Pull out the dereferenced void pointer, we can assume its type based on the template
auto *extension_ptr = static_cast<HPPStructureType *>(extension_features.find(structureType)->second.get());
return *static_cast<HPPStructureType *>(it->second.get());
}

// If an extension feature has already been requested, we shift the linked list down by one
// Making this current extension the new base pointer
if (last_requested_extension_feature)
/**
* @brief Request an optional features flag
*
* Calls get_extension_features to get the support of the requested flag. If it's supported,
* add_extension_features is called, otherwise a log message is generated.
*
* @returns true if the requested feature is supported, otherwise false
*/
template <typename Feature>
vk::Bool32 request_optional_feature(vk::Bool32 Feature::*flag, std::string const &featureName, std::string const &flagName)
{
vk::Bool32 supported = get_extension_features<Feature>().*flag;
if (supported)
{
extension_ptr->pNext = last_requested_extension_feature;
add_extension_features<Feature>().*flag = true;
}
last_requested_extension_feature = extension_ptr;
else
{
LOGI("Requested optional feature <{}::{}> is not supported", featureName, flagName);
}
return supported;
}

return *extension_ptr;
/**
* @brief Request a required features flag
*
* Calls get_extension_features to get the support of the requested flag. If it's supported,
* add_extension_features is called, otherwise a runtime_error is thrown.
*/
template <typename Feature>
void request_required_feature(vk::Bool32 Feature::*flag, std::string const &featureName, std::string const &flagName)
{
if (get_extension_features<Feature>().*flag)
{
add_extension_features<Feature>().*flag = true;
}
else
{
throw std::runtime_error(std::string("Requested required feature <") + featureName + "::" + flagName + "> is not supported");
}
}

/**
Expand Down Expand Up @@ -192,5 +244,9 @@ class HPPPhysicalDevice

bool high_priority_graphics_queue{false};
};

#define HPP_REQUEST_OPTIONAL_FEATURE(gpu, Feature, flag) gpu.request_optional_feature<Feature>(&Feature::flag, #Feature, #flag)
#define HPP_REQUEST_REQUIRED_FEATURE(gpu, Feature, flag) gpu.request_required_feature<Feature>(&Feature::flag, #Feature, #flag)

} // namespace core
} // namespace vkb
114 changes: 87 additions & 27 deletions framework/core/physical_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ class PhysicalDevice

void enumerate_queue_family_performance_query_counters(
uint32_t queue_family_index,
uint32_t * count,
VkPerformanceCounterKHR * counters,
uint32_t *count,
VkPerformanceCounterKHR *counters,
VkPerformanceCounterDescriptionKHR *descriptions) const;

const VkPhysicalDeviceFeatures get_requested_features() const;
Expand All @@ -79,7 +79,35 @@ class PhysicalDevice
void *get_extension_feature_chain() const;

/**
* @brief Requests a third party extension to be used by the framework
* @brief Get an extension features struct
*
* Gets the actual extension features struct with the supported flags set.
* The flags you're interested in can be set in a corresponding struct in the structure chain
* by calling PhysicalDevice::add_extension_features()
* @param type The VkStructureType for the extension you are requesting
* @returns The extension feature struct
*/
template <typename T>
T get_extension_features(VkStructureType type)
{
// We cannot request extension features if the physical device properties 2 instance extension isn't enabled
if (!instance.is_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
throw std::runtime_error("Couldn't request feature from device as " + std::string(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) +
" isn't enabled!");
}

// Get the extension features
T features{type};
VkPhysicalDeviceFeatures2KHR physical_device_features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
physical_device_features.pNext = &features;
vkGetPhysicalDeviceFeatures2KHR(handle, &physical_device_features);

return features;
}

/**
* @brief Add an extension features struct to the structure chain used for device creation
*
* To have the features enabled, this function must be called before the logical device
* is created. To do this request sample specific features inside
Expand All @@ -89,45 +117,73 @@ class PhysicalDevice
* modify the struct returned by this function, it will propagate the changes to the logical
* device.
* @param type The VkStructureType for the extension you are requesting
* @returns The extension feature struct
* @returns A reference to extension feature struct in the structure chain
*/
template <typename T>
T &request_extension_features(VkStructureType type)
T &add_extension_features(VkStructureType type)
{
// We cannot request extension features if the physical device properties 2 instance extension isn't enabled
if (!instance.is_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
throw std::runtime_error("Couldn't request feature from device as " + std::string(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) + " isn't enabled!");
throw std::runtime_error("Couldn't request feature from device as " + std::string(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) +
" isn't enabled!");
}

// If the type already exists in the map, return a casted pointer to get the extension feature struct
auto extension_features_it = extension_features.find(type);
if (extension_features_it != extension_features.end())
// Add an (empty) extension features into the map of extension features
auto [it, added] = extension_features.insert({type, std::make_shared<T>(T{type})});
if (added)
{
return *static_cast<T *>(extension_features_it->second.get());
// if it was actually added, also add it to the structure chain
if (last_requested_extension_feature)
{
static_cast<T *>(it->second.get())->pNext = last_requested_extension_feature;
}
last_requested_extension_feature = it->second.get();
}

// Get the extension feature
VkPhysicalDeviceFeatures2KHR physical_device_features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
T extension{type};
physical_device_features.pNext = &extension;
vkGetPhysicalDeviceFeatures2KHR(handle, &physical_device_features);

// Insert the extension feature into the extension feature map so its ownership is held
extension_features.insert({type, std::make_shared<T>(extension)});

// Pull out the dereferenced void pointer, we can assume its type based on the template
auto *extension_ptr = static_cast<T *>(extension_features.find(type)->second.get());
return *static_cast<T *>(it->second.get());
}

// If an extension feature has already been requested, we shift the linked list down by one
// Making this current extension the new base pointer
if (last_requested_extension_feature)
/**
* @brief Request an optional features flag
*
* Calls get_extension_features to get the support of the requested flag. If it's supported,
* add_extension_features is called, otherwise a log message is generated.
*
* @returns true if the requested feature is supported, otherwise false
*/
template <typename Feature>
VkBool32 request_optional_feature(VkStructureType type, VkBool32 Feature::*flag, std::string const &featureName, std::string const &flagName)
{
VkBool32 supported = get_extension_features<Feature>(type).*flag;
if (supported)
{
extension_ptr->pNext = last_requested_extension_feature;
add_extension_features<Feature>(type).*flag = true;
}
last_requested_extension_feature = extension_ptr;
else
{
LOGI("Requested optional feature <{}::{}> is not supported", featureName, flagName);
}
return supported;
}

return *extension_ptr;
/**
* @brief Request a required features flag
*
* Calls get_extension_features to get the support of the requested flag. If it's supported,
* add_extension_features is called, otherwise a runtime_error is thrown.
*/
template <typename Feature>
void request_required_feature(VkStructureType type, VkBool32 Feature::*flag, std::string const &featureName, std::string const &flagName)
{
if (get_extension_features<Feature>(type).*flag)
{
add_extension_features<Feature>(type).*flag = true;
}
else
{
throw std::runtime_error(std::string("Requested required feature <") + featureName + "::" + flagName + "> is not supported");
}
}

/**
Expand Down Expand Up @@ -183,4 +239,8 @@ class PhysicalDevice

bool high_priority_graphics_queue{};
};

#define REQUEST_OPTIONAL_FEATURE(gpu, Feature, type, flag) gpu.request_optional_feature<Feature>(type, &Feature::flag, #Feature, #flag)
#define REQUEST_REQUIRED_FEATURE(gpu, Feature, type, flag) gpu.request_required_feature<Feature>(type, &Feature::flag, #Feature, #flag)

} // namespace vkb
3 changes: 1 addition & 2 deletions samples/api/hpp_timestamp_queries/hpp_timestamp_queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ bool HPPTimestampQueries::resize(const uint32_t width, const uint32_t height)
void HPPTimestampQueries::request_gpu_features(vkb::core::HPPPhysicalDevice &gpu)
{
// We need to enable the command pool reset feature in the extension struct
auto &requested_extension_features = gpu.request_extension_features<vk::PhysicalDeviceHostQueryResetFeaturesEXT>();
requested_extension_features.hostQueryReset = true;
HPP_REQUEST_REQUIRED_FEATURE(gpu, vk::PhysicalDeviceHostQueryResetFeaturesEXT, hostQueryReset);

// Enable anisotropic filtering if supported
if (gpu.get_features().samplerAnisotropy)
Expand Down
3 changes: 1 addition & 2 deletions samples/api/timestamp_queries/timestamp_queries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ TimestampQueries::~TimestampQueries()
void TimestampQueries::request_gpu_features(vkb::PhysicalDevice &gpu)
{
// We need to enable the command pool reset feature in the extension struct
auto &requested_extension_features = gpu.request_extension_features<VkPhysicalDeviceHostQueryResetFeaturesEXT>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT);
requested_extension_features.hostQueryReset = VK_TRUE;
REQUEST_REQUIRED_FEATURE(gpu, VkPhysicalDeviceHostQueryResetFeaturesEXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT, hostQueryReset);

// Enable anisotropic filtering if supported
if (gpu.get_features().samplerAnisotropy)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,10 @@ void BufferDeviceAddress::render(float delta_time)
void BufferDeviceAddress::request_gpu_features(vkb::PhysicalDevice &gpu)
{
// Need to enable the bufferDeviceAddress feature.
auto &features = gpu.request_extension_features<VkPhysicalDeviceBufferDeviceAddressFeaturesKHR>(
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR);
features.bufferDeviceAddress = VK_TRUE;
REQUEST_REQUIRED_FEATURE(gpu,
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR,
bufferDeviceAddress);
}

std::unique_ptr<vkb::VulkanSampleC> create_buffer_device_address()
Expand Down
11 changes: 6 additions & 5 deletions samples/extensions/color_write_enable/color_write_enable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,11 @@ void ColorWriteEnable::create_attachments()

void ColorWriteEnable::request_gpu_features(vkb::PhysicalDevice &gpu)
{
{
auto &features = gpu.request_extension_features<VkPhysicalDeviceColorWriteEnableFeaturesEXT>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT);
features.colorWriteEnable = VK_TRUE;
}
REQUEST_REQUIRED_FEATURE(gpu,
VkPhysicalDeviceColorWriteEnableFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT,
colorWriteEnable);

{
auto &features = gpu.get_mutable_requested_features();
features.independentBlend = VK_TRUE;
Expand Down Expand Up @@ -544,7 +545,7 @@ void ColorWriteEnable::on_update_ui_overlay(vkb::Drawer &drawer)
ImGuiColorEditFlags_NoSidePreview |
ImGuiColorEditFlags_NoSmallPreview |
ImGuiColorEditFlags_Float |
ImGuiColorEditFlags_HDR))
ImGuiColorEditFlags_HDR))
{
rebuild_command_buffers();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ ConditionalRendering::~ConditionalRendering()
void ConditionalRendering::request_gpu_features(vkb::PhysicalDevice &gpu)
{
// We need to enable conditional rendering using a new feature struct
auto &requested_extension_features = gpu.request_extension_features<VkPhysicalDeviceConditionalRenderingFeaturesEXT>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT);
requested_extension_features.conditionalRendering = VK_TRUE;
REQUEST_REQUIRED_FEATURE(gpu,
VkPhysicalDeviceConditionalRenderingFeaturesEXT,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT,
conditionalRendering);
}

void ConditionalRendering::build_command_buffers()
Expand Down
Loading
Loading