Skip to content
Snippets Groups Projects
Verified Commit 66213df6 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

[#101] Added feature manager to check active features and extensions

parent ab528a93
No related branches found
No related tags found
1 merge request!86Resolve "Device feature checks missing"
Pipeline #26589 passed
# adding all source files and header files of the framework:
set(vkcv_sources
${vkcv_include}/vkcv/FeatureManager.hpp
${vkcv_source}/vkcv/FeatureManager.cpp
${vkcv_include}/vkcv/Context.hpp
${vkcv_source}/vkcv/Context.cpp
......
......@@ -5,6 +5,7 @@
#include "QueueManager.hpp"
#include "DrawcallRecording.hpp"
#include "FeatureManager.hpp"
namespace vkcv
{
......@@ -32,6 +33,9 @@ namespace vkcv
[[nodiscard]]
const vk::Device &getDevice() const;
[[nodiscard]]
const FeatureManager& getFeatureManager() const;
[[nodiscard]]
const QueueManager& getQueueManager() const;
......@@ -53,11 +57,12 @@ namespace vkcv
* @param device Vulkan-Device
*/
Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device,
QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
FeatureManager&& featureManager, QueueManager&& queueManager, vma::Allocator&& allocator) noexcept;
vk::Instance m_Instance;
vk::PhysicalDevice m_PhysicalDevice;
vk::Device m_Device;
FeatureManager m_FeatureManager;
QueueManager m_QueueManager;
vma::Allocator m_Allocator;
......
#pragma once
#include "Logger.hpp"
#include <functional>
#include <unordered_set>
#include <vector>
#include <vulkan/vulkan.hpp>
namespace vkcv {
class FeatureManager {
private:
vk::PhysicalDevice& m_physicalDevice;
std::vector<const char*> m_supportedExtensions;
std::vector<const char*> m_activeExtensions;
vk::PhysicalDeviceFeatures2 m_featuresBase;
std::vector<vk::BaseOutStructure*> m_featuresExtensions;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDevice16BitStorageFeatures& features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDevice8BitStorageFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceBufferDeviceAddressFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceDescriptorIndexingFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceHostQueryResetFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceImagelessFramebufferFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceMultiviewFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceProtectedMemoryFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceSamplerYcbcrConversionFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceScalarBlockLayoutFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceSeparateDepthStencilLayoutsFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceShaderAtomicInt64Features &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceShaderFloat16Int8Features& features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceShaderSubgroupExtendedTypesFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceTimelineSemaphoreFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceUniformBufferStandardLayoutFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceVariablePointersFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceVulkanMemoryModelFeatures &features, bool required) const;
[[nodiscard]]
bool checkSupport(const vk::PhysicalDeviceMeshShaderFeaturesNV& features, bool required) const;
public:
explicit FeatureManager(vk::PhysicalDevice& physicalDevice);
FeatureManager(const FeatureManager& other) = delete;
FeatureManager(FeatureManager&& other) noexcept;
~FeatureManager();
FeatureManager& operator=(const FeatureManager& other) = delete;
FeatureManager& operator=(FeatureManager&& other) noexcept;
[[nodiscard]]
bool isExtensionSupported(const char *extension) const;
bool useExtension(const char *extension, bool required = true);
[[nodiscard]]
bool isExtensionActive(const char *extension) const;
[[nodiscard]]
const std::vector<const char*>& getActiveExtensions() const;
bool useFeatures(const std::function<void(vk::PhysicalDeviceFeatures&)>& featureFunction, bool required = true);
template<typename T>
bool useFeatures(const std::function<void(T&)>& featureFunction, bool required = true) {
T* features = new T();
featureFunction(*features);
if (!checkSupport(*features, required)) {
delete features;
return false;
}
if (m_featuresExtensions.empty()) {
m_featuresBase.setPNext(features);
} else {
m_featuresExtensions.back()->setPNext(
reinterpret_cast<vk::BaseOutStructure*>(features)
);
}
m_featuresExtensions.push_back(
reinterpret_cast<vk::BaseOutStructure*>(features)
);
return true;
}
[[nodiscard]]
const vk::PhysicalDeviceFeatures2& getFeatures() const;
};
}
......@@ -177,7 +177,7 @@ namespace vkcv::upscaling {
vkcv::shader::GLSLCompiler easuCompiler;
vkcv::shader::GLSLCompiler rcasCompiler;
const auto& features = m_core.getContext().getPhysicalDevice().getFeatures2();
const auto& features = m_core.getContext().getFeatureManager().getFeatures();
const bool float16Support = (
checkFeatures<vk::PhysicalDeviceFloat16Int8FeaturesKHR>(
reinterpret_cast<const vk::BaseInStructure*>(&features),
......@@ -189,7 +189,7 @@ namespace vkcv::upscaling {
vk::StructureType::ePhysicalDevice16BitStorageFeaturesKHR,
check16Storage
)
) || (true); // check doesn't work because chain is empty
);
if (!float16Support) {
easuCompiler.setDefine("SAMPLE_SLOW_FALLBACK", "1");
......
first_triangle
\ No newline at end of file
mesh_shader
\ No newline at end of file
......@@ -9,8 +9,9 @@ namespace vkcv
m_Instance(other.m_Instance),
m_PhysicalDevice(other.m_PhysicalDevice),
m_Device(other.m_Device),
m_QueueManager(other.m_QueueManager),
m_Allocator(other.m_Allocator)
m_FeatureManager(std::move(other.m_FeatureManager)),
m_QueueManager(std::move(other.m_QueueManager)),
m_Allocator(other.m_Allocator)
{
other.m_Instance = nullptr;
other.m_PhysicalDevice = nullptr;
......@@ -23,7 +24,8 @@ namespace vkcv
m_Instance = other.m_Instance;
m_PhysicalDevice = other.m_PhysicalDevice;
m_Device = other.m_Device;
m_QueueManager = other.m_QueueManager;
m_FeatureManager = std::move(other.m_FeatureManager);
m_QueueManager = std::move(other.m_QueueManager);
m_Allocator = other.m_Allocator;
other.m_Instance = nullptr;
......@@ -37,12 +39,14 @@ namespace vkcv
Context::Context(vk::Instance instance,
vk::PhysicalDevice physicalDevice,
vk::Device device,
FeatureManager&& featureManager,
QueueManager&& queueManager,
vma::Allocator&& allocator) noexcept :
m_Instance(instance),
m_PhysicalDevice(physicalDevice),
m_Device(device),
m_QueueManager(queueManager),
m_FeatureManager(std::move(featureManager)),
m_QueueManager(std::move(queueManager)),
m_Allocator(allocator)
{}
......@@ -68,6 +72,10 @@ namespace vkcv
return m_Device;
}
const FeatureManager& Context::getFeatureManager() const {
return m_FeatureManager;
}
const QueueManager& Context::getQueueManager() const {
return m_QueueManager;
}
......@@ -167,7 +175,6 @@ namespace vkcv
return true;
}
std::vector<const char*> getRequiredExtensions() {
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
......@@ -180,15 +187,6 @@ namespace vkcv
return extensions;
}
bool isPresentInCharPtrVector(const std::vector<const char*>& v, const char* term){
for (const auto& entry : v) {
if (strcmp(entry, term) != 0) {
return true;
}
}
return false;
}
Context Context::create(const char *applicationName,
uint32_t applicationVersion,
const std::vector<vk::QueueFlagBits>& queueFlags,
......@@ -226,14 +224,14 @@ namespace vkcv
supportedExtensions.push_back(elem.extensionName);
}
if (!checkSupport(supportedExtensions, instanceExtensions)) {
throw std::runtime_error("The requested instance extensions are not supported!");
}
// for GLFW: get all required extensions
std::vector<const char*> requiredExtensions = getRequiredExtensions();
requiredExtensions.insert(requiredExtensions.end(), instanceExtensions.begin(), instanceExtensions.end());
if (!checkSupport(supportedExtensions, requiredExtensions)) {
throw std::runtime_error("The requested instance extensions are not supported!");
}
const vk::ApplicationInfo applicationInfo(
applicationName,
applicationVersion,
......@@ -261,15 +259,7 @@ namespace vkcv
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance);
// check for physical device extension support
std::vector<vk::ExtensionProperties> deviceExtensionProperties = physicalDevice.enumerateDeviceExtensionProperties();
supportedExtensions.clear();
for (auto& elem : deviceExtensionProperties) {
supportedExtensions.push_back(elem.extensionName);
}
if (!checkSupport(supportedExtensions, deviceExtensions)) {
throw std::runtime_error("The requested device extensions are not supported by the physical device!");
}
FeatureManager featureManager (physicalDevice);
std::vector<vk::DeviceQueueCreateInfo> qCreateInfos;
......@@ -295,49 +285,41 @@ namespace vkcv
deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
#endif
const bool shaderFloat16 = checkSupport(deviceExtensions, { "VK_KHR_shader_float16_int8" });
const bool storage16bit = checkSupport(deviceExtensions, { "VK_KHR_16bit_storage" });
// FIXME: check if device feature is supported
vk::PhysicalDeviceShaderFloat16Int8Features deviceShaderFloat16Int8Features;
deviceShaderFloat16Int8Features.shaderFloat16 = shaderFloat16;
vk::PhysicalDevice16BitStorageFeatures device16BitStorageFeatures;
device16BitStorageFeatures.storageBuffer16BitAccess = storage16bit;
vk::PhysicalDeviceFeatures2 deviceFeatures2;
deviceFeatures2.features.fragmentStoresAndAtomics = true;
deviceFeatures2.features.geometryShader = true;
deviceFeatures2.features.depthClamp = true;
deviceFeatures2.features.shaderInt16 = true;
const bool usingMeshShaders = isPresentInCharPtrVector(deviceExtensions, VK_NV_MESH_SHADER_EXTENSION_NAME);
vk::PhysicalDeviceMeshShaderFeaturesNV meshShadingFeatures;
if (usingMeshShaders) {
meshShadingFeatures.taskShader = true;
meshShadingFeatures.meshShader = true;
deviceFeatures2.setPNext(&meshShadingFeatures);
if (featureManager.useExtension(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false)) {
featureManager.useFeatures<vk::PhysicalDeviceShaderFloat16Int8Features>(
[](vk::PhysicalDeviceShaderFloat16Int8Features& features) {
features.setShaderFloat16(true);
}, false);
}
if (shaderFloat16) {
deviceFeatures2.setPNext(&deviceShaderFloat16Int8Features);
if (featureManager.useExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, false)) {
featureManager.useFeatures<vk::PhysicalDevice16BitStorageFeatures>(
[](vk::PhysicalDevice16BitStorageFeatures& features) {
features.setStorageBuffer16BitAccess(true);
}, false);
}
if (storage16bit) {
deviceShaderFloat16Int8Features.setPNext(&device16BitStorageFeatures);
featureManager.useFeatures([](vk::PhysicalDeviceFeatures& features) {
features.setFragmentStoresAndAtomics(true);
features.setGeometryShader(true);
features.setDepthClamp(true);
features.setShaderInt16(true);
});
if (featureManager.useExtension(VK_NV_MESH_SHADER_EXTENSION_NAME, false)) {
featureManager.useFeatures<vk::PhysicalDeviceMeshShaderFeaturesNV>(
[](vk::PhysicalDeviceMeshShaderFeaturesNV& features) {
features.setTaskShader(true);
features.setMeshShader(true);
}, false);
}
deviceCreateInfo.setPNext(&deviceFeatures2);
// Ablauf
// qCreateInfos erstellen --> braucht das Device
// device erstellen
// jetzt koennen wir mit dem device die queues erstellen
deviceCreateInfo.setPNext(&(featureManager.getFeatures()));
vk::Device device = physicalDevice.createDevice(deviceCreateInfo);
if (usingMeshShaders)
{
if (featureManager.isExtensionActive(VK_NV_MESH_SHADER_EXTENSION_NAME)) {
InitMeshShaderDrawFunctions(device);
}
......@@ -376,6 +358,7 @@ namespace vkcv
instance,
physicalDevice,
device,
std::move(featureManager),
std::move(queueManager),
std::move(allocator)
);
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment