.. _program_listing_file_PrismEngine_src_deviceRater.cpp: Program Listing for File deviceRater.cpp ======================================== |exhale_lsh| :ref:`Return to documentation for file ` (``PrismEngine/src/deviceRater.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include #include #include "deviceRater.h" #include "base.h" #include "deviceWrapper.h" #include "deviceChecker.h" int prism::PGC::L2::DeviceRater::rate(VkPhysicalDevice device) { debugDeviceSelection = settings->debug.debugDeviceSelection; // Базовые проверки DeviceChecker deviceChecker(context, settings); if (!deviceChecker.check(device)) return 0; DeviceScore deviceScore; deviceScore.typeScore = (int)(getDeviceTypeScore(device) * settings->deviceEvaluationWeights.wType); deviceScore.featureScore = (int)(getDeviceFeatureScore(device) * settings->deviceEvaluationWeights.wFeatures); deviceScore.hardwareScore = (int)(getDeviceHardwareScore(device) * settings->deviceEvaluationWeights.wHardware); deviceScore.apiScore = (int)(getDeviceApiScore(device) * settings->deviceEvaluationWeights.wApi); if (debugDeviceSelection) { ScoreWrapper::print(deviceScore); } return ScoreWrapper::getTotal(deviceScore); } int prism::PGC::L2::DeviceRater::getDeviceTypeScore(VkPhysicalDevice device) { switch (prism::PGC::L3::DeviceWrapper::getDeviceProperties(device).deviceType) { case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return 100; case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return 70; case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return 40; case VK_PHYSICAL_DEVICE_TYPE_CPU: return 10; default: return 10; } } int prism::PGC::L2::DeviceRater::getDeviceFeatureScore(VkPhysicalDevice device) { FeatureScores features = calculateFeatureScore(device); // Учитываем вендора для RT и Upscaling VkPhysicalDeviceProperties props = L3::DeviceWrapper::getDeviceProperties(device);; if (props.vendorID == 0x10DE) { // NVIDIA features.raytracing *= 1.5f; if (features.upscaling > 0) features.upscaling += 5.0f; } if (debugDeviceSelection) { ScoreWrapper::print(features); } return static_cast(ScoreWrapper::getTotal(features)); } int prism::PGC::L2::DeviceRater::getDeviceHardwareScore(VkPhysicalDevice device) { HardwareScore score; VkPhysicalDeviceProperties props = L3::DeviceWrapper::getDeviceProperties(device); VkPhysicalDeviceMemoryProperties memProps = L3::DeviceWrapper::getDeviceMemoryProperties(device); // Константы для преобразования единиц constexpr float BYTES_TO_GB = 1.0f / (1024 * 1024 * 1024); constexpr float MHZ_TO_GHZ = 1.0f / 1000.0f; constexpr float TEXTURE_UNITS_NORMALIZER = 1.0f / 10000.0f; // Расчет VRAM for (uint32_t i = 0; i < memProps.memoryHeapCount; ++i) { if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { score.vramGB += static_cast(memProps.memoryHeaps[i].size) * BYTES_TO_GB; } } // показатели производительности score.shaderCores = std::log2(static_cast(props.limits.maxComputeWorkGroupInvocations) + 1.0f); if (props.limits.maxComputeWorkGroupSize[0] > 0) { score.clockSpeedGHz = static_cast(props.limits.maxComputeWorkGroupSize[0]) * MHZ_TO_GHZ; } else { score.clockSpeedGHz = 1.0f; } score.textureUnits = static_cast(props.limits.maxImageDimension2D) * TEXTURE_UNITS_NORMALIZER; if (debugDeviceSelection) { ScoreWrapper::print(score); } return ScoreWrapper::getTotal(score); } int prism::PGC::L2::DeviceRater::getDeviceApiScore(VkPhysicalDevice device) { const int BASE_SCORE_V1 = 30; const int V1_1_BONUS = 5; const int V1_2_BONUS = 15; const int V1_3_BONUS = 25; const int FEATURE_BONUS = 5; VkPhysicalDeviceProperties props = L3::DeviceWrapper::getDeviceProperties(device); int score = 0; uint32_t api_version = props.apiVersion; const int major = VK_VERSION_MAJOR(api_version); const int minor = VK_VERSION_MINOR(api_version); // Базовые баллы if (major >= 1) { score += BASE_SCORE_V1; // Vulkan 1.0+ // Бонусы за минорные версии через switch-case switch (minor) { case 3: score += V1_3_BONUS; break; // 1.3 case 2: score += V1_2_BONUS; break; // 1.2 case 1: score += V1_1_BONUS; break; // 1.1 case 0: break; // 1.0 - без бонусов default: // Для версий выше 1.3 if (minor > 3) score += V1_3_BONUS; break; } // Проверка фич Vulkan 1.2+ if (minor >= 2) { VkPhysicalDeviceVulkan12Features features12 = {}; features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; VkPhysicalDeviceFeatures2 features2 = {}; features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, features2.pNext = &features12; vkGetPhysicalDeviceFeatures2(device, &features2); if (features12.shaderFloat16) score += 5; if (features12.descriptorIndexing) score += 5; } } return score; } prism::PGC::L2::FeatureScores prism::PGC::L2::DeviceRater::calculateFeatureScore(VkPhysicalDevice device) { FeatureScores scores; std::vector extensions; L3::DeviceWrapper::getDeviceExtensionProperties(device, &extensions); std::unordered_set availableExtensions; for (const auto& ext : extensions) { availableExtensions.insert(ext.extensionName); } const std::string swapchainExt = "VK_KHR_swapchain"; if (availableExtensions.count(swapchainExt)) { scores.swapchain = 10.0f; } // Проверяем Ray Tracing const std::vector rtExtensions = { "VK_KHR_ray_tracing_pipeline", "VK_NV_ray_tracing" }; for (const auto& rtExt : rtExtensions) { if (availableExtensions.count(rtExt)) { scores.raytracing = 25.0f; break; } } // Проверяем Upscaling технологии const std::vector upscalingExtensions = { "VK_NV_DLSS", // NVIDIA DLSS "VK_KHR_fragment_shading_rate", // FSR/XeSS "VK_EXT_fragment_density_map" // Альтернативный механизм }; for (const auto& upExt : upscalingExtensions) { if (availableExtensions.count(upExt)) { scores.upscaling = upExt == "VK_NV_DLSS" ? 20.0f : 15.0f; break; } if (L3::DeviceWrapper::getDeviceProperties(device).apiVersion >= VK_MAKE_VERSION(1, 2, 0)) { scores.advancedFeatures += 5.0f; } } // Проверяем дополнительные возможности VkPhysicalDeviceFeatures2 features2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; vkGetPhysicalDeviceFeatures2(device, &features2); if (features2.features.tessellationShader) { scores.advancedFeatures += 5.0f; } if (features2.features.multiViewport) { scores.advancedFeatures += 3.0f; } return scores; } void prism::PGC::L2::ScoreWrapper::print(DeviceScore score) { logger::info("----------------Score----------------"); logger::info("Type: " + std::to_string(score.typeScore)); logger::info("Features: " + std::to_string(score.featureScore)); logger::info("Hardware: " + std::to_string(score.hardwareScore)); logger::info("API: " + std::to_string(score.apiScore)); logger::info("TOTAL: " + std::to_string(getTotal(score))); } void prism::PGC::L2::ScoreWrapper::print(FeatureScores score) { logger::info("----------------FeatureScore----------------"); logger::info("Swapchain: " + std::to_string(score.swapchain)); logger::info("Ray Tracing: " + std::to_string(score.raytracing)); logger::info("Upscaling: " + std::to_string(score.upscaling)); logger::info("Advanced Features: " + std::to_string(score.advancedFeatures)); logger::info("Total Features: " + std::to_string(getTotal(score))); } void prism::PGC::L2::ScoreWrapper::print(HardwareScore score) { logger::info("----------------HardwareScore----------------"); logger::info("VRAM (GB): " + std::to_string(score.vramGB)); logger::info("Shader Cores (log2): " + std::to_string(score.shaderCores)); logger::info("Clock Speed (GHz): " + std::to_string(score.clockSpeedGHz)); logger::info("Texture Units: " + std::to_string(score.textureUnits)); logger::info("Normalized Score: " + std::to_string(getTotal(score))); } int prism::PGC::L2::ScoreWrapper::getTotal(DeviceScore score) { return score.typeScore + score.featureScore + score.hardwareScore + score.apiScore; } int prism::PGC::L2::ScoreWrapper::getTotal(FeatureScores score) { return score.swapchain + score.raytracing + score.upscaling + score.advancedFeatures; } int prism::PGC::L2::ScoreWrapper::getTotal(HardwareScore score) { float normalizedVram = std::min(score.vramGB / score.REFERENCE_VRAM_GB, 1.0f); float normalizedShaderCores = std::min(score.shaderCores / score.REFERENCE_SHADER_CORES, 1.0f); float normalizedClockSpeed = std::min(score.clockSpeedGHz / score.REFERENCE_CLOCK_SPEED_GHZ, 1.0f); float total = normalizedVram * score.VRAM_WEIGHT + normalizedShaderCores * score.SHADER_CORES_WEIGHT + normalizedClockSpeed * score.CLOCK_SPEED_WEIGHT; return static_cast(std::clamp(total * 100.0f, 0.0f, 100.0f)); }