Created physical device object
Contains helper functions for picking the most suitable device in a rust/java factory-like way Has cast operator for underlying vulkan object
This commit is contained in:
82
include/vulkan/basalt_physical_device.h
Normal file
82
include/vulkan/basalt_physical_device.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include "basalt_context.h"
|
||||
|
||||
namespace basalt
|
||||
{
|
||||
struct DeviceQueueFamilyIndicies
|
||||
{
|
||||
DeviceQueueFamilyIndicies(VkPhysicalDevice phys, VkSurfaceKHR surface);
|
||||
DeviceQueueFamilyIndicies(u32 graphics=-1, u32 present=-1, u32 compute=-1, u32 transfer=-1);
|
||||
|
||||
u32 graphics = -1;
|
||||
u32 present = -1;
|
||||
u32 compute = -1;
|
||||
u32 transfer = -1;
|
||||
};
|
||||
struct SwapchainSupportDetails
|
||||
{
|
||||
SwapchainSupportDetails();
|
||||
SwapchainSupportDetails(VkPhysicalDevice phy, VkSurfaceKHR surface);
|
||||
~SwapchainSupportDetails();
|
||||
|
||||
VkSurfaceFormatKHR get_surface_format(const std::initializer_list<VkSurfaceFormatKHR>& allowed_formats);
|
||||
VkPresentModeKHR get_present_mode(const std::initializer_list<VkPresentModeKHR>& allowed_present_modes);
|
||||
VkExtent2D get_framebuffer_extent(basalt::Window& window);
|
||||
|
||||
VkSurfaceCapabilitiesKHR surface_capabilities;
|
||||
basalt::darray<VkSurfaceFormatKHR> surface_formats;
|
||||
basalt::darray<VkPresentModeKHR> present_modes;
|
||||
VkSurfaceFormatKHR cached_format = {VK_FORMAT_MAX_ENUM, VK_COLOR_SPACE_MAX_ENUM_KHR};
|
||||
VkPresentModeKHR cached_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;
|
||||
};
|
||||
|
||||
class PhysicalDevice
|
||||
{
|
||||
public:
|
||||
PhysicalDevice(VkPhysicalDevice dev, const DeviceQueueFamilyIndicies& indicies, basalt::darray<const char*>&& enabled_extensions, VkSurfaceKHR surface);
|
||||
|
||||
operator VkPhysicalDevice() noexcept;
|
||||
|
||||
basalt::darray<const char*> enabled_extensions;
|
||||
DeviceQueueFamilyIndicies indicies;
|
||||
VkSurfaceKHR surface;
|
||||
VkPhysicalDevice phys;
|
||||
};
|
||||
|
||||
class PhysicalDeviceSelector
|
||||
{
|
||||
public:
|
||||
|
||||
PhysicalDeviceSelector(const PhysicalDeviceSelector& src);
|
||||
PhysicalDeviceSelector& operator =(const PhysicalDeviceSelector& src) = delete;
|
||||
PhysicalDeviceSelector(PhysicalDeviceSelector&& other);
|
||||
PhysicalDeviceSelector& operator =(PhysicalDeviceSelector&& other) = delete;
|
||||
|
||||
PhysicalDeviceSelector(basalt::Context& ctx, VkSurfaceKHR surface);
|
||||
~PhysicalDeviceSelector();
|
||||
|
||||
uint32_t num_devices(void);
|
||||
basalt::PhysicalDevice pick();
|
||||
|
||||
basalt::PhysicalDeviceSelector& prefer_types(const VkPhysicalDeviceType type, const float pv = 1.0f, const float nv = INFINITY);
|
||||
basalt::PhysicalDeviceSelector& prefer_features(const VkPhysicalDeviceFeatures req, const float pv = 1.0f, const float nv = INFINITY);
|
||||
basalt::PhysicalDeviceSelector& ensure_queues(const VkQueueFlagBits req_queues, const bool require_present, const float pv = 1.0f, const float nv = INFINITY);
|
||||
basalt::PhysicalDeviceSelector& prefer_extension (const char* extension, const float pv = 1.0f, const float nv=INFINITY);
|
||||
basalt::PhysicalDeviceSelector& prefer_extensions(const char** extensions, u32 num_extensions, const float pv = 1.0f, const float nv = INFINITY);
|
||||
basalt::PhysicalDeviceSelector& prefer_extensions(const basalt::darray<const char*>& extensions, const float pv = 1.0f, const float nv = INFINITY);
|
||||
|
||||
basalt::PhysicalDeviceSelector& ensure_swapchain(void);
|
||||
basalt::PhysicalDeviceSelector& prefer_surface_format(VkSurfaceFormatKHR format, const float pv = 1.0f, const float nv = INFINITY);
|
||||
basalt::PhysicalDeviceSelector& prefer_present_mode(VkPresentModeKHR present_mode, const float pv = 1.0f, const float nv = INFINITY);
|
||||
|
||||
basalt::darray<float> device_rankings;
|
||||
basalt::darray<VkPhysicalDevice> devices;
|
||||
basalt::darray<VkPhysicalDeviceProperties> props;
|
||||
basalt::darray<VkPhysicalDeviceFeatures> features;
|
||||
basalt::darray<SwapchainSupportDetails> support_details;
|
||||
basalt::darray<const char*> enabled_extensions;
|
||||
basalt::Context& ctx;
|
||||
VkSurfaceKHR surface;
|
||||
bool using_swapchain = false;
|
||||
};
|
||||
}
|
||||
418
src/vulkan/basalt_physical_device.cpp
Normal file
418
src/vulkan/basalt_physical_device.cpp
Normal file
@@ -0,0 +1,418 @@
|
||||
#include "vulkan/basalt_physical_device.h"
|
||||
|
||||
basalt::PhysicalDeviceSelector::PhysicalDeviceSelector(const PhysicalDeviceSelector& src) :
|
||||
ctx(src.ctx), device_rankings(src.device_rankings), devices(src.devices), props(src.props),
|
||||
features(src.features), enabled_extensions(src.enabled_extensions), support_details(src.support_details)
|
||||
{}
|
||||
|
||||
basalt::PhysicalDeviceSelector::PhysicalDeviceSelector(PhysicalDeviceSelector&& other) :
|
||||
ctx(other.ctx), device_rankings(std::move(other.device_rankings)), devices(std::move(other.devices)),
|
||||
props(std::move(other.props)), features(std::move(other.features)), enabled_extensions(std::move(other.enabled_extensions)),
|
||||
support_details(std::move(other.support_details))
|
||||
{}
|
||||
|
||||
basalt::PhysicalDeviceSelector::PhysicalDeviceSelector(basalt::Context& ctx, VkSurfaceKHR surface) :
|
||||
ctx(ctx),
|
||||
devices(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
props(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
features(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
device_rankings(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
enabled_extensions(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
support_details(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
surface(surface)
|
||||
{
|
||||
VkResult err = VK_SUCCESS;
|
||||
u32 n_devices;
|
||||
VK_ASSERT(vkEnumeratePhysicalDevices(ctx.inst, &n_devices, VK_NULL_HANDLE), "Failed to enumerate count of physical devices\n\tAt %s:%d\n\tError %s\n");
|
||||
this->devices.resize(n_devices);
|
||||
this->features.resize(n_devices);
|
||||
this->device_rankings.resize(n_devices);
|
||||
this->props.resize(n_devices);
|
||||
VK_ASSERT(vkEnumeratePhysicalDevices(ctx.inst, &n_devices, this->devices.m_pdata), "Failed to enumerate count of physical devices\n\tAt %s:%d\n\tError %s\n");
|
||||
for (u32 i = 0; i < n_devices; ++i)
|
||||
{
|
||||
vkGetPhysicalDeviceFeatures(this->devices[i], &this->features[i]);
|
||||
vkGetPhysicalDeviceProperties(this->devices[i], &this->props[i]);
|
||||
device_rankings[i] = 0.0f;
|
||||
}
|
||||
BTRACE("%s %p created\n", typeid(*this).name(), this);
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector::~PhysicalDeviceSelector()
|
||||
{
|
||||
BTRACE("%s %p destroyed\n", typeid(*this).name(), this);
|
||||
}
|
||||
|
||||
uint32_t basalt::PhysicalDeviceSelector::num_devices(void)
|
||||
{
|
||||
u32 cnt = 0;
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
cnt += this->device_rankings[i] != -INFINITY;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
basalt::PhysicalDevice basalt::PhysicalDeviceSelector::pick()
|
||||
{
|
||||
VkResult err = VK_SUCCESS;
|
||||
VkPhysicalDevice best = nullptr;
|
||||
float score = -INFINITY;
|
||||
u32 best_idx = -1;
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
if (this->device_rankings[i] > score)
|
||||
{
|
||||
best = this->devices[i];
|
||||
score = this->device_rankings[i];
|
||||
best_idx = i;
|
||||
}
|
||||
}
|
||||
BASSERT_FATAL(best != nullptr, "Assertion %s failed at %s:%d\n\tNo device matches all requirements specified\n");
|
||||
|
||||
|
||||
//BDEBUG("Chosen device %s supports the extensions;", this->props[best_idx].deviceName);
|
||||
//darray<VkExtensionProperties> ext_props(MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY);
|
||||
//u32 n = -1;
|
||||
//vkEnumerateDeviceExtensionProperties(best, nullptr, &n, nullptr);
|
||||
//ext_props.resize(n);
|
||||
//vkEnumerateDeviceExtensionProperties(best, nullptr, &n, ext_props.begin());
|
||||
|
||||
//for (const VkExtensionProperties& ext : ext_props)
|
||||
//{
|
||||
// BDEBUG("\t%s\n", ext.extensionName);
|
||||
//}
|
||||
|
||||
return basalt::PhysicalDevice(best, basalt::DeviceQueueFamilyIndicies(best, this->surface), std::move(this->enabled_extensions), this->surface);
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_types(const VkPhysicalDeviceType type, const float pv, const float nv)
|
||||
{
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
if (this->device_rankings[i] == -INFINITY)
|
||||
continue;
|
||||
if (this->props[i].deviceType & type)
|
||||
this->device_rankings[i] += pv;
|
||||
else
|
||||
this->device_rankings[i] -= nv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_features(const VkPhysicalDeviceFeatures req, const float pv, const float nv)
|
||||
{
|
||||
const VkBool32* u32_req = (VkBool32*)&req;
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
if (this->device_rankings[i] == -INFINITY)
|
||||
continue;
|
||||
const VkBool32* u32_avail = (VkBool32*)&this->features[i];
|
||||
for (size_t j = 0; j < sizeof(VkPhysicalDeviceProperties) / sizeof(VkBool32); ++j)
|
||||
{
|
||||
if (u32_req && u32_req == u32_avail)
|
||||
this->device_rankings[i] += pv;
|
||||
else if (u32_req)
|
||||
this->device_rankings[i] -= nv;
|
||||
|
||||
if (this->device_rankings[i] == -INFINITY)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::ensure_queues(const VkQueueFlagBits req_queues, const bool require_present, const float pv, const float nv)
|
||||
{
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
basalt::DeviceQueueFamilyIndicies indicies(this->devices[i], this->surface);
|
||||
if ((req_queues & VK_QUEUE_GRAPHICS_BIT) && (indicies.graphics != -1))
|
||||
this->device_rankings[i] += pv;
|
||||
else if (req_queues & VK_QUEUE_GRAPHICS_BIT)
|
||||
this->device_rankings[i] -= nv;
|
||||
if ((req_queues & VK_QUEUE_TRANSFER_BIT) && (indicies.transfer != -1))
|
||||
this->device_rankings[i] += pv;
|
||||
else if (req_queues & VK_QUEUE_TRANSFER_BIT)
|
||||
this->device_rankings[i] -= nv;
|
||||
if ((req_queues & VK_QUEUE_COMPUTE_BIT) && (indicies.compute != -1))
|
||||
this->device_rankings[i] += pv;
|
||||
else if (req_queues & VK_QUEUE_COMPUTE_BIT)
|
||||
this->device_rankings[i] -= nv;
|
||||
if (require_present && (indicies.present != -1))
|
||||
this->device_rankings[i] += pv;
|
||||
else if (require_present)
|
||||
this->device_rankings[i] -= nv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_extension(const char* extension, const float pv, const float nv)
|
||||
{
|
||||
u32 num_supported_extensions = 0;
|
||||
darray<VkExtensionProperties> exts(32, MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY);
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
vkEnumerateDeviceExtensionProperties(this->devices[i], nullptr, &num_supported_extensions, nullptr);
|
||||
exts.reserve(num_supported_extensions);
|
||||
vkEnumerateDeviceExtensionProperties(this->devices[i], nullptr, &num_supported_extensions, exts.m_pdata);
|
||||
exts.m_nelements = num_supported_extensions;
|
||||
|
||||
bool found = false;
|
||||
for (const VkExtensionProperties& prop : exts)
|
||||
{
|
||||
if (strcmp(prop.extensionName, extension) == 0)
|
||||
{
|
||||
this->device_rankings[i] += pv;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
this->device_rankings[i] -= nv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_extensions(const char** extensions, u32 num_extensions, const float pv, const float nv)
|
||||
{
|
||||
u32 num_supported_extensions = 0;
|
||||
darray<VkExtensionProperties> exts(32, MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY);
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
vkEnumerateDeviceExtensionProperties(this->devices[i], nullptr, &num_supported_extensions, nullptr);
|
||||
exts.reserve(num_supported_extensions);
|
||||
vkEnumerateDeviceExtensionProperties(this->devices[i], nullptr, &num_supported_extensions, exts.m_pdata);
|
||||
exts.m_nelements = num_supported_extensions;
|
||||
|
||||
for (u32 j = 0; j < num_extensions; ++j)
|
||||
{
|
||||
for (const VkExtensionProperties& prop : exts)
|
||||
{
|
||||
if (strcmp(prop.extensionName, extensions[j]) == 0)
|
||||
{
|
||||
this->device_rankings[i] += pv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->device_rankings[i] -= nv;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_extensions(const basalt::darray<const char*>& extensions, const float pv, const float nv)
|
||||
{
|
||||
u32 num_supported_extensions = 0;
|
||||
darray<VkExtensionProperties> exts(32, MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY);
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
vkEnumerateDeviceExtensionProperties(this->devices[i], nullptr, &num_supported_extensions, nullptr);
|
||||
exts.reserve(num_supported_extensions);
|
||||
vkEnumerateDeviceExtensionProperties(this->devices[i], nullptr, &num_supported_extensions, exts.m_pdata);
|
||||
exts.m_nelements = num_supported_extensions;
|
||||
|
||||
for (const char* extension : extensions)
|
||||
{
|
||||
for (const VkExtensionProperties& prop : exts)
|
||||
{
|
||||
if (strcmp(prop.extensionName, extension) == 0)
|
||||
{
|
||||
this->device_rankings[i] += pv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->device_rankings[i] -= nv;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::ensure_swapchain(void)
|
||||
{
|
||||
// Require the swapchain extension
|
||||
this->prefer_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
this->support_details.resize(this->devices.m_nelements);
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
if (this->device_rankings[i] == -INFINITY)
|
||||
{
|
||||
new (this->support_details.m_pdata + i) SwapchainSupportDetails();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure that the extension has present and surface modes
|
||||
new (this->support_details.m_pdata + i) SwapchainSupportDetails(this->devices[i], surface);
|
||||
if (this->support_details[i].present_modes.m_nelements == 0 ||
|
||||
this->support_details[i].surface_formats.m_nelements == 0)
|
||||
{
|
||||
this->device_rankings[i] = -INFINITY;
|
||||
}
|
||||
}
|
||||
using_swapchain = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_surface_format(VkSurfaceFormatKHR format, const float pv, const float nv)
|
||||
{
|
||||
BASSERT_FATAL(this->using_swapchain, "Assertion %s failed at %s:%d\n\t%s is not set up for checking swapchain surface format support\n\tCall ensure_swapchain() before this\n");
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
if (this->device_rankings[i] == -INFINITY)
|
||||
continue;
|
||||
bool found = false;
|
||||
for (const VkSurfaceFormatKHR& fmt : this->support_details[i].surface_formats)
|
||||
{
|
||||
if (fmt.colorSpace == format.colorSpace && fmt.format == format.format)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
this->device_rankings[i] += pv;
|
||||
else this->device_rankings[i] -= nv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basalt::PhysicalDeviceSelector& basalt::PhysicalDeviceSelector::prefer_present_mode(VkPresentModeKHR present_mode, const float pv, const float nv)
|
||||
{
|
||||
BASSERT_FATAL(this->using_swapchain, "Assertion %s failed at %s:%d\n\t%s is not set up for checking swapchain present mode support\n\tCall ensure_swapchain() before this\n");
|
||||
for (u32 i = 0; i < this->devices.m_nelements; ++i)
|
||||
{
|
||||
if (this->device_rankings[i] == -INFINITY)
|
||||
continue;
|
||||
bool found = false;
|
||||
for (const VkPresentModeKHR& mode : this->support_details[i].present_modes)
|
||||
{
|
||||
if (mode == present_mode)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
this->device_rankings[i] += pv;
|
||||
else this->device_rankings[i] -= nv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
basalt::DeviceQueueFamilyIndicies::DeviceQueueFamilyIndicies(VkPhysicalDevice phys, VkSurfaceKHR surface)
|
||||
{
|
||||
VkResult err = VK_SUCCESS;
|
||||
u32 num_queue_families = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(phys, &num_queue_families, VK_NULL_HANDLE);
|
||||
basalt::darray<VkQueueFamilyProperties> queue_families(num_queue_families,
|
||||
MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(phys, &num_queue_families, queue_families.m_pdata);
|
||||
queue_families.m_nelements = num_queue_families;
|
||||
|
||||
for (u32 i = 0; i < queue_families.m_nelements; ++i)
|
||||
{
|
||||
if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
this->graphics = i;
|
||||
if (queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT)
|
||||
this->transfer = i;
|
||||
if (queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||
this->compute = i;
|
||||
if (surface != VK_NULL_HANDLE)
|
||||
{
|
||||
VkBool32 present_supported = VK_FALSE;
|
||||
VK_ASSERT(vkGetPhysicalDeviceSurfaceSupportKHR(phys, i, surface, &present_supported), "Failed to determine if physical device queue supports presenting to surface\n\tAt %s:%d\n\tError %s\n");
|
||||
if (present_supported)
|
||||
this->present = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
basalt::DeviceQueueFamilyIndicies::DeviceQueueFamilyIndicies(u32 graphics, u32 present, u32 compute, u32 transfer) :
|
||||
graphics(graphics), present(present), compute(compute), transfer(transfer)
|
||||
{}
|
||||
|
||||
basalt::PhysicalDevice::PhysicalDevice(VkPhysicalDevice dev, const DeviceQueueFamilyIndicies& indicies, basalt::darray<const char*>&& enabled_extensions, VkSurfaceKHR surface) :
|
||||
phys(dev), indicies(indicies), enabled_extensions(std::move(enabled_extensions)), surface(surface)
|
||||
{ }
|
||||
|
||||
basalt::PhysicalDevice::operator VkPhysicalDevice() noexcept
|
||||
{ return this->phys; }
|
||||
|
||||
basalt::SwapchainSupportDetails::SwapchainSupportDetails() :
|
||||
surface_formats(MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_UNKNOWN | MEMORY_TAG_ALIGN_ANY),
|
||||
present_modes(MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_UNKNOWN | MEMORY_TAG_ALIGN_ANY)
|
||||
{}
|
||||
|
||||
basalt::SwapchainSupportDetails::SwapchainSupportDetails(VkPhysicalDevice phy, VkSurfaceKHR surface) :
|
||||
surface_formats(MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||
present_modes(MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY)
|
||||
{
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phy, surface, &this->surface_capabilities);
|
||||
u32 tmp = 0;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(phy, surface, &tmp, VK_NULL_HANDLE);
|
||||
this->surface_formats.resize(tmp);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(phy, surface, &tmp, this->surface_formats.begin());
|
||||
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surface, &tmp, VK_NULL_HANDLE);
|
||||
this->present_modes.resize(tmp);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(phy, surface, &tmp, this->present_modes.begin());
|
||||
BTRACE("Created %s (%p) with present modes at %p, and surface formats at %p\n", typeid(SwapchainSupportDetails).name(), this, this->present_modes.m_pdata, this->surface_formats.m_pdata);
|
||||
}
|
||||
|
||||
basalt::SwapchainSupportDetails::~SwapchainSupportDetails()
|
||||
{
|
||||
BTRACE("Destroyed %s (%p) with present modes at %p, and surface formats at %p\n", typeid(SwapchainSupportDetails).name(), this, this->present_modes.m_pdata, this->surface_formats.m_pdata);
|
||||
}
|
||||
|
||||
VkSurfaceFormatKHR basalt::SwapchainSupportDetails::get_surface_format(const std::initializer_list<VkSurfaceFormatKHR>& allowed_formats)
|
||||
{
|
||||
if (this->cached_format.colorSpace != VK_COLOR_SPACE_MAX_ENUM_KHR && this->cached_format.format != VK_FORMAT_MAX_ENUM)
|
||||
return this->cached_format;
|
||||
for (const VkSurfaceFormatKHR& prefered_fmt : allowed_formats)
|
||||
{
|
||||
for (const auto& available_fmt : surface_formats)
|
||||
{
|
||||
if (available_fmt.colorSpace == prefered_fmt.colorSpace && available_fmt.format == prefered_fmt.format)
|
||||
{
|
||||
this->cached_format = prefered_fmt;
|
||||
return prefered_fmt;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->cached_format = surface_formats[0];
|
||||
return surface_formats[0];
|
||||
}
|
||||
|
||||
VkPresentModeKHR basalt::SwapchainSupportDetails::get_present_mode(const std::initializer_list<VkPresentModeKHR>& allowed_present_modes)
|
||||
{
|
||||
if (this->cached_present_mode != VK_PRESENT_MODE_MAX_ENUM_KHR)
|
||||
return this->cached_present_mode;
|
||||
for (const VkPresentModeKHR& mode : present_modes)
|
||||
{
|
||||
for (const VkPresentModeKHR& pref_mode : allowed_present_modes)
|
||||
{
|
||||
if (mode == pref_mode)
|
||||
{
|
||||
this->cached_present_mode = pref_mode;
|
||||
return pref_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->cached_present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
|
||||
VkExtent2D basalt::SwapchainSupportDetails::get_framebuffer_extent(basalt::Window& window)
|
||||
{
|
||||
if (this->surface_capabilities.currentExtent.width != -1)
|
||||
return this->surface_capabilities.currentExtent;
|
||||
i32 width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
VkExtent2D ext = {
|
||||
.width = (u32)width,
|
||||
.height = (u32)height
|
||||
};
|
||||
BCLAMP_EXTENT(ext, this->surface_capabilities.minImageExtent, this->surface_capabilities.maxImageExtent);
|
||||
return ext;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user