Permalink
Browse files

Merge pull request #10075 from hrydgard/vulkan-device-detection

Vulkan device detection - prefer discrete GPUs
  • Loading branch information...
hrydgard committed Nov 9, 2017
2 parents ca3be18 + ba846fd commit 13e508e00b3e4c7404d8d1e5788895ff36339d90
View
@@ -36,4 +36,4 @@ class DummyGraphicsContext : public GraphicsContext {
void Resize() override {}
Draw::DrawContext *GetDrawContext() override { return nullptr; }
};
};
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "VulkanContext.h"
#include "GPU/Common/ShaderCommon.h"
#include "Common/StringUtils.h"
#ifdef USE_CRT_DBG
#undef new
@@ -50,6 +51,20 @@ static const char *validationLayers[] = {
*/
};
std::string VulkanVendorString(uint32_t vendorId) {
switch (vendorId) {
case VULKAN_VENDOR_INTEL: return "Intel";
case VULKAN_VENDOR_NVIDIA: return "nVidia";
case VULKAN_VENDOR_AMD: return "AMD";
case VULKAN_VENDOR_ARM: return "ARM";
case VULKAN_VENDOR_QUALCOMM: return "Qualcomm";
case VULKAN_VENDOR_IMGTEC: return "Imagination";
default:
return StringFromFormat("%08x", vendorId);
}
}
VulkanContext::VulkanContext() {
if (!VulkanLoad()) {
init_error_ = "Failed to load Vulkan driver library";
@@ -120,6 +135,11 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32
}
VulkanLoadInstanceFunctions(instance_);
if (!CheckLayers(instance_layer_properties_, instance_layer_names_)) {
WLOG("CheckLayers for instance failed");
// init_error_ = "Failed to validate instance layers";
// return;
}
uint32_t gpu_count = 1;
res = vkEnumeratePhysicalDevices(instance_, &gpu_count, nullptr);
@@ -141,11 +161,6 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32
return res;
}
if (!CheckLayers(instance_layer_properties_, instance_layer_names_)) {
WLOG("CheckLayers failed");
// init_error_ = "Failed to validate instance layers";
// return;
}
return VK_SUCCESS;
}
@@ -333,14 +348,47 @@ bool VulkanContext::CheckLayers(const std::vector<LayerProperties> &layer_props,
return true;
}
int VulkanContext::GetBestPhysicalDevice() {
// Rules: Prefer discrete over embedded.
// Prefer nVidia over Intel.
int maxScore = -1;
int best = -1;
for (size_t i = 0; i < physical_devices_.size(); i++) {
int score = 0;
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(physical_devices_[i], &props);
switch (props.deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_CPU:
score += 1;
break;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
score += 20;
break;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
score += 10;
break;
}
if (props.vendorID == VULKAN_VENDOR_AMD) {
score += 5;
} else if (props.vendorID == VULKAN_VENDOR_NVIDIA) {
score += 5;
}
if (score > maxScore) {
best = (int)i;
maxScore = score;
}
}
return best;
}
void VulkanContext::ChooseDevice(int physical_device) {
physical_device_ = physical_device;
GetDeviceLayerProperties();
if (!CheckLayers(device_layer_properties_, device_layer_names_)) {
WLOG("CheckLayers failed (2)");
// init_error_ = "Failed to validate device layers";
// return;
WLOG("CheckLayers for device %d failed", physical_device);
}
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices_[physical_device_], &queue_count, nullptr);
@@ -913,4 +961,4 @@ const char *VulkanResultToString(VkResult res) {
default:
return "VK_ERROR_...(unknown)";
}
}
}
@@ -43,6 +43,18 @@ enum {
VULKAN_FLAG_PRESENT_FIFO_RELAXED = 8,
};
enum {
VULKAN_VENDOR_NVIDIA = 0x000010de,
VULKAN_VENDOR_INTEL = 0x00008086, // Haha!
VULKAN_VENDOR_AMD = 0x00001002,
VULKAN_VENDOR_ARM = 0x000013B5, // Mali
VULKAN_VENDOR_QUALCOMM = 0x00005143,
VULKAN_VENDOR_IMGTEC = 0x00001010, // PowerVR
};
std::string VulkanVendorString(uint32_t vendorId);
struct VulkanPhysicalDeviceInfo {
VkFormat preferredDepthStencilFormat;
};
@@ -203,8 +215,7 @@ class VulkanContext {
VkResult CreateInstance(const char *app_name, int app_ver, uint32_t flags);
// TODO: Actually do some checks?
int GetBestPhysicalDevice() const { return 0; }
int GetBestPhysicalDevice();
void ChooseDevice(int physical_device);
bool EnableDeviceExtension(const char *extension);
VkResult CreateDevice();
View
@@ -30,8 +30,6 @@ android {
}
} else {
release {
// Can't build release builds without a key store.
println 'This build type should only be invoked from CI. Use Optimized builds instead.'
}
}
}
@@ -137,5 +135,5 @@ afterEvaluate {
android.sourceSets.main.assets.getSrcDirs().each { println it }
}
dependencies {
compile project(':com.bda.controller')
implementation project(':com.bda.controller')
}
@@ -290,7 +290,15 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
return false;
}
g_Vulkan->ChooseDevice(g_Vulkan->GetBestPhysicalDevice());
int physicalDevice = g_Vulkan->GetBestPhysicalDevice();
if (physicalDevice < 0) {
ELOG("No usable Vulkan device found.");
delete g_Vulkan;
g_Vulkan = nullptr;
return false;
}
g_Vulkan->ChooseDevice(physicalDevice);
// Here we can enable device extensions if we like.
ILOG("Creating vulkan device");
@@ -429,7 +429,7 @@ class VKContext : public DrawContext {
switch (info) {
case APINAME: return "Vulkan";
case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties().deviceName;
case VENDOR: return StringFromFormat("%08x", vulkan_->GetPhysicalDeviceProperties().vendorID);
case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties().vendorID);
case DRIVER: return StringFromFormat("%08x", vulkan_->GetPhysicalDeviceProperties().driverVersion);
case SHADELANGVERSION: return "N/A";;
case APIVERSION:

0 comments on commit 13e508e

Please sign in to comment.