Vulkan: Extract Vendor/Driver/Device Information #107872
|
@ -26,29 +26,53 @@
|
|||
|
||||
namespace blender::gpu {
|
||||
|
||||
void VKBackend::init_platform()
|
||||
static eGPUOSType determine_os_type()
|
||||
{
|
||||
BLI_assert(!GPG.initialized);
|
||||
#ifdef _WIN32
|
||||
return GPU_OS_WIN;
|
||||
#elif defined(__APPLE__)
|
||||
return GPU_OS_MAC;
|
||||
#else
|
||||
return GPU_OS_UNIX;
|
||||
#endif
|
||||
}
|
||||
|
||||
eGPUDeviceType device = GPU_DEVICE_ANY;
|
||||
eGPUOSType os = GPU_OS_ANY;
|
||||
void VKBackend::platform_init()
|
||||
{
|
||||
GPG.init(GPU_DEVICE_ANY,
|
||||
determine_os_type(),
|
||||
GPU_DRIVER_ANY,
|
||||
GPU_SUPPORT_LEVEL_SUPPORTED,
|
||||
GPU_BACKEND_VULKAN,
|
||||
"",
|
||||
"",
|
||||
"");
|
||||
}
|
||||
|
||||
void VKBackend::platform_init(const VKDevice &device)
|
||||
{
|
||||
const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
|
||||
|
||||
eGPUDeviceType device_type = device.device_type();
|
||||
eGPUOSType os = determine_os_type();
|
||||
eGPUDriverType driver = GPU_DRIVER_ANY;
|
||||
eGPUSupportLevel support_level = GPU_SUPPORT_LEVEL_SUPPORTED;
|
||||
|
||||
#ifdef _WIN32
|
||||
os = GPU_OS_WIN;
|
||||
#elif defined(__APPLE__)
|
||||
os = GPU_OS_MAC;
|
||||
#else
|
||||
os = GPU_OS_UNIX;
|
||||
#endif
|
||||
std::string vendor_name = device.vendor_name();
|
||||
std::string driver_version = device.driver_version();
|
||||
|
||||
GPG.init(device, os, driver, support_level, GPU_BACKEND_VULKAN, "", "", "");
|
||||
GPG.init(device_type,
|
||||
os,
|
||||
driver,
|
||||
support_level,
|
||||
GPU_BACKEND_VULKAN,
|
||||
vendor_name.c_str(),
|
||||
properties.deviceName,
|
||||
driver_version.c_str());
|
||||
}
|
||||
|
||||
void VKBackend::platform_exit()
|
||||
{
|
||||
BLI_assert(GPG.initialized);
|
||||
GPG.clear();
|
||||
}
|
||||
|
||||
|
@ -147,10 +171,10 @@ shaderc::Compiler &VKBackend::get_shaderc_compiler()
|
|||
return shaderc_compiler_;
|
||||
}
|
||||
|
||||
void VKBackend::capabilities_init()
|
||||
void VKBackend::capabilities_init(const VKDevice &device)
|
||||
{
|
||||
const VkPhysicalDeviceLimits &limits =
|
||||
VKBackend::get().device_get().physical_device_limits_get();
|
||||
const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
|
||||
const VkPhysicalDeviceLimits &limits = properties.limits;
|
||||
|
||||
/* Reset all capabilities from previous context. */
|
||||
GCaps = {};
|
||||
|
|
|
@ -36,7 +36,7 @@ class VKBackend : public GPUBackend {
|
|||
public:
|
||||
VKBackend()
|
||||
{
|
||||
VKBackend::init_platform();
|
||||
platform_init();
|
||||
}
|
||||
|
||||
virtual ~VKBackend()
|
||||
|
@ -76,8 +76,6 @@ class VKBackend : public GPUBackend {
|
|||
|
||||
shaderc::Compiler &get_shaderc_compiler();
|
||||
|
||||
static void capabilities_init();
|
||||
|
||||
static VKBackend &get()
|
||||
{
|
||||
return *static_cast<VKBackend *>(GPUBackend::get());
|
||||
|
@ -88,8 +86,11 @@ class VKBackend : public GPUBackend {
|
|||
return device_;
|
||||
}
|
||||
|
||||
static void platform_init(const VKDevice &device);
|
||||
static void capabilities_init(const VKDevice &device);
|
||||
|
||||
private:
|
||||
static void init_platform();
|
||||
static void platform_init();
|
||||
static void platform_exit();
|
||||
|
||||
/* These classes are allowed to modify the global device. */
|
||||
|
|
|
@ -24,7 +24,7 @@ void VKDevice::deinit()
|
|||
vk_device_ = VK_NULL_HANDLE;
|
||||
vk_queue_family_ = 0;
|
||||
vk_queue_ = VK_NULL_HANDLE;
|
||||
vk_physical_device_limits_ = {};
|
||||
vk_physical_device_properties_ = {};
|
||||
}
|
||||
|
||||
bool VKDevice::is_initialized() const
|
||||
|
@ -42,8 +42,9 @@ void VKDevice::init(void *ghost_context)
|
|||
&vk_queue_family_,
|
||||
&vk_queue_);
|
||||
|
||||
init_physical_device_limits();
|
||||
init_capabilities();
|
||||
init_physical_device_properties();
|
||||
VKBackend::platform_init(*this);
|
||||
VKBackend::capabilities_init(*this);
|
||||
init_debug_callbacks();
|
||||
init_memory_allocator();
|
||||
init_descriptor_pools();
|
||||
|
@ -57,17 +58,10 @@ void VKDevice::init_debug_callbacks()
|
|||
debugging_tools_.init(vk_instance_);
|
||||
}
|
||||
|
||||
void VKDevice::init_physical_device_limits()
|
||||
void VKDevice::init_physical_device_properties()
|
||||
{
|
||||
BLI_assert(vk_physical_device_ != VK_NULL_HANDLE);
|
||||
VkPhysicalDeviceProperties properties = {};
|
||||
vkGetPhysicalDeviceProperties(vk_physical_device_, &properties);
|
||||
vk_physical_device_limits_ = properties.limits;
|
||||
}
|
||||
|
||||
void VKDevice::init_capabilities()
|
||||
{
|
||||
VKBackend::capabilities_init();
|
||||
vkGetPhysicalDeviceProperties(vk_physical_device_, &vk_physical_device_properties_);
|
||||
}
|
||||
|
||||
void VKDevice::init_memory_allocator()
|
||||
|
@ -87,4 +81,98 @@ void VKDevice::init_descriptor_pools()
|
|||
descriptor_pools_.init(vk_device_);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Platform/driver/device information
|
||||
* \{ */
|
||||
|
||||
constexpr int32_t PCI_ID_NVIDIA = 0x10de;
|
||||
constexpr int32_t PCI_ID_INTEL = 0x8086;
|
||||
constexpr int32_t PCI_ID_AMD = 0x1022;
|
||||
|
||||
eGPUDeviceType VKDevice::device_type() const
|
||||
{
|
||||
/* According to the vulkan specifications:
|
||||
*
|
||||
* If the vendor has a PCI vendor ID, the low 16 bits of vendorID must contain that PCI vendor
|
||||
* ID, and the remaining bits must be set to zero. Otherwise, the value returned must be a valid
|
||||
* Khronos vendor ID.
|
||||
*/
|
||||
switch (vk_physical_device_properties_.vendorID) {
|
||||
case PCI_ID_NVIDIA:
|
||||
return GPU_DEVICE_NVIDIA;
|
||||
case PCI_ID_INTEL:
|
||||
return GPU_DEVICE_INTEL;
|
||||
case PCI_ID_AMD:
|
||||
return GPU_DEVICE_ATI;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GPU_DEVICE_UNKNOWN;
|
||||
}
|
||||
|
||||
eGPUDriverType VKDevice::driver_type() const
|
||||
{
|
||||
/* It is unclear how to determine the driver type, but it is required to extract the correct
|
||||
* driver version. */
|
||||
return GPU_DRIVER_ANY;
|
||||
}
|
||||
|
||||
std::string VKDevice::vendor_name() const
|
||||
{
|
||||
/* Below 0x10000 are the PCI vendor IDs (https://pcisig.com/membership/member-companies) */
|
||||
if (vk_physical_device_properties_.vendorID < 0x10000) {
|
||||
switch (vk_physical_device_properties_.vendorID) {
|
||||
case 0x1022:
|
||||
return "Advanced Micro Devices";
|
||||
case 0x10DE:
|
||||
return "NVIDIA Corporation";
|
||||
case 0x8086:
|
||||
return "Intel Corporation";
|
||||
default:
|
||||
return std::to_string(vk_physical_device_properties_.vendorID);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* above 0x10000 should be vkVendorIDs
|
||||
* NOTE: When debug_messaging landed we can use something similar to
|
||||
* vk::to_string(vk::VendorId(properties.vendorID));
|
||||
*/
|
||||
return std::to_string(vk_physical_device_properties_.vendorID);
|
||||
}
|
||||
}
|
||||
|
||||
std::string VKDevice::driver_version() const
|
||||
{
|
||||
/*
|
||||
* NOTE: this depends on the driver type and is currently incorrect. Idea is to use a default per
|
||||
* OS.
|
||||
*/
|
||||
const uint32_t driver_version = vk_physical_device_properties_.driverVersion;
|
||||
switch (vk_physical_device_properties_.vendorID) {
|
||||
case PCI_ID_NVIDIA:
|
||||
return std::to_string((driver_version >> 22) & 0x3FF) + "." +
|
||||
std::to_string((driver_version >> 14) & 0xFF) + "." +
|
||||
std::to_string((driver_version >> 6) & 0xFF) + "." +
|
||||
std::to_string(driver_version & 0x3F);
|
||||
case PCI_ID_INTEL: {
|
||||
const uint32_t major = VK_VERSION_MAJOR(driver_version);
|
||||
/* When using Mesa driver we should use VK_VERSION_*. */
|
||||
if (major > 30) {
|
||||
return std::to_string((driver_version >> 14) & 0x3FFFF) + "." +
|
||||
std::to_string((driver_version & 0x3FFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return std::to_string(VK_VERSION_MAJOR(driver_version)) + "." +
|
||||
std::to_string(VK_VERSION_MINOR(driver_version)) + "." +
|
||||
std::to_string(VK_VERSION_PATCH(driver_version));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -29,7 +29,7 @@ class VKDevice : public NonCopyable {
|
|||
VKDescriptorPools descriptor_pools_;
|
||||
|
||||
/** Limits of the device linked to this context. */
|
||||
VkPhysicalDeviceLimits vk_physical_device_limits_;
|
||||
VkPhysicalDeviceProperties vk_physical_device_properties_ = {};
|
||||
|
||||
/** Functions of vk_ext_debugutils for this device/instance. */
|
||||
debug::VKDebuggingTools debugging_tools_;
|
||||
|
@ -40,9 +40,9 @@ class VKDevice : public NonCopyable {
|
|||
return vk_physical_device_;
|
||||
}
|
||||
|
||||
const VkPhysicalDeviceLimits &physical_device_limits_get() const
|
||||
const VkPhysicalDeviceProperties &physical_device_properties_get() const
|
||||
{
|
||||
return vk_physical_device_limits_;
|
||||
return vk_physical_device_properties_;
|
||||
}
|
||||
|
||||
VkInstance instance_get() const
|
||||
|
@ -89,9 +89,13 @@ class VKDevice : public NonCopyable {
|
|||
void init(void *ghost_context);
|
||||
void deinit();
|
||||
|
||||
eGPUDeviceType device_type() const;
|
||||
eGPUDriverType driver_type() const;
|
||||
std::string vendor_name() const;
|
||||
std::string driver_version() const;
|
||||
|
||||
private:
|
||||
void init_physical_device_limits();
|
||||
void init_capabilities();
|
||||
void init_physical_device_properties();
|
||||
void init_debug_callbacks();
|
||||
void init_memory_allocator();
|
||||
void init_descriptor_pools();
|
||||
|
|
|
@ -48,15 +48,16 @@ uint32_t struct_size(Span<shader::ShaderCreateInfo::PushConst> push_constants)
|
|||
}
|
||||
|
||||
VKPushConstants::StorageType VKPushConstants::Layout::determine_storage_type(
|
||||
const shader::ShaderCreateInfo &info, const VkPhysicalDeviceLimits &vk_physical_device_limits)
|
||||
const shader::ShaderCreateInfo &info, const VKDevice &device)
|
||||
{
|
||||
if (info.push_constants_.is_empty()) {
|
||||
return StorageType::NONE;
|
||||
}
|
||||
|
||||
uint32_t max_push_constants_size =
|
||||
device.physical_device_properties_get().limits.maxPushConstantsSize;
|
||||
uint32_t size = struct_size<Std430>(info.push_constants_);
|
||||
return size <= vk_physical_device_limits.maxPushConstantsSize ? STORAGE_TYPE_DEFAULT :
|
||||
STORAGE_TYPE_FALLBACK;
|
||||
return size <= max_push_constants_size ? STORAGE_TYPE_DEFAULT : STORAGE_TYPE_FALLBACK;
|
||||
}
|
||||
|
||||
template<typename LayoutT>
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace blender::gpu {
|
|||
class VKShaderInterface;
|
||||
class VKUniformBuffer;
|
||||
class VKContext;
|
||||
class VKDevice;
|
||||
|
||||
/**
|
||||
* Container to store push constants in a buffer.
|
||||
|
@ -88,17 +89,16 @@ class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
|
|||
public:
|
||||
/**
|
||||
* Return the desired storage type that can fit the push constants of the given shader create
|
||||
* info, matching the device limits.
|
||||
* info, matching the limits of the given device.
|
||||
*
|
||||
* Returns:
|
||||
* - StorageType::NONE: No push constants are needed.
|
||||
* - StorageType::PUSH_CONSTANTS: Regular vulkan push constants can be used.
|
||||
* - StorageType::UNIFORM_BUFFER: The push constants don't fit in the limits of the given
|
||||
* device. A uniform buffer should be used as a fallback method.
|
||||
* device. A uniform buffer should be used as a fallback method.
|
||||
*/
|
||||
static StorageType determine_storage_type(
|
||||
const shader::ShaderCreateInfo &info,
|
||||
const VkPhysicalDeviceLimits &vk_physical_device_limits);
|
||||
static StorageType determine_storage_type(const shader::ShaderCreateInfo &info,
|
||||
const VKDevice &device);
|
||||
|
||||
/**
|
||||
* Initialize the push constants of the given shader create info with the
|
||||
|
|
|
@ -50,7 +50,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
size_t names_size = info.interface_names_size_;
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
const VKPushConstants::StorageType push_constants_storage_type =
|
||||
VKPushConstants::Layout::determine_storage_type(info, device.physical_device_limits_get());
|
||||
VKPushConstants::Layout::determine_storage_type(info, device);
|
||||
if (push_constants_storage_type == VKPushConstants::StorageType::UNIFORM_BUFFER) {
|
||||
ubo_len_++;
|
||||
names_size += PUSH_CONSTANTS_FALLBACK_NAME_LEN + 1;
|
||||
|
|
Loading…
Reference in New Issue