diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc index a9bd54d310f..3420e3bedc6 100644 --- a/source/blender/gpu/vulkan/vk_backend.cc +++ b/source/blender/gpu/vulkan/vk_backend.cc @@ -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 = {}; diff --git a/source/blender/gpu/vulkan/vk_backend.hh b/source/blender/gpu/vulkan/vk_backend.hh index 65599f9dfe3..39feeb952a0 100644 --- a/source/blender/gpu/vulkan/vk_backend.hh +++ b/source/blender/gpu/vulkan/vk_backend.hh @@ -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(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. */ diff --git a/source/blender/gpu/vulkan/vk_device.cc b/source/blender/gpu/vulkan/vk_device.cc index c396f277419..bd97850debd 100644 --- a/source/blender/gpu/vulkan/vk_device.cc +++ b/source/blender/gpu/vulkan/vk_device.cc @@ -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 diff --git a/source/blender/gpu/vulkan/vk_device.hh b/source/blender/gpu/vulkan/vk_device.hh index c0df1ec703f..d386da44767 100644 --- a/source/blender/gpu/vulkan/vk_device.hh +++ b/source/blender/gpu/vulkan/vk_device.hh @@ -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(); diff --git a/source/blender/gpu/vulkan/vk_push_constants.cc b/source/blender/gpu/vulkan/vk_push_constants.cc index c60e1d664e6..b30e7edd4cb 100644 --- a/source/blender/gpu/vulkan/vk_push_constants.cc +++ b/source/blender/gpu/vulkan/vk_push_constants.cc @@ -48,15 +48,16 @@ uint32_t struct_size(Span 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(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 diff --git a/source/blender/gpu/vulkan/vk_push_constants.hh b/source/blender/gpu/vulkan/vk_push_constants.hh index b13fce6cb1c..f39c81476c9 100644 --- a/source/blender/gpu/vulkan/vk_push_constants.hh +++ b/source/blender/gpu/vulkan/vk_push_constants.hh @@ -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 { 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 diff --git a/source/blender/gpu/vulkan/vk_shader_interface.cc b/source/blender/gpu/vulkan/vk_shader_interface.cc index a8fd996442b..c029cc043c5 100644 --- a/source/blender/gpu/vulkan/vk_shader_interface.cc +++ b/source/blender/gpu/vulkan/vk_shader_interface.cc @@ -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;