mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-22 15:24:34 +00:00
Finished basic rewrite of queue handling logic
Premise is to let the easy creation of a compute or transfer queue. If the user supplies a custom list they want to use, defer to that. Else, enable the basic requirements and be on your merry way.
This commit is contained in:
parent
3e7e283e3f
commit
2b711f30d5
@ -75,8 +75,18 @@ int device_initialization (Init& init) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get_queues (Init& init, RenderData& data) {
|
int get_queues (Init& init, RenderData& data) {
|
||||||
data.graphics_queue = vkb::get_graphics_queue (init.device).value ();
|
auto gq = vkb::get_graphics_queue (init.device);
|
||||||
data.present_queue = vkb::get_present_queue (init.device).value ();
|
if (!gq.has_value ()) {
|
||||||
|
std::cout << "failed to get graphics queue\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data.graphics_queue = gq.value ();
|
||||||
|
auto pq = vkb::get_present_queue (init.device);
|
||||||
|
if (!pq.has_value ()) {
|
||||||
|
std::cout << "failed to get present queue\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data.present_queue = pq.value ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +126,27 @@ bool check_layers_supported (std::vector<const char*> layer_names) {
|
|||||||
return all_found;
|
return all_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_extensions_supported (std::vector<const char*> extension_names) {
|
||||||
|
auto available_extensions =
|
||||||
|
detail::get_vector<VkExtensionProperties> (vkEnumerateInstanceExtensionProperties, nullptr);
|
||||||
|
if (!available_extensions.has_value ()) {
|
||||||
|
return false; // maybe report error?
|
||||||
|
}
|
||||||
|
bool all_found = true;
|
||||||
|
for (const auto& extension_name : extension_names) {
|
||||||
|
bool found = false;
|
||||||
|
for (const auto& layer_properties : available_extensions.value ()) {
|
||||||
|
if (strcmp (extension_name, layer_properties.extensionName) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) all_found = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_found;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void setup_pNext_chain (T& structure, std::vector<VkBaseOutStructure*>& structs) {
|
void setup_pNext_chain (T& structure, std::vector<VkBaseOutStructure*>& structs) {
|
||||||
structure.pNext = nullptr;
|
structure.pNext = nullptr;
|
||||||
@ -180,6 +201,11 @@ detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build
|
|||||||
extensions.push_back ("VK_KHR_metal_surface");
|
extensions.push_back ("VK_KHR_metal_surface");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
bool all_extensions_supported = detail::check_extensions_supported (extensions);
|
||||||
|
if (!all_extensions_supported) {
|
||||||
|
return detail::Error<InstanceError>{ InstanceError::requested_extensions_not_present };
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<const char*> layers;
|
std::vector<const char*> layers;
|
||||||
for (auto& layer : info.layers)
|
for (auto& layer : info.layers)
|
||||||
layers.push_back (layer.c_str ());
|
layers.push_back (layer.c_str ());
|
||||||
@ -499,33 +525,46 @@ int get_present_queue_index (VkPhysicalDevice const phys_device,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (VkPhysicalDevice phys_device) {
|
PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details (
|
||||||
Suitable suitable = Suitable::yes;
|
VkPhysicalDevice phys_device) {
|
||||||
|
PhysicalDeviceSelector::PhysicalDeviceDesc desc{};
|
||||||
|
desc.phys_device = phys_device;
|
||||||
auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> (
|
auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> (
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties, phys_device);
|
vkGetPhysicalDeviceQueueFamilyProperties, phys_device);
|
||||||
bool dedicated_compute = get_distinct_compute_queue_index (queue_families);
|
desc.queue_families = queue_families;
|
||||||
bool dedicated_transfer = get_distinct_transfer_queue_index (queue_families);
|
|
||||||
bool present_queue = get_present_queue_index (phys_device, info.surface, queue_families);
|
vkGetPhysicalDeviceProperties (phys_device, &desc.device_properties);
|
||||||
|
vkGetPhysicalDeviceFeatures (phys_device, &desc.device_features);
|
||||||
|
vkGetPhysicalDeviceMemoryProperties (phys_device, &desc.mem_properties);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (PhysicalDeviceDesc pd) {
|
||||||
|
Suitable suitable = Suitable::yes;
|
||||||
|
|
||||||
|
bool dedicated_compute = get_distinct_compute_queue_index (pd.queue_families);
|
||||||
|
bool dedicated_transfer = get_distinct_transfer_queue_index (pd.queue_families);
|
||||||
|
bool present_queue = get_present_queue_index (pd.phys_device, system_info.surface, pd.queue_families);
|
||||||
|
|
||||||
if (criteria.require_dedicated_compute_queue && !dedicated_compute) suitable = Suitable::no;
|
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_dedicated_transfer_queue && !dedicated_transfer) suitable = Suitable::no;
|
||||||
if (criteria.require_present && !present_queue) suitable = Suitable::no;
|
if (criteria.require_present && !present_queue) suitable = Suitable::no;
|
||||||
|
|
||||||
auto required_extensions_supported =
|
auto required_extensions_supported =
|
||||||
detail::check_device_extension_support (phys_device, criteria.required_extensions);
|
detail::check_device_extension_support (pd.phys_device, criteria.required_extensions);
|
||||||
if (required_extensions_supported.size () != criteria.required_extensions.size ())
|
if (required_extensions_supported.size () != criteria.required_extensions.size ())
|
||||||
suitable = Suitable::no;
|
suitable = Suitable::no;
|
||||||
|
|
||||||
auto desired_extensions_supported =
|
auto desired_extensions_supported =
|
||||||
detail::check_device_extension_support (phys_device, criteria.desired_extensions);
|
detail::check_device_extension_support (pd.phys_device, criteria.desired_extensions);
|
||||||
if (desired_extensions_supported.size () != criteria.desired_extensions.size ())
|
if (desired_extensions_supported.size () != criteria.desired_extensions.size ())
|
||||||
suitable = Suitable::partial;
|
suitable = Suitable::partial;
|
||||||
|
|
||||||
|
|
||||||
bool swapChainAdequate = false;
|
bool swapChainAdequate = false;
|
||||||
if (!info.headless) {
|
if (!system_info.headless) {
|
||||||
auto swapChainSupport_ret = detail::query_surface_support_details (phys_device, info.surface);
|
auto swapChainSupport_ret =
|
||||||
|
detail::query_surface_support_details (pd.phys_device, system_info.surface);
|
||||||
if (swapChainSupport_ret.has_value ()) {
|
if (swapChainSupport_ret.has_value ()) {
|
||||||
auto swapchain_support = swapChainSupport_ret.value ();
|
auto swapchain_support = swapChainSupport_ret.value ();
|
||||||
swapChainAdequate =
|
swapChainAdequate =
|
||||||
@ -534,17 +573,33 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (VkP
|
|||||||
}
|
}
|
||||||
if (criteria.require_present && !swapChainAdequate) suitable = Suitable::no;
|
if (criteria.require_present && !swapChainAdequate) suitable = Suitable::no;
|
||||||
|
|
||||||
VkPhysicalDeviceMemoryProperties mem_properties;
|
if ((criteria.preferred_type == PreferredDeviceType::discrete &&
|
||||||
vkGetPhysicalDeviceMemoryProperties (phys_device, &mem_properties);
|
pd.device_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) ||
|
||||||
|
(criteria.preferred_type == PreferredDeviceType::integrated &&
|
||||||
|
pd.device_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) ||
|
||||||
|
(criteria.preferred_type == PreferredDeviceType::virtual_gpu &&
|
||||||
|
pd.device_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)) {
|
||||||
|
if (criteria.allow_fallback)
|
||||||
|
suitable = Suitable::partial;
|
||||||
|
else
|
||||||
|
suitable = 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;
|
||||||
|
|
||||||
bool has_required_memory = false;
|
bool has_required_memory = false;
|
||||||
bool has_preferred_memory = false;
|
bool has_preferred_memory = false;
|
||||||
for (int i = 0; i < mem_properties.memoryHeapCount; i++) {
|
for (int i = 0; i < pd.mem_properties.memoryHeapCount; i++) {
|
||||||
if (mem_properties.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
|
if (pd.mem_properties.memoryHeaps[i].flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
|
||||||
if (mem_properties.memoryHeaps[i].size > criteria.required_mem_size) {
|
if (pd.mem_properties.memoryHeaps[i].size > criteria.required_mem_size) {
|
||||||
has_required_memory = true;
|
has_required_memory = true;
|
||||||
}
|
}
|
||||||
if (mem_properties.memoryHeaps[i].size > criteria.desired_mem_size) {
|
if (pd.mem_properties.memoryHeaps[i].size > criteria.desired_mem_size) {
|
||||||
has_preferred_memory = true;
|
has_preferred_memory = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,40 +607,18 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (VkP
|
|||||||
if (!has_required_memory) suitable = Suitable::no;
|
if (!has_required_memory) suitable = Suitable::no;
|
||||||
if (!has_preferred_memory) suitable = Suitable::partial;
|
if (!has_preferred_memory) suitable = Suitable::partial;
|
||||||
|
|
||||||
VkPhysicalDeviceProperties device_properties;
|
|
||||||
vkGetPhysicalDeviceProperties (phys_device, &device_properties);
|
|
||||||
if ((criteria.preferred_type == PreferredDeviceType::discrete &&
|
|
||||||
device_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) ||
|
|
||||||
(criteria.preferred_type == PreferredDeviceType::integrated &&
|
|
||||||
device_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) ||
|
|
||||||
(criteria.preferred_type == PreferredDeviceType::virtual_gpu &&
|
|
||||||
device_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)) {
|
|
||||||
if (criteria.allow_fallback)
|
|
||||||
suitable = Suitable::partial;
|
|
||||||
else
|
|
||||||
suitable = Suitable::no;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (criteria.required_version < device_properties.apiVersion) suitable = Suitable::no;
|
|
||||||
if (criteria.desired_version < device_properties.apiVersion) suitable = Suitable::partial;
|
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures supported_features{};
|
|
||||||
vkGetPhysicalDeviceFeatures (phys_device, &supported_features);
|
|
||||||
bool required_features_supported =
|
|
||||||
detail::supports_features (supported_features, criteria.required_features);
|
|
||||||
if (!required_features_supported) suitable = Suitable::no;
|
|
||||||
|
|
||||||
return suitable;
|
return suitable;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDeviceSelector::PhysicalDeviceSelector (Instance const& instance) {
|
PhysicalDeviceSelector::PhysicalDeviceSelector (Instance const& instance) {
|
||||||
info.instance = instance.instance;
|
system_info.instance = instance.instance;
|
||||||
info.headless = instance.headless;
|
system_info.headless = instance.headless;
|
||||||
criteria.require_present = !instance.headless;
|
criteria.require_present = !instance.headless;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::Expected<PhysicalDevice, detail::Error<PhysicalDeviceError>> PhysicalDeviceSelector::select () {
|
detail::Expected<PhysicalDevice, detail::Error<PhysicalDeviceError>> PhysicalDeviceSelector::select () {
|
||||||
auto physical_devices = detail::get_vector<VkPhysicalDevice> (vkEnumeratePhysicalDevices, info.instance);
|
auto physical_devices =
|
||||||
|
detail::get_vector<VkPhysicalDevice> (vkEnumeratePhysicalDevices, system_info.instance);
|
||||||
if (!physical_devices.has_value ()) {
|
if (!physical_devices.has_value ()) {
|
||||||
return detail::Error<PhysicalDeviceError>{ PhysicalDeviceError::failed_enumerate_physical_devices,
|
return detail::Error<PhysicalDeviceError>{ PhysicalDeviceError::failed_enumerate_physical_devices,
|
||||||
physical_devices.error () };
|
physical_devices.error () };
|
||||||
@ -594,42 +627,50 @@ detail::Expected<PhysicalDevice, detail::Error<PhysicalDeviceError>> PhysicalDev
|
|||||||
return detail::Error<PhysicalDeviceError>{ PhysicalDeviceError::no_physical_devices_found };
|
return detail::Error<PhysicalDeviceError>{ PhysicalDeviceError::no_physical_devices_found };
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDevice physical_device;
|
std::vector<PhysicalDeviceDesc> phys_device_descriptions;
|
||||||
|
for (auto& phys_device : physical_devices.value ()) {
|
||||||
|
phys_device_descriptions.push_back (populate_device_details (phys_device));
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceDesc selected_device{};
|
||||||
|
|
||||||
if (criteria.use_first_gpu_unconditionally) {
|
if (criteria.use_first_gpu_unconditionally) {
|
||||||
physical_device.phys_device = physical_devices.value ().at (0);
|
selected_device = phys_device_descriptions.at (0);
|
||||||
} else {
|
} else {
|
||||||
for (const auto& device : physical_devices.value ()) {
|
for (const auto& device : phys_device_descriptions) {
|
||||||
auto suitable = is_device_suitable (device);
|
auto suitable = is_device_suitable (device);
|
||||||
if (suitable == Suitable::yes) {
|
if (suitable == Suitable::yes) {
|
||||||
physical_device.phys_device = device;
|
selected_device = device;
|
||||||
break;
|
break;
|
||||||
} else if (suitable == Suitable::partial) {
|
} else if (suitable == Suitable::partial) {
|
||||||
physical_device.phys_device = device;
|
selected_device = device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (physical_device.phys_device == VK_NULL_HANDLE) {
|
if (selected_device.phys_device == VK_NULL_HANDLE) {
|
||||||
return detail::Error<PhysicalDeviceError>{ PhysicalDeviceError::no_suitable_device };
|
return detail::Error<PhysicalDeviceError>{ PhysicalDeviceError::no_suitable_device };
|
||||||
}
|
}
|
||||||
|
PhysicalDevice out_device{};
|
||||||
|
out_device.phys_device = selected_device.phys_device;
|
||||||
|
out_device.surface = system_info.surface;
|
||||||
|
out_device.features = criteria.required_features;
|
||||||
|
out_device.queue_families = selected_device.queue_families;
|
||||||
|
|
||||||
physical_device.surface = info.surface;
|
out_device.extensions_to_enable.insert (out_device.extensions_to_enable.end (),
|
||||||
physical_device.features = criteria.required_features;
|
|
||||||
|
|
||||||
physical_device.extensions_to_enable.insert (physical_device.extensions_to_enable.end (),
|
|
||||||
criteria.required_extensions.begin (),
|
criteria.required_extensions.begin (),
|
||||||
criteria.required_extensions.end ());
|
criteria.required_extensions.end ());
|
||||||
auto desired_extensions_supported =
|
auto desired_extensions_supported =
|
||||||
detail::check_device_extension_support (physical_device.phys_device, criteria.desired_extensions);
|
detail::check_device_extension_support (out_device.phys_device, criteria.desired_extensions);
|
||||||
physical_device.extensions_to_enable.insert (physical_device.extensions_to_enable.end (),
|
out_device.extensions_to_enable.insert (out_device.extensions_to_enable.end (),
|
||||||
desired_extensions_supported.begin (),
|
desired_extensions_supported.begin (),
|
||||||
desired_extensions_supported.end ());
|
desired_extensions_supported.end ());
|
||||||
return physical_device;
|
return out_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalDeviceSelector& PhysicalDeviceSelector::set_surface (VkSurfaceKHR surface) {
|
PhysicalDeviceSelector& PhysicalDeviceSelector::set_surface (VkSurfaceKHR surface) {
|
||||||
info.surface = surface;
|
system_info.surface = surface;
|
||||||
info.headless = false;
|
system_info.headless = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
PhysicalDeviceSelector& PhysicalDeviceSelector::prefer_gpu_device_type (PreferredDeviceType type) {
|
PhysicalDeviceSelector& PhysicalDeviceSelector::prefer_gpu_device_type (PreferredDeviceType type) {
|
||||||
@ -706,21 +747,41 @@ void destroy_device (Device device) { vkDestroyDevice (device.device, nullptr);
|
|||||||
DeviceBuilder::DeviceBuilder (PhysicalDevice phys_device) {
|
DeviceBuilder::DeviceBuilder (PhysicalDevice phys_device) {
|
||||||
info.physical_device = phys_device;
|
info.physical_device = phys_device;
|
||||||
info.extensions = phys_device.extensions_to_enable;
|
info.extensions = phys_device.extensions_to_enable;
|
||||||
|
info.queue_families = phys_device.queue_families;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::Expected<Device, detail::Error<DeviceError>> DeviceBuilder::build () {
|
detail::Expected<Device, detail::Error<DeviceError>> DeviceBuilder::build () {
|
||||||
|
|
||||||
auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> (
|
std::vector<CustomQueueDescription> queue_descriptions;
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties, info.physical_device.phys_device);
|
queue_descriptions.insert (
|
||||||
|
queue_descriptions.end (), info.queue_descriptions.begin (), info.queue_descriptions.end ());
|
||||||
|
|
||||||
|
if (queue_descriptions.size () == 0) {
|
||||||
|
int graphics = get_graphics_queue_index (info.queue_families);
|
||||||
|
if (graphics >= 0) {
|
||||||
|
queue_descriptions.push_back ({ static_cast<uint32_t> (graphics), 1, { 1.0f } });
|
||||||
|
}
|
||||||
|
if (info.request_compute_queue) {
|
||||||
|
int compute = get_distinct_compute_queue_index (info.queue_families);
|
||||||
|
if (compute >= 0) {
|
||||||
|
queue_descriptions.push_back ({ static_cast<uint32_t> (compute), 1, { 1.0f } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (info.request_transfer_queue) {
|
||||||
|
int transfer = get_distinct_transfer_queue_index (info.queue_families);
|
||||||
|
if (transfer >= 0) {
|
||||||
|
queue_descriptions.push_back ({ static_cast<uint32_t> (transfer), 1, { 1.0f } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||||
float priority = 1.0f;
|
for (auto& desc : queue_descriptions) {
|
||||||
for (int i = 0; i < queue_families.size (); i++) {
|
|
||||||
VkDeviceQueueCreateInfo queue_create_info = {};
|
VkDeviceQueueCreateInfo queue_create_info = {};
|
||||||
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
queue_create_info.queueFamilyIndex = static_cast<uint32_t> (i);
|
queue_create_info.queueFamilyIndex = desc.index;
|
||||||
queue_create_info.queueCount = 1;
|
queue_create_info.queueCount = desc.count;
|
||||||
queue_create_info.pQueuePriorities = &priority;
|
queue_create_info.pQueuePriorities = desc.priorities.data ();
|
||||||
queueCreateInfos.push_back (queue_create_info);
|
queueCreateInfos.push_back (queue_create_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,6 +809,7 @@ detail::Expected<Device, detail::Error<DeviceError>> DeviceBuilder::build () {
|
|||||||
}
|
}
|
||||||
device.physical_device = info.physical_device;
|
device.physical_device = info.physical_device;
|
||||||
device.surface = info.physical_device.surface;
|
device.surface = info.physical_device.surface;
|
||||||
|
device.queue_families = info.queue_families;
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,6 +818,20 @@ template <typename T> DeviceBuilder& DeviceBuilder::add_pNext (T* structure) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceBuilder& DeviceBuilder::request_dedicated_compute_queue (bool compute) {
|
||||||
|
info.request_compute_queue = compute;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
DeviceBuilder& DeviceBuilder::request_dedicated_transfer_queue (bool transfer) {
|
||||||
|
info.request_transfer_queue = transfer;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
DeviceBuilder& DeviceBuilder::custom_queue_setup (std::vector<CustomQueueDescription> queue_descriptions) {
|
||||||
|
info.queue_descriptions = queue_descriptions;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---- Getting Queues ---- //
|
// ---- Getting Queues ---- //
|
||||||
|
|
||||||
detail::Expected<uint32_t, detail::Error<QueueError>> get_present_queue_index (Device const& device) {
|
detail::Expected<uint32_t, detail::Error<QueueError>> get_present_queue_index (Device const& device) {
|
||||||
|
@ -124,6 +124,8 @@ struct Instance {
|
|||||||
|
|
||||||
void destroy_instance (Instance instance); // release instance resources
|
void destroy_instance (Instance instance); // release instance resources
|
||||||
|
|
||||||
|
// TODO utility function for users to check if layer/extension is supported
|
||||||
|
|
||||||
class InstanceBuilder {
|
class InstanceBuilder {
|
||||||
public:
|
public:
|
||||||
detail::Expected<Instance, detail::Error<InstanceError>> build (); // use builder pattern
|
detail::Expected<Instance, detail::Error<InstanceError>> build (); // use builder pattern
|
||||||
@ -138,9 +140,14 @@ class InstanceBuilder {
|
|||||||
InstanceBuilder& add_layer (std::string app_name);
|
InstanceBuilder& add_layer (std::string app_name);
|
||||||
InstanceBuilder& add_extension (std::string app_name);
|
InstanceBuilder& add_extension (std::string app_name);
|
||||||
|
|
||||||
|
bool check_and_add_layer (std::string app_name);
|
||||||
|
bool check_and_add_extension (std::string app_name);
|
||||||
|
|
||||||
InstanceBuilder& setup_validation_layers (bool enable_validation = true);
|
InstanceBuilder& setup_validation_layers (bool enable_validation = true);
|
||||||
InstanceBuilder& set_headless (bool headless = false);
|
InstanceBuilder& set_headless (bool headless = false);
|
||||||
|
|
||||||
|
bool check_and_setup_validation_layers (bool enable_validation = true);
|
||||||
|
|
||||||
InstanceBuilder& set_default_debug_messenger ();
|
InstanceBuilder& set_default_debug_messenger ();
|
||||||
InstanceBuilder& set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback);
|
InstanceBuilder& set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback);
|
||||||
InstanceBuilder& set_debug_messenger_severity (VkDebugUtilsMessageSeverityFlagsEXT severity);
|
InstanceBuilder& set_debug_messenger_severity (VkDebugUtilsMessageSeverityFlagsEXT severity);
|
||||||
@ -222,6 +229,7 @@ struct PhysicalDevice {
|
|||||||
private:
|
private:
|
||||||
VkPhysicalDeviceFeatures features{};
|
VkPhysicalDeviceFeatures features{};
|
||||||
std::vector<std::string> extensions_to_enable;
|
std::vector<std::string> extensions_to_enable;
|
||||||
|
std::vector<VkQueueFamilyProperties> queue_families;
|
||||||
friend class PhysicalDeviceSelector;
|
friend class PhysicalDeviceSelector;
|
||||||
friend class DeviceBuilder;
|
friend class DeviceBuilder;
|
||||||
};
|
};
|
||||||
@ -259,11 +267,21 @@ struct PhysicalDeviceSelector {
|
|||||||
PhysicalDeviceSelector& select_first_device_unconditionally (bool unconditionally = true);
|
PhysicalDeviceSelector& select_first_device_unconditionally (bool unconditionally = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PhysicalDeviceInfo {
|
struct SystemInfo {
|
||||||
VkInstance instance = VK_NULL_HANDLE;
|
VkInstance instance = VK_NULL_HANDLE;
|
||||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||||
bool headless = false;
|
bool headless = false;
|
||||||
} info;
|
} system_info;
|
||||||
|
|
||||||
|
struct PhysicalDeviceDesc {
|
||||||
|
VkPhysicalDevice phys_device = VK_NULL_HANDLE;
|
||||||
|
std::vector<VkQueueFamilyProperties> queue_families;
|
||||||
|
|
||||||
|
VkPhysicalDeviceFeatures device_features;
|
||||||
|
VkPhysicalDeviceProperties device_properties;
|
||||||
|
VkPhysicalDeviceMemoryProperties mem_properties;
|
||||||
|
};
|
||||||
|
PhysicalDeviceDesc populate_device_details (VkPhysicalDevice phys_device);
|
||||||
|
|
||||||
struct SelectionCriteria {
|
struct SelectionCriteria {
|
||||||
PreferredDeviceType preferred_type = PreferredDeviceType::discrete;
|
PreferredDeviceType preferred_type = PreferredDeviceType::discrete;
|
||||||
@ -287,13 +305,9 @@ struct PhysicalDeviceSelector {
|
|||||||
|
|
||||||
enum class Suitable { yes, partial, no };
|
enum class Suitable { yes, partial, no };
|
||||||
|
|
||||||
Suitable is_device_suitable (VkPhysicalDevice phys_device);
|
Suitable is_device_suitable (PhysicalDeviceDesc phys_device);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- Queue Selection ---- //
|
|
||||||
|
|
||||||
enum class QueueType : uint8_t { primary, compute, transfer };
|
|
||||||
|
|
||||||
// ---- Device ---- //
|
// ---- Device ---- //
|
||||||
enum class DeviceError {
|
enum class DeviceError {
|
||||||
failed_create_device,
|
failed_create_device,
|
||||||
@ -308,6 +322,12 @@ struct Device {
|
|||||||
|
|
||||||
void destroy_device (Device device);
|
void destroy_device (Device device);
|
||||||
|
|
||||||
|
struct CustomQueueDescription {
|
||||||
|
uint32_t index;
|
||||||
|
uint32_t count;
|
||||||
|
std::vector<float> priorities;
|
||||||
|
};
|
||||||
|
|
||||||
class DeviceBuilder {
|
class DeviceBuilder {
|
||||||
public:
|
public:
|
||||||
DeviceBuilder (PhysicalDevice device);
|
DeviceBuilder (PhysicalDevice device);
|
||||||
@ -315,12 +335,22 @@ class DeviceBuilder {
|
|||||||
|
|
||||||
template <typename T> DeviceBuilder& add_pNext (T* structure);
|
template <typename T> DeviceBuilder& add_pNext (T* structure);
|
||||||
|
|
||||||
|
DeviceBuilder& request_dedicated_compute_queue (bool compute = true);
|
||||||
|
DeviceBuilder& request_dedicated_transfer_queue (bool transfer = true);
|
||||||
|
|
||||||
|
/* For advanced users */
|
||||||
|
DeviceBuilder& custom_queue_setup (std::vector<CustomQueueDescription> queue_descriptions);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct DeviceInfo {
|
struct DeviceInfo {
|
||||||
VkDeviceCreateFlags flags = 0;
|
VkDeviceCreateFlags flags = 0;
|
||||||
std::vector<VkBaseOutStructure*> pNext_chain;
|
std::vector<VkBaseOutStructure*> pNext_chain;
|
||||||
PhysicalDevice physical_device;
|
PhysicalDevice physical_device;
|
||||||
std::vector<std::string> extensions;
|
std::vector<std::string> extensions;
|
||||||
|
std::vector<VkQueueFamilyProperties> queue_families;
|
||||||
|
std::vector<CustomQueueDescription> queue_descriptions;
|
||||||
|
bool request_compute_queue = true;
|
||||||
|
bool request_transfer_queue = true;
|
||||||
} info;
|
} info;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -381,9 +411,6 @@ class SwapchainBuilder {
|
|||||||
detail::Expected<Swapchain, detail::Error<SwapchainError>> build ();
|
detail::Expected<Swapchain, detail::Error<SwapchainError>> build ();
|
||||||
detail::Expected<Swapchain, detail::Error<SwapchainError>> recreate (Swapchain const& swapchain);
|
detail::Expected<Swapchain, detail::Error<SwapchainError>> recreate (Swapchain const& swapchain);
|
||||||
|
|
||||||
// SwapchainBuilder& set_desired_image_count (uint32_t count);
|
|
||||||
// SwapchainBuilder& set_maximum_image_count (uint32_t count);
|
|
||||||
|
|
||||||
SwapchainBuilder& set_desired_format (VkSurfaceFormatKHR format);
|
SwapchainBuilder& set_desired_format (VkSurfaceFormatKHR format);
|
||||||
SwapchainBuilder& add_fallback_format (VkSurfaceFormatKHR format);
|
SwapchainBuilder& add_fallback_format (VkSurfaceFormatKHR format);
|
||||||
SwapchainBuilder& use_default_format_selection ();
|
SwapchainBuilder& use_default_format_selection ();
|
||||||
|
Loading…
Reference in New Issue
Block a user