diff options
-rw-r--r-- | samples/amber.cc | 17 | ||||
-rw-r--r-- | samples/config_helper.cc | 3 | ||||
-rw-r--r-- | samples/config_helper.h | 2 | ||||
-rw-r--r-- | samples/config_helper_dawn.cc | 1 | ||||
-rw-r--r-- | samples/config_helper_dawn.h | 1 | ||||
-rw-r--r-- | samples/config_helper_vulkan.cc | 164 | ||||
-rw-r--r-- | samples/config_helper_vulkan.h | 11 |
7 files changed, 130 insertions, 69 deletions
diff --git a/samples/amber.cc b/samples/amber.cc index cb085c6..6e7af87 100644 --- a/samples/amber.cc +++ b/samples/amber.cc @@ -49,6 +49,7 @@ struct Options { uint32_t engine_major = 1; uint32_t engine_minor = 0; int32_t fence_timeout = -1; + int32_t selected_device = -1; bool parse_only = false; bool pipeline_create_only = false; bool disable_validation_layer = false; @@ -70,6 +71,7 @@ const char kUsage[] = R"(Usage: amber [options] SCRIPT [SCRIPTS...] -ps -- Parse input files, create pipelines; Don't execute. -q -- Disable summary output. -d -- Disable validation layers. + -D <ID> -- ID of device to run with (Vulkan only). -f <value> -- Sets the fence timeout value to |value| -t <spirv_env> -- The target SPIR-V environment e.g., spv1.3, vulkan1.1. If a SPIR-V environment, assume the lowest version of Vulkan that @@ -146,6 +148,20 @@ bool ParseArgs(const std::vector<std::string>& args, Options* opts) { << std::endl; return false; } + } else if (arg == "-D") { + ++i; + if (i >= args.size()) { + std::cerr << "Missing ID for -D argument." << std::endl; + return false; + } + + int32_t val = std::stoi(std::string(args[i])); + if (val < 0) { + std::cerr << "Device ID must be non-negative" << std::endl; + return false; + } + opts->selected_device = val; + } else if (arg == "-f") { ++i; if (i >= args.size()) { @@ -405,6 +421,7 @@ int main(int argc, const char** argv) { amber::Result r = config_helper.CreateConfig( amber_options.engine, options.engine_major, options.engine_minor, + options.selected_device, std::vector<std::string>(required_features.begin(), required_features.end()), std::vector<std::string>(required_instance_extensions.begin(), diff --git a/samples/config_helper.cc b/samples/config_helper.cc index a1a8016..4cceb85 100644 --- a/samples/config_helper.cc +++ b/samples/config_helper.cc @@ -40,6 +40,7 @@ amber::Result ConfigHelper::CreateConfig( amber::EngineType engine, uint32_t engine_major, uint32_t engine_minor, + int32_t selected_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_instance_extensions, const std::vector<std::string>& required_device_extensions, @@ -67,7 +68,7 @@ amber::Result ConfigHelper::CreateConfig( return amber::Result("Unable to create config helper"); return impl_->CreateConfig( - engine_major, engine_minor, required_features, + engine_major, engine_minor, selected_device, required_features, required_instance_extensions, required_device_extensions, disable_validation_layer, show_version_info, config); } diff --git a/samples/config_helper.h b/samples/config_helper.h index cc351d6..fbed9ef 100644 --- a/samples/config_helper.h +++ b/samples/config_helper.h @@ -35,6 +35,7 @@ class ConfigHelperImpl { virtual amber::Result CreateConfig( uint32_t engine_major, uint32_t engine_minor, + int32_t selected_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_instance_extensions, const std::vector<std::string>& required_device_extensions, @@ -58,6 +59,7 @@ class ConfigHelper { amber::EngineType engine, uint32_t engine_major, uint32_t engine_minor, + int32_t selected_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_instance_extensions, const std::vector<std::string>& required_device_extensions, diff --git a/samples/config_helper_dawn.cc b/samples/config_helper_dawn.cc index b160756..6fbb079 100644 --- a/samples/config_helper_dawn.cc +++ b/samples/config_helper_dawn.cc @@ -51,6 +51,7 @@ void PrintDeviceError(DawnErrorType errorType, const char* message, void*) { amber::Result ConfigHelperDawn::CreateConfig( uint32_t, uint32_t, + int32_t, const std::vector<std::string>&, const std::vector<std::string>&, const std::vector<std::string>&, diff --git a/samples/config_helper_dawn.h b/samples/config_helper_dawn.h index 1f0fdff..8e8c56c 100644 --- a/samples/config_helper_dawn.h +++ b/samples/config_helper_dawn.h @@ -39,6 +39,7 @@ class ConfigHelperDawn : public ConfigHelperImpl { amber::Result CreateConfig( uint32_t engine_major, uint32_t engine_minor, + int32_t selected_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_instance_extensions, const std::vector<std::string>& required_device_extensions, diff --git a/samples/config_helper_vulkan.cc b/samples/config_helper_vulkan.cc index 551fc12..9cc1c73 100644 --- a/samples/config_helper_vulkan.cc +++ b/samples/config_helper_vulkan.cc @@ -699,9 +699,85 @@ amber::Result ConfigHelperVulkan::CreateDebugReportCallback() { return {}; } -amber::Result ConfigHelperVulkan::ChooseVulkanPhysicalDevice( +amber::Result ConfigHelperVulkan::CheckVulkanPhysicalDeviceRequirements( + const VkPhysicalDevice physical_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_extensions) { + VkPhysicalDeviceFeatures required_vulkan_features = + VkPhysicalDeviceFeatures(); + + if (use_physical_device_features2_) { + VkPhysicalDeviceVariablePointerFeaturesKHR var_ptrs = + VkPhysicalDeviceVariablePointerFeaturesKHR(); + var_ptrs.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; + var_ptrs.pNext = nullptr; + + VkPhysicalDeviceFeatures2KHR features2 = VkPhysicalDeviceFeatures2KHR(); + features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + features2.pNext = &var_ptrs; + + auto vkGetPhysicalDeviceFeatures2KHR = + reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>( + vkGetInstanceProcAddr(vulkan_instance_, + "vkGetPhysicalDeviceFeatures2KHR")); + vkGetPhysicalDeviceFeatures2KHR(physical_device, &features2); + available_features_ = features2.features; + + std::vector<std::string> required_features1; + for (const auto& feature : required_features) { + // No dot means this is a features1 feature. + if (feature.find_first_of('.') == std::string::npos) { + required_features1.push_back(feature); + continue; + } + + if (feature == kVariablePointers && + var_ptrs.variablePointers != VK_TRUE) { + continue; + } + if (feature == kVariablePointersStorageBuffer && + var_ptrs.variablePointersStorageBuffer != VK_TRUE) { + continue; + } + } + + amber::Result r = + NamesToVulkanFeatures(required_features1, &required_vulkan_features); + if (!r.IsSuccess()) + return r; + + } else { + amber::Result r = + NamesToVulkanFeatures(required_features, &required_vulkan_features); + if (!r.IsSuccess()) + return r; + + vkGetPhysicalDeviceFeatures(physical_device, &available_features_); + } + if (!AreAllRequiredFeaturesSupported(available_features_, + required_vulkan_features)) { + return amber::Result("Device does not support all required features"); + } + + available_device_extensions_ = GetAvailableDeviceExtensions(physical_device); + if (!AreAllExtensionsSupported(available_device_extensions_, + required_extensions)) { + return amber::Result("Device does not support all required extensions"); + } + + vulkan_queue_family_index_ = ChooseQueueFamilyIndex(physical_device); + if (vulkan_queue_family_index_ == std::numeric_limits<uint32_t>::max()) { + return amber::Result("Device does not support required queue flags"); + } + + return {}; +} + +amber::Result ConfigHelperVulkan::ChooseVulkanPhysicalDevice( + const std::vector<std::string>& required_features, + const std::vector<std::string>& required_extensions, + const int32_t selected_device) { uint32_t count = 0; std::vector<VkPhysicalDevice> physical_devices; @@ -716,72 +792,24 @@ amber::Result ConfigHelperVulkan::ChooseVulkanPhysicalDevice( return amber::Result("Unable to enumerate physical devices"); } - VkPhysicalDeviceFeatures required_vulkan_features = - VkPhysicalDeviceFeatures(); - for (uint32_t i = 0; i < count; ++i) { - if (use_physical_device_features2_) { - VkPhysicalDeviceVariablePointerFeaturesKHR var_ptrs = - VkPhysicalDeviceVariablePointerFeaturesKHR(); - var_ptrs.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; - var_ptrs.pNext = nullptr; - - VkPhysicalDeviceFeatures2KHR features2 = VkPhysicalDeviceFeatures2KHR(); - features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; - features2.pNext = &var_ptrs; - - auto vkGetPhysicalDeviceFeatures2KHR = - reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>( - vkGetInstanceProcAddr(vulkan_instance_, - "vkGetPhysicalDeviceFeatures2KHR")); - vkGetPhysicalDeviceFeatures2KHR(physical_devices[i], &features2); - available_features_ = features2.features; - - std::vector<std::string> required_features1; - for (const auto& feature : required_features) { - // No dot means this is a features1 feature. - if (feature.find_first_of('.') == std::string::npos) { - required_features1.push_back(feature); - continue; - } - - if (feature == kVariablePointers && - var_ptrs.variablePointers != VK_TRUE) { - continue; - } - if (feature == kVariablePointersStorageBuffer && - var_ptrs.variablePointersStorageBuffer != VK_TRUE) { - continue; - } - } - - amber::Result r = - NamesToVulkanFeatures(required_features1, &required_vulkan_features); - if (!r.IsSuccess()) - return r; - - } else { - amber::Result r = - NamesToVulkanFeatures(required_features, &required_vulkan_features); - if (!r.IsSuccess()) - return r; - - vkGetPhysicalDeviceFeatures(physical_devices[i], &available_features_); - } - if (!AreAllRequiredFeaturesSupported(available_features_, - required_vulkan_features)) { - continue; - } - - available_device_extensions_ = - GetAvailableDeviceExtensions(physical_devices[i]); - if (!AreAllExtensionsSupported(available_device_extensions_, - required_extensions)) { - continue; + if (selected_device > -1) { + uint32_t deviceID = static_cast<uint32_t>(selected_device); + if (deviceID >= count) { + return amber::Result("Unable to find Vulkan device with ID " + + std::to_string(deviceID)); } - - vulkan_queue_family_index_ = ChooseQueueFamilyIndex(physical_devices[i]); - if (vulkan_queue_family_index_ != std::numeric_limits<uint32_t>::max()) { + amber::Result r = CheckVulkanPhysicalDeviceRequirements( + physical_devices[deviceID], required_features, required_extensions); + if (!r.IsSuccess()) + return r; + vulkan_physical_device_ = physical_devices[deviceID]; + return {}; + } else { + for (uint32_t i = 0; i < count; ++i) { + amber::Result r = CheckVulkanPhysicalDeviceRequirements( + physical_devices[i], required_features, required_extensions); + if (!r.IsSuccess()) + continue; vulkan_physical_device_ = physical_devices[i]; return {}; } @@ -909,6 +937,7 @@ void ConfigHelperVulkan::DumpPhysicalDeviceInfo() { amber::Result ConfigHelperVulkan::CreateConfig( uint32_t engine_major, uint32_t engine_minor, + int32_t selected_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_instance_extensions, const std::vector<std::string>& required_device_extensions, @@ -927,7 +956,8 @@ amber::Result ConfigHelperVulkan::CreateConfig( return r; } - r = ChooseVulkanPhysicalDevice(required_features, required_device_extensions); + r = ChooseVulkanPhysicalDevice(required_features, required_device_extensions, + selected_device); if (!r.IsSuccess()) return r; diff --git a/samples/config_helper_vulkan.h b/samples/config_helper_vulkan.h index d0d312d..6c19fbc 100644 --- a/samples/config_helper_vulkan.h +++ b/samples/config_helper_vulkan.h @@ -44,6 +44,7 @@ class ConfigHelperVulkan : public ConfigHelperImpl { amber::Result CreateConfig( uint32_t engine_major, uint32_t engine_minor, + int32_t selected_device, const std::vector<std::string>& required_features, const std::vector<std::string>& required_instance_extensions, const std::vector<std::string>& required_device_extensions, @@ -63,11 +64,19 @@ class ConfigHelperVulkan : public ConfigHelperImpl { /// via debugCallback() function in config_helper_vulkan.cc. amber::Result CreateDebugReportCallback(); + /// Check if |physical_device| supports both + /// |required_features| and |required_extensions|. + amber::Result CheckVulkanPhysicalDeviceRequirements( + const VkPhysicalDevice physical_device, + const std::vector<std::string>& required_features, + const std::vector<std::string>& required_extensions); + /// Choose Vulkan physical device that supports both /// |required_features| and |required_extensions|. amber::Result ChooseVulkanPhysicalDevice( const std::vector<std::string>& required_features, - const std::vector<std::string>& required_extensions); + const std::vector<std::string>& required_extensions, + const int32_t selected_device); /// Create Vulkan logical device that enables both /// |required_features| and |required_extensions|. |