WIP: Vulkan: Workbench #107886

Closed
Jeroen Bakker wants to merge 88 commits from Jeroen-Bakker:vulkan-draw-manager-workbench into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 164 additions and 46 deletions
Showing only changes of commit e69cc677d0 - Show all commits

View File

@ -27,29 +27,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();
}
@ -149,10 +173,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 = {};

View File

@ -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. */

View File

@ -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

View File

@ -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();

View File

@ -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>

View File

@ -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

View File

@ -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;