Program Listing for File physicalDevice.cpp
↰ Return to documentation for file (PrismEngine/src/physicalDevice.cpp)
#include "physicalDevice.h"
#include "logger.h"
#include <map>
#include "deviceWrapper.h"
#include "deviceRater.h"
void prism::PGC::L1::PhysicalDevice::createImpl()
{
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(context->instance, &deviceCount, nullptr);
if (deviceCount == 0) {
logger::logError(logger::Error::VULKAN_NO_GPU_SUPPORT, __FUNCTION__);
}
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(context->instance, &deviceCount, devices.data());
std::multimap<int, VkPhysicalDevice> candidates;
L2::DeviceRater deviceRater(context, settings);
for (const auto& device : devices) {
int score = deviceRater.rate(device);
candidates.insert(std::make_pair(score, device));
}
// Check if the best candidate is suitable at all
if (candidates.rbegin()->first > 0) {
context->physicalDevice = candidates.rbegin()->second;
if (settings->defaultPipeline.multisample.rasterizationSamples)
context->msaaSamples = getMsaaSamples();
}
else {
logger::logError(logger::Error::VULKAN_NO_SUITABLE_GPU, __FUNCTION__);
}
// Вывод информации о выбранном устройстве
VkPhysicalDeviceProperties deviceProps = L3::DeviceWrapper::getDeviceProperties(context->physicalDevice);
logger::info("\n");
logger::info("Selected Vulkan device:");
logger::info(" - Name: " + std::string(deviceProps.deviceName));
std::string type;
switch (deviceProps.deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: type = "Integrated GPU"; break;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: type = "Discrete GPU"; break;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: type = "Virtual GPU"; break;
case VK_PHYSICAL_DEVICE_TYPE_CPU: type = "CPU"; break;
default: type = "Other"; break;
}
logger::info(" - Type: " + type);
logger::info(" - API Version: "
+ std::to_string(VK_VERSION_MAJOR(deviceProps.apiVersion)) + "."
+ std::to_string(VK_VERSION_MINOR(deviceProps.apiVersion)) + "."
+ std::to_string(VK_VERSION_PATCH(deviceProps.apiVersion)));
logger::info(" - Driver Version: " + std::to_string(deviceProps.driverVersion));
logger::info(" - Vendor ID: " + std::to_string(deviceProps.vendorID));
logger::info(" - Device ID: " + std::to_string(deviceProps.deviceID));
logger::info(" - Score: " + std::to_string(candidates.rbegin()->first) + "\n");
}
void prism::PGC::L1::PhysicalDevice::cleanupImpl()
{
}
VkSampleCountFlagBits prism::PGC::L1::PhysicalDevice::getMsaaSamples() {
VkSampleCountFlagBits maxCount = getMaxUsableSampleCount();
std::vector<VkSampleCountFlagBits> possibleCounts = getPossibleCounts(maxCount);
if (possibleCounts.empty()) {
return VK_SAMPLE_COUNT_1_BIT;
}
switch (settings->defaultPipeline.multisample.strategy) {
case utils::MultisampleSelectionStrategy::MINIMAL:
if (possibleCounts.size() >= 2) {
for (size_t i = 1; i < possibleCounts.size(); ++i) {
if (possibleCounts[i] != VK_SAMPLE_COUNT_1_BIT) {
return possibleCounts[i];
}
}
}
return possibleCounts[0];
case utils::MultisampleSelectionStrategy::MIDDLE:
if (possibleCounts.size() == 1) {
return possibleCounts[0];
}
return possibleCounts[possibleCounts.size() / 2];
case utils::MultisampleSelectionStrategy::MAXIMAL:
return possibleCounts.back();
case utils::MultisampleSelectionStrategy::CUSTOM:
for (VkSampleCountFlagBits possibleCount : possibleCounts) {
if (possibleCount == settings->defaultPipeline.multisample.rasterizationSamples) {
return possibleCount;
}
}
VkSampleCountFlagBits closest = possibleCounts[0];
int minDiff = std::abs(static_cast<int>(closest) - static_cast<int>(settings->defaultPipeline.multisample.rasterizationSamples));
for (size_t i = 1; i < possibleCounts.size(); ++i) {
int diff = std::abs(static_cast<int>(possibleCounts[i]) - static_cast<int>(settings->defaultPipeline.multisample.rasterizationSamples));
if (diff < minDiff) {
minDiff = diff;
closest = possibleCounts[i];
}
}
return closest;
return VK_SAMPLE_COUNT_1_BIT;
}
}
VkSampleCountFlagBits prism::PGC::L1::PhysicalDevice::getMaxUsableSampleCount()
{
VkPhysicalDeviceProperties physicalDeviceProperties;
vkGetPhysicalDeviceProperties(context->physicalDevice, &physicalDeviceProperties);
VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
return VK_SAMPLE_COUNT_1_BIT;
}
std::vector<VkSampleCountFlagBits> prism::PGC::L1::PhysicalDevice::getPossibleCounts(VkSampleCountFlagBits maxCount) {
std::vector<VkSampleCountFlagBits> counts = {
VK_SAMPLE_COUNT_1_BIT,
VK_SAMPLE_COUNT_2_BIT,
VK_SAMPLE_COUNT_4_BIT,
VK_SAMPLE_COUNT_8_BIT,
VK_SAMPLE_COUNT_16_BIT,
VK_SAMPLE_COUNT_32_BIT,
VK_SAMPLE_COUNT_64_BIT
};
std::vector<VkSampleCountFlagBits> possibleCounts;
for (VkSampleCountFlagBits count : counts)
{
if (count <= maxCount) {
possibleCounts.push_back(count);
}
else
{
break;
}
}
return possibleCounts;
}