mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-22 15:24:34 +00:00
Added a desired_api_version to InstanceBuilder and cleaned up the triangle example error handling.
Fixed several bugs in the PhysicalDeviceSelector code, causing erroneous failures.
This commit is contained in:
parent
1160b19a5c
commit
4c91df1c12
@ -44,7 +44,8 @@ int device_initialization (Init& init) {
|
||||
vkb::InstanceBuilder instance_builder;
|
||||
auto instance_ret = instance_builder.use_default_debug_messenger ().request_validation_layers ().build ();
|
||||
if (!instance_ret) {
|
||||
std::cout << static_cast<uint32_t> (instance_ret.error ().type) << "\n";
|
||||
std::cout << vkb::to_string (instance_ret.error ().type) << "\n";
|
||||
return -1;
|
||||
}
|
||||
init.instance = instance_ret.value ();
|
||||
|
||||
@ -53,14 +54,16 @@ int device_initialization (Init& init) {
|
||||
vkb::PhysicalDeviceSelector phys_device_selector (init.instance);
|
||||
auto phys_device_ret = phys_device_selector.set_surface (init.surface).select ();
|
||||
if (!phys_device_ret) {
|
||||
std::cout << static_cast<uint32_t> (phys_device_ret.error ().type) << "\n";
|
||||
std::cout << vkb::to_string (phys_device_ret.error ().type) << "\n";
|
||||
return -1;
|
||||
}
|
||||
vkb::PhysicalDevice physical_device = phys_device_ret.value ();
|
||||
|
||||
vkb::DeviceBuilder device_builder{ physical_device };
|
||||
auto device_ret = device_builder.build ();
|
||||
if (!device_ret) {
|
||||
std::cout << static_cast<uint32_t> (device_ret.error ().type) << "\n";
|
||||
std::cout << vkb::to_string (device_ret.error ().type) << "\n";
|
||||
return -1;
|
||||
}
|
||||
init.device = device_ret.value ();
|
||||
|
||||
@ -68,7 +71,8 @@ int device_initialization (Init& init) {
|
||||
auto swap_ret =
|
||||
swapchain_builder.use_default_format_selection ().use_default_present_mode_selection ().build ();
|
||||
if (!swap_ret) {
|
||||
std::cout << static_cast<uint32_t> (swap_ret.error ().type) << "\n";
|
||||
std::cout << vkb::to_string (swap_ret.error ().type) << "\n";
|
||||
return -1;
|
||||
}
|
||||
init.swapchain = swap_ret.value ();
|
||||
return 0;
|
||||
@ -77,14 +81,14 @@ int device_initialization (Init& init) {
|
||||
int get_queues (Init& init, RenderData& data) {
|
||||
auto gq = init.device.get_queue (vkb::QueueType::graphics);
|
||||
if (!gq.has_value ()) {
|
||||
std::cout << "failed to get graphics queue\n";
|
||||
std::cout << "failed to get graphics queue: " << vkb::to_string (gq.error ().type) << "\n";
|
||||
return -1;
|
||||
}
|
||||
data.graphics_queue = gq.value ();
|
||||
|
||||
auto pq = init.device.get_queue (vkb::QueueType::present);
|
||||
if (!pq.has_value ()) {
|
||||
std::cout << "failed to get present queue\n";
|
||||
std::cout << "failed to get present queue: " << vkb::to_string (gq.error ().type) << "\n";
|
||||
return -1;
|
||||
}
|
||||
data.present_queue = pq.value ();
|
||||
@ -129,6 +133,7 @@ int create_render_pass (Init& init, RenderData& data) {
|
||||
render_pass_info.pDependencies = &dependency;
|
||||
|
||||
if (vkCreateRenderPass (init.device.device, &render_pass_info, nullptr, &data.render_pass) != VK_SUCCESS) {
|
||||
std::cout << "failed to create render pass\n";
|
||||
return -1; // failed to create render pass!
|
||||
}
|
||||
return 0;
|
||||
@ -173,6 +178,7 @@ int create_graphics_pipeline (Init& init, RenderData& data) {
|
||||
VkShaderModule vert_module = createShaderModule (init, vert_code);
|
||||
VkShaderModule frag_module = createShaderModule (init, frag_code);
|
||||
if (vert_module == VK_NULL_HANDLE || frag_module == VK_NULL_HANDLE) {
|
||||
std::cout << "failed to create shader module\n";
|
||||
return -1; // failed to create shader modules
|
||||
}
|
||||
|
||||
@ -257,6 +263,7 @@ int create_graphics_pipeline (Init& init, RenderData& data) {
|
||||
|
||||
if (vkCreatePipelineLayout (
|
||||
init.device.device, &pipeline_layout_info, nullptr, &data.pipeline_layout) != VK_SUCCESS) {
|
||||
std::cout << "failed to create pipeline layout\n";
|
||||
return -1; // failed to create pipeline layout
|
||||
}
|
||||
|
||||
@ -277,6 +284,7 @@ int create_graphics_pipeline (Init& init, RenderData& data) {
|
||||
|
||||
if (vkCreateGraphicsPipelines (
|
||||
init.device.device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &data.graphics_pipeline) != VK_SUCCESS) {
|
||||
std::cout << "failed to create pipline\n";
|
||||
return -1; // failed to create graphics pipeline
|
||||
}
|
||||
|
||||
@ -318,6 +326,7 @@ int create_command_pool (Init& init, RenderData& data) {
|
||||
pool_info.queueFamilyIndex = init.device.get_queue_index (vkb::QueueType::graphics).value ();
|
||||
|
||||
if (vkCreateCommandPool (init.device.device, &pool_info, nullptr, &data.command_pool) != VK_SUCCESS) {
|
||||
std::cout << "failed to create command pool\n";
|
||||
return -1; // failed to create command pool
|
||||
}
|
||||
return 0;
|
||||
@ -364,6 +373,7 @@ int create_command_buffers (Init& init, RenderData& data) {
|
||||
vkCmdEndRenderPass (data.command_buffers[i]);
|
||||
|
||||
if (vkEndCommandBuffer (data.command_buffers[i]) != VK_SUCCESS) {
|
||||
std::cout << "failed to record command buffer\n";
|
||||
return -1; // failed to record command buffer!
|
||||
}
|
||||
}
|
||||
@ -387,6 +397,7 @@ int create_sync_objects (Init& init, RenderData& data) {
|
||||
if (vkCreateSemaphore (init.device.device, &semaphore_info, nullptr, &data.available_semaphores[i]) != VK_SUCCESS ||
|
||||
vkCreateSemaphore (init.device.device, &semaphore_info, nullptr, &data.finished_semaphore[i]) != VK_SUCCESS ||
|
||||
vkCreateFence (init.device.device, &fence_info, nullptr, &data.in_flight_fences[i]) != VK_SUCCESS) {
|
||||
std::cout << "failed to create sync objects\n";
|
||||
return -1; // failed to create synchronization objects for a frame
|
||||
}
|
||||
}
|
||||
@ -428,7 +439,8 @@ int draw_frame (Init& init, RenderData& data) {
|
||||
vkResetFences (init.device.device, 1, &data.in_flight_fences[data.current_frame]);
|
||||
|
||||
if (vkQueueSubmit (data.graphics_queue, 1, &submitInfo, data.in_flight_fences[data.current_frame]) != VK_SUCCESS) {
|
||||
return -1; //"failed to submit draw command buffer
|
||||
std::cout << "failed to submit draw command buffer\n";
|
||||
return -1; //"failed to submit draw command buffer
|
||||
}
|
||||
|
||||
VkPresentInfoKHR present_info = {};
|
||||
@ -481,20 +493,14 @@ int main () {
|
||||
Init init;
|
||||
RenderData render_data;
|
||||
|
||||
int res = 0;
|
||||
res = device_initialization (init);
|
||||
res = get_queues (init, render_data);
|
||||
res = create_render_pass (init, render_data);
|
||||
res = create_graphics_pipeline (init, render_data);
|
||||
res = create_framebuffers (init, render_data);
|
||||
res = create_command_pool (init, render_data);
|
||||
res = create_command_buffers (init, render_data);
|
||||
res = create_sync_objects (init, render_data);
|
||||
|
||||
if (res != 0) {
|
||||
std::cout << "failed to initialize vulkan\n";
|
||||
return -1;
|
||||
}
|
||||
if(0 != device_initialization (init)) return -1;
|
||||
if(0 != get_queues (init, render_data)) return -1;
|
||||
if(0 != create_render_pass (init, render_data)) return -1;
|
||||
if(0 != create_graphics_pipeline (init, render_data)) return -1;
|
||||
if(0 != create_framebuffers (init, render_data)) return -1;
|
||||
if(0 != create_command_pool (init, render_data)) return -1;
|
||||
if(0 != create_command_buffers (init, render_data)) return -1;
|
||||
if(0 != create_sync_objects (init, render_data)) return -1;
|
||||
|
||||
while (!glfwWindowShouldClose (init.window)) {
|
||||
glfwPollEvents ();
|
||||
|
@ -172,8 +172,14 @@ const char* validation_layer_name = "VK_LAYER_KHRONOS_validation";
|
||||
|
||||
const char* to_string (InstanceError err) {
|
||||
switch (err) {
|
||||
case InstanceError::unavailable_vulkan_version:
|
||||
return "unavailable_vulkan_version";
|
||||
case InstanceError::vulkan_unavailable:
|
||||
return "vulkan_unavailable";
|
||||
case InstanceError::vulkan_version_unavailable:
|
||||
return "vulkan_version_unavailable";
|
||||
case InstanceError::vulkan_version_1_1_unavailable:
|
||||
return "vulkan_version_1_1_unavailable";
|
||||
case InstanceError::vulkan_version_1_2_unavailable:
|
||||
return "vulkan_version_1_2_unavailable";
|
||||
case InstanceError::failed_create_debug_messenger:
|
||||
return "failed_create_debug_messenger";
|
||||
case InstanceError::failed_create_instance:
|
||||
@ -278,19 +284,38 @@ SystemInfo InstanceBuilder::get_system_info () const { return system; }
|
||||
|
||||
detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build () const {
|
||||
|
||||
if (VK_VERSION_MINOR (info.api_version) > 0) {
|
||||
uint32_t api_version = VK_MAKE_VERSION (1, 0, 0);
|
||||
|
||||
if (info.required_api_version > VK_MAKE_VERSION (1, 0, 0) || info.desired_api_version > VK_MAKE_VERSION (1, 0, 0)) {
|
||||
PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion;
|
||||
detail::get_inst_proc_addr (
|
||||
pfn_vkEnumerateInstanceVersion, "vkEnumerateInstanceVersion", nullptr, vkGetInstanceProcAddr);
|
||||
if (pfn_vkEnumerateInstanceVersion == nullptr) {
|
||||
return detail::Error<InstanceError>{ InstanceError::unavailable_vulkan_version };
|
||||
} else if (pfn_vkEnumerateInstanceVersion != nullptr) {
|
||||
uint32_t api_version = 0;
|
||||
pfn_vkEnumerateInstanceVersion (&api_version);
|
||||
if (VK_VERSION_MINOR (api_version) < VK_VERSION_MINOR (info.api_version))
|
||||
return detail::Error<InstanceError>{ InstanceError::unavailable_vulkan_version };
|
||||
|
||||
uint32_t queried_api_version = VK_MAKE_VERSION (1, 0, 0);
|
||||
if (pfn_vkEnumerateInstanceVersion != nullptr) {
|
||||
VkResult res = pfn_vkEnumerateInstanceVersion (&api_version);
|
||||
// Should always return VK_SUCCESS
|
||||
if (res != VK_SUCCESS && info.required_api_version > 0)
|
||||
return detail::Error<InstanceError>{ InstanceError::vulkan_version_unavailable };
|
||||
}
|
||||
if (pfn_vkEnumerateInstanceVersion == nullptr || queried_api_version < info.required_api_version) {
|
||||
if (VK_VERSION_MINOR (info.required_api_version) == 2)
|
||||
return detail::Error<InstanceError>{ InstanceError::vulkan_version_1_2_unavailable };
|
||||
else if (VK_VERSION_MINOR (info.required_api_version))
|
||||
return detail::Error<InstanceError>{ InstanceError::vulkan_version_1_1_unavailable };
|
||||
else
|
||||
return detail::Error<InstanceError>{ InstanceError::vulkan_version_unavailable };
|
||||
}
|
||||
if (info.required_api_version > VK_MAKE_VERSION (1, 0, 0)) {
|
||||
api_version = info.required_api_version;
|
||||
} else if (info.desired_api_version > VK_MAKE_VERSION (1, 0, 0)) {
|
||||
if (queried_api_version >= info.desired_api_version)
|
||||
api_version = info.desired_api_version;
|
||||
else
|
||||
api_version = queried_api_version;
|
||||
}
|
||||
}
|
||||
|
||||
VkApplicationInfo app_info = {};
|
||||
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
app_info.pNext = nullptr;
|
||||
@ -298,7 +323,7 @@ detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build
|
||||
app_info.applicationVersion = info.application_version;
|
||||
app_info.pEngineName = info.engine_name != nullptr ? info.engine_name : "";
|
||||
app_info.engineVersion = info.engine_version;
|
||||
app_info.apiVersion = info.api_version;
|
||||
app_info.apiVersion = api_version;
|
||||
|
||||
std::vector<const char*> extensions;
|
||||
for (auto& ext : info.extensions)
|
||||
@ -406,7 +431,7 @@ detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build
|
||||
instance.headless = true;
|
||||
}
|
||||
instance.allocation_callbacks = info.allocation_callbacks;
|
||||
instance.instance_version = info.api_version;
|
||||
instance.instance_version = api_version;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -429,7 +454,11 @@ InstanceBuilder& InstanceBuilder::set_engine_version (uint32_t major, uint32_t m
|
||||
return *this;
|
||||
}
|
||||
InstanceBuilder& InstanceBuilder::require_api_version (uint32_t major, uint32_t minor, uint32_t patch) {
|
||||
info.api_version = VK_MAKE_VERSION (major, minor, patch);
|
||||
info.required_api_version = VK_MAKE_VERSION (major, minor, patch);
|
||||
return *this;
|
||||
}
|
||||
InstanceBuilder& InstanceBuilder::desire_api_version (uint32_t major, uint32_t minor, uint32_t patch) {
|
||||
info.desired_api_version = VK_MAKE_VERSION (major, minor, patch);
|
||||
return *this;
|
||||
}
|
||||
InstanceBuilder& InstanceBuilder::enable_layer (const char* layer_name) {
|
||||
@ -674,24 +703,27 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi
|
||||
PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (PhysicalDeviceDesc pd) const {
|
||||
Suitable suitable = Suitable::yes;
|
||||
|
||||
if (criteria.required_version > pd.device_properties.apiVersion) return Suitable::no;
|
||||
if (criteria.desired_version > pd.device_properties.apiVersion) suitable = Suitable::partial;
|
||||
|
||||
bool dedicated_compute = detail::get_dedicated_compute_queue_index (pd.queue_families) >= 0;
|
||||
bool dedicated_transfer = detail::get_dedicated_transfer_queue_index (pd.queue_families) >= 0;
|
||||
bool separate_compute = detail::get_separate_compute_queue_index (pd.queue_families) >= 0;
|
||||
bool separate_transfer = detail::get_separate_transfer_queue_index (pd.queue_families) >= 0;
|
||||
|
||||
bool present_queue =
|
||||
detail::get_present_queue_index (pd.phys_device, system_info.surface, pd.queue_families);
|
||||
detail::get_present_queue_index (pd.phys_device, system_info.surface, pd.queue_families) >= 0;
|
||||
|
||||
if (criteria.require_dedicated_compute_queue && !dedicated_compute) suitable = Suitable::no;
|
||||
if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) suitable = Suitable::no;
|
||||
if (criteria.require_separate_compute_queue && !separate_compute) suitable = Suitable::no;
|
||||
if (criteria.require_separate_transfer_queue && !separate_transfer) suitable = Suitable::no;
|
||||
if (criteria.require_present && !present_queue) suitable = Suitable::no;
|
||||
if (criteria.require_dedicated_compute_queue && !dedicated_compute) return Suitable::no;
|
||||
if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) return Suitable::no;
|
||||
if (criteria.require_separate_compute_queue && !separate_compute) return Suitable::no;
|
||||
if (criteria.require_separate_transfer_queue && !separate_transfer) return Suitable::no;
|
||||
if (criteria.require_present && !present_queue) return Suitable::no;
|
||||
|
||||
auto required_extensions_supported =
|
||||
detail::check_device_extension_support (pd.phys_device, criteria.required_extensions);
|
||||
if (required_extensions_supported.size () != criteria.required_extensions.size ())
|
||||
suitable = Suitable::no;
|
||||
return Suitable::no;
|
||||
|
||||
auto desired_extensions_supported =
|
||||
detail::check_device_extension_support (pd.phys_device, criteria.desired_extensions);
|
||||
@ -713,21 +745,18 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (Phy
|
||||
swapChainAdequate = !formats.value ().empty () && !present_modes.value ().empty ();
|
||||
}
|
||||
}
|
||||
if (criteria.require_present && !swapChainAdequate) suitable = Suitable::no;
|
||||
if (criteria.require_present && !swapChainAdequate) return Suitable::no;
|
||||
|
||||
if (pd.device_properties.deviceType != static_cast<VkPhysicalDeviceType> (criteria.preferred_type)) {
|
||||
if (criteria.allow_any_type)
|
||||
suitable = Suitable::partial;
|
||||
else
|
||||
suitable = Suitable::no;
|
||||
return Suitable::no;
|
||||
}
|
||||
|
||||
if (criteria.required_version < pd.device_properties.apiVersion) suitable = Suitable::no;
|
||||
if (criteria.desired_version < pd.device_properties.apiVersion) suitable = Suitable::partial;
|
||||
|
||||
bool required_features_supported =
|
||||
detail::supports_features (pd.device_features, criteria.required_features);
|
||||
if (!required_features_supported) suitable = Suitable::no;
|
||||
if (!required_features_supported) return Suitable::no;
|
||||
|
||||
bool has_required_memory = false;
|
||||
bool has_preferred_memory = false;
|
||||
@ -741,7 +770,7 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (Phy
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!has_required_memory) suitable = Suitable::no;
|
||||
if (!has_required_memory) return Suitable::no;
|
||||
if (!has_preferred_memory) suitable = Suitable::partial;
|
||||
|
||||
return suitable;
|
||||
@ -752,6 +781,7 @@ PhysicalDeviceSelector::PhysicalDeviceSelector (Instance const& instance) {
|
||||
system_info.headless = instance.headless;
|
||||
criteria.require_present = !instance.headless;
|
||||
criteria.required_version = instance.instance_version;
|
||||
criteria.desired_version = instance.instance_version;
|
||||
}
|
||||
|
||||
detail::Expected<PhysicalDevice, detail::Error<PhysicalDeviceError>> PhysicalDeviceSelector::select () const {
|
||||
|
@ -98,7 +98,10 @@ template <typename E, typename U> class Expected {
|
||||
} // namespace detail
|
||||
|
||||
enum class InstanceError {
|
||||
unavailable_vulkan_version,
|
||||
vulkan_unavailable,
|
||||
vulkan_version_unavailable,
|
||||
vulkan_version_1_1_unavailable,
|
||||
vulkan_version_1_2_unavailable,
|
||||
failed_create_instance,
|
||||
failed_create_debug_messenger,
|
||||
requested_layers_not_present,
|
||||
@ -183,8 +186,10 @@ class InstanceBuilder {
|
||||
InstanceBuilder& set_app_version (uint32_t major, uint32_t minor, uint32_t patch);
|
||||
// Sets the (major, minor, patch) version of the engine.
|
||||
InstanceBuilder& set_engine_version (uint32_t major, uint32_t minor, uint32_t patch);
|
||||
// Require a minimum vulkan instance API version.
|
||||
// Require a vulkan instance API version. Will fail to create if this version isn't available.
|
||||
InstanceBuilder& require_api_version (uint32_t major, uint32_t minor, uint32_t patch);
|
||||
// Prefer a vulkan instance API version. If the desired version isn't available, it will use the highest version available.
|
||||
InstanceBuilder& desire_api_version (uint32_t major, uint32_t minor, uint32_t patch);
|
||||
|
||||
// Adds a layer to be enabled. Will fail to create an instance if the layer isn't available.
|
||||
InstanceBuilder& enable_layer (const char* layer_name);
|
||||
@ -234,7 +239,8 @@ class InstanceBuilder {
|
||||
const char* engine_name = nullptr;
|
||||
uint32_t application_version = 0;
|
||||
uint32_t engine_version = 0;
|
||||
uint32_t api_version = VK_MAKE_VERSION (1, 0, 0);
|
||||
uint32_t required_api_version = VK_MAKE_VERSION (1, 0, 0);
|
||||
uint32_t desired_api_version = VK_MAKE_VERSION (1, 0, 0);
|
||||
|
||||
// VkInstanceCreateInfo
|
||||
std::vector<const char*> layers;
|
||||
|
@ -90,10 +90,14 @@ int test_instance_headless () {
|
||||
}
|
||||
|
||||
int test_physical_device_selection () {
|
||||
printf ("\nphysical device selection\n");
|
||||
|
||||
printf ("\nphysical device selection\n");
|
||||
vkb::InstanceBuilder instance_builder;
|
||||
auto instance_ret = instance_builder.use_default_debug_messenger ().build ();
|
||||
if(!instance_ret.has_value()){
|
||||
printf("\n%s",vkb::to_string(instance_ret.error().type));
|
||||
return -1;
|
||||
}
|
||||
auto instance = instance_ret.value ();
|
||||
auto window = create_window_glfw ();
|
||||
auto surface = create_surface_glfw (instance.instance, window);
|
||||
@ -119,7 +123,7 @@ int test_device_creation () {
|
||||
vkb::InstanceBuilder instance_builder;
|
||||
auto instance_ret = instance_builder.use_default_debug_messenger ().build ();
|
||||
if (!instance_ret.has_value ()) {
|
||||
printf ("couldn't create instance %i\n", static_cast<uint32_t> (instance_ret.error ().type));
|
||||
printf ("couldn't create instance %s\n", vkb::to_string (instance_ret.error ().type));
|
||||
return -1;
|
||||
}
|
||||
auto instance = instance_ret.value ();
|
||||
@ -129,16 +133,16 @@ int test_device_creation () {
|
||||
|
||||
vkb::PhysicalDeviceSelector selector (instance);
|
||||
auto phys_dev_ret = selector.set_surface (surface).select ();
|
||||
auto phys_dev = phys_dev_ret.value ();
|
||||
if (!phys_dev_ret.has_value ()) {
|
||||
printf ("couldn't select device %i\n", static_cast<uint32_t> (phys_dev_ret.error ().type));
|
||||
printf ("couldn't select device %s\n", vkb::to_string (phys_dev_ret.error ().type));
|
||||
return -1;
|
||||
}
|
||||
auto phys_dev = phys_dev_ret.value ();
|
||||
|
||||
vkb::DeviceBuilder device_builder (phys_dev);
|
||||
auto dev_ret = device_builder.build ();
|
||||
if (!dev_ret.has_value ()) {
|
||||
printf ("couldn't create device %i\n", static_cast<uint32_t> (dev_ret.error ().type));
|
||||
printf ("couldn't create device %s\n", vkb::to_string (dev_ret.error ().type));
|
||||
return -1;
|
||||
}
|
||||
vkb::destroy_device (dev_ret.value ());
|
||||
|
Loading…
Reference in New Issue
Block a user