mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-27 09:12:46 +01:00
vulkan_instance: Allow different Vulkan versions and enforce 1.1
For listing the available physical devices we can use Vulkan 1.0. Now that MoltenVK supports 1.1 we can require it for running games. Add missing documentation.
This commit is contained in:
parent
7344a7c447
commit
cdbee27692
7 changed files with 39 additions and 41 deletions
|
@ -127,8 +127,8 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
|
|
||||||
bool RendererVulkan::Init() try {
|
bool RendererVulkan::Init() try {
|
||||||
library = OpenLibrary();
|
library = OpenLibrary();
|
||||||
std::tie(instance, instance_version) = CreateInstance(
|
instance = CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
|
||||||
library, dld, render_window.GetWindowInfo().type, true, Settings::values.renderer_debug);
|
true, Settings::values.renderer_debug);
|
||||||
if (Settings::values.renderer_debug) {
|
if (Settings::values.renderer_debug) {
|
||||||
debug_callback = CreateDebugCallback(instance);
|
debug_callback = CreateDebugCallback(instance);
|
||||||
}
|
}
|
||||||
|
@ -184,8 +184,7 @@ void RendererVulkan::InitializeDevice() {
|
||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
}
|
}
|
||||||
const vk::PhysicalDevice physical_device(devices[static_cast<size_t>(device_index)], dld);
|
const vk::PhysicalDevice physical_device(devices[static_cast<size_t>(device_index)], dld);
|
||||||
device =
|
device = std::make_unique<VKDevice>(*instance, physical_device, *surface, dld);
|
||||||
std::make_unique<VKDevice>(*instance, instance_version, physical_device, *surface, dld);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::Report() const {
|
void RendererVulkan::Report() const {
|
||||||
|
@ -213,7 +212,7 @@ void RendererVulkan::Report() const {
|
||||||
std::vector<std::string> RendererVulkan::EnumerateDevices() try {
|
std::vector<std::string> RendererVulkan::EnumerateDevices() try {
|
||||||
vk::InstanceDispatch dld;
|
vk::InstanceDispatch dld;
|
||||||
const Common::DynamicLibrary library = OpenLibrary();
|
const Common::DynamicLibrary library = OpenLibrary();
|
||||||
const vk::Instance instance = CreateInstance(library, dld).first;
|
const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
|
||||||
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
|
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
names.reserve(physical_devices.size());
|
names.reserve(physical_devices.size());
|
||||||
|
|
|
@ -68,7 +68,6 @@ private:
|
||||||
vk::InstanceDispatch dld;
|
vk::InstanceDispatch dld;
|
||||||
|
|
||||||
vk::Instance instance;
|
vk::Instance instance;
|
||||||
u32 instance_version{};
|
|
||||||
|
|
||||||
vk::SurfaceKHR surface;
|
vk::SurfaceKHR surface;
|
||||||
|
|
||||||
|
|
|
@ -206,10 +206,10 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
VKDevice::VKDevice(VkInstance instance_, u32 instance_version_, vk::PhysicalDevice physical_,
|
VKDevice::VKDevice(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
|
||||||
VkSurfaceKHR surface, const vk::InstanceDispatch& dld_)
|
const vk::InstanceDispatch& dld_)
|
||||||
: instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()},
|
: instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()},
|
||||||
instance_version{instance_version_}, format_properties{GetFormatProperties(physical, dld)} {
|
format_properties{GetFormatProperties(physical, dld)} {
|
||||||
CheckSuitability();
|
CheckSuitability();
|
||||||
SetupFamilies(surface);
|
SetupFamilies(surface);
|
||||||
SetupFeatures();
|
SetupFeatures();
|
||||||
|
@ -653,9 +653,7 @@ std::vector<const char*> VKDevice::LoadExtensions() {
|
||||||
test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false);
|
test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false);
|
||||||
test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
|
test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
|
||||||
test(has_ext_robustness2, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, false);
|
test(has_ext_robustness2, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, false);
|
||||||
if (instance_version >= VK_API_VERSION_1_1) {
|
|
||||||
test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
|
test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
|
||||||
}
|
|
||||||
if (Settings::values.renderer_debug) {
|
if (Settings::values.renderer_debug) {
|
||||||
test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
|
test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
|
||||||
true);
|
true);
|
||||||
|
|
|
@ -24,8 +24,8 @@ const u32 GuestWarpSize = 32;
|
||||||
/// Handles data specific to a physical device.
|
/// Handles data specific to a physical device.
|
||||||
class VKDevice final {
|
class VKDevice final {
|
||||||
public:
|
public:
|
||||||
explicit VKDevice(VkInstance instance, u32 instance_version, vk::PhysicalDevice physical,
|
explicit VKDevice(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
|
||||||
VkSurfaceKHR surface, const vk::InstanceDispatch& dld);
|
const vk::InstanceDispatch& dld);
|
||||||
~VKDevice();
|
~VKDevice();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,11 +79,6 @@ public:
|
||||||
return present_family;
|
return present_family;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current instance Vulkan API version in Vulkan-formatted version numbers.
|
|
||||||
u32 InstanceApiVersion() const {
|
|
||||||
return instance_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the current Vulkan API version provided in Vulkan-formatted version numbers.
|
/// Returns the current Vulkan API version provided in Vulkan-formatted version numbers.
|
||||||
u32 ApiVersion() const {
|
u32 ApiVersion() const {
|
||||||
return properties.apiVersion;
|
return properties.apiVersion;
|
||||||
|
|
|
@ -272,19 +272,12 @@ bool IsPrecise(Operation operand) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ShaderVersion(const VKDevice& device) {
|
|
||||||
if (device.InstanceApiVersion() < VK_API_VERSION_1_1) {
|
|
||||||
return 0x00010000;
|
|
||||||
}
|
|
||||||
return 0x00010300;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SPIRVDecompiler final : public Sirit::Module {
|
class SPIRVDecompiler final : public Sirit::Module {
|
||||||
public:
|
public:
|
||||||
explicit SPIRVDecompiler(const VKDevice& device_, const ShaderIR& ir_, ShaderType stage_,
|
explicit SPIRVDecompiler(const VKDevice& device_, const ShaderIR& ir_, ShaderType stage_,
|
||||||
const Registry& registry_, const Specialization& specialization_)
|
const Registry& registry_, const Specialization& specialization_)
|
||||||
: Module(ShaderVersion(device_)), device{device_}, ir{ir_}, stage{stage_},
|
: Module(0x00010300), device{device_}, ir{ir_}, stage{stage_}, header{ir_.GetHeader()},
|
||||||
header{ir_.GetHeader()}, registry{registry_}, specialization{specialization_} {
|
registry{registry_}, specialization{specialization_} {
|
||||||
if (stage_ != ShaderType::Compute) {
|
if (stage_ != ShaderType::Compute) {
|
||||||
transform_feedback = BuildTransformFeedback(registry_.GetGraphicsInfo());
|
transform_feedback = BuildTransformFeedback(registry_.GetGraphicsInfo());
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,9 +111,8 @@ void RemoveUnavailableLayers(const vk::InstanceDispatch& dld, std::vector<const
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::pair<vk::Instance, u32> CreateInstance(const Common::DynamicLibrary& library,
|
vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceDispatch& dld,
|
||||||
vk::InstanceDispatch& dld,
|
u32 required_version, Core::Frontend::WindowSystemType window_type,
|
||||||
Core::Frontend::WindowSystemType window_type,
|
|
||||||
bool enable_debug_utils, bool enable_layers) {
|
bool enable_debug_utils, bool enable_layers) {
|
||||||
if (!library.IsOpen()) {
|
if (!library.IsOpen()) {
|
||||||
LOG_ERROR(Render_Vulkan, "Vulkan library not available");
|
LOG_ERROR(Render_Vulkan, "Vulkan library not available");
|
||||||
|
@ -134,15 +133,19 @@ std::pair<vk::Instance, u32> CreateInstance(const Common::DynamicLibrary& librar
|
||||||
std::vector<const char*> layers = Layers(enable_layers);
|
std::vector<const char*> layers = Layers(enable_layers);
|
||||||
RemoveUnavailableLayers(dld, layers);
|
RemoveUnavailableLayers(dld, layers);
|
||||||
|
|
||||||
// Limit the maximum version of Vulkan to avoid using untested version.
|
const u32 available_version = vk::AvailableVersion(dld);
|
||||||
const u32 version = std::min(vk::AvailableVersion(dld), VK_API_VERSION_1_1);
|
if (available_version < required_version) {
|
||||||
|
LOG_ERROR(Render_Vulkan, "Vulkan {}.{} is not supported, {}.{} is required",
|
||||||
vk::Instance instance = vk::Instance::Create(version, layers, extensions, dld);
|
VK_VERSION_MAJOR(available_version), VK_VERSION_MINOR(available_version),
|
||||||
|
VK_VERSION_MAJOR(required_version), VK_VERSION_MINOR(required_version));
|
||||||
|
throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||||
|
}
|
||||||
|
vk::Instance instance = vk::Instance::Create(required_version, layers, extensions, dld);
|
||||||
if (!vk::Load(*instance, dld)) {
|
if (!vk::Load(*instance, dld)) {
|
||||||
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers");
|
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers");
|
||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
}
|
}
|
||||||
return std::make_pair(std::move(instance), version);
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/dynamic_library.h"
|
#include "common/dynamic_library.h"
|
||||||
#include "core/frontend/emu_window.h"
|
#include "core/frontend/emu_window.h"
|
||||||
|
@ -13,8 +11,21 @@
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
[[nodiscard]] std::pair<vk::Instance, u32> CreateInstance(
|
/**
|
||||||
const Common::DynamicLibrary& library, vk::InstanceDispatch& dld,
|
* Create a Vulkan instance
|
||||||
|
*
|
||||||
|
* @param library Dynamic library to load the Vulkan instance from
|
||||||
|
* @param dld Dispatch table to load function pointers into
|
||||||
|
* @param required_version Required Vulkan version (for example, VK_API_VERSION_1_1)
|
||||||
|
* @param window_type Window system type's enabled extension
|
||||||
|
* @param enable_debug_utils Whether to enable VK_EXT_debug_utils_extension_name or not
|
||||||
|
* @param enable_layers Whether to enable Vulkan validation layers or not
|
||||||
|
*
|
||||||
|
* @return A new Vulkan instance
|
||||||
|
* @throw vk::Exception on failure
|
||||||
|
*/
|
||||||
|
[[nodiscard]] vk::Instance CreateInstance(
|
||||||
|
const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, u32 required_version,
|
||||||
Core::Frontend::WindowSystemType window_type = Core::Frontend::WindowSystemType::Headless,
|
Core::Frontend::WindowSystemType window_type = Core::Frontend::WindowSystemType::Headless,
|
||||||
bool enable_debug_utils = false, bool enable_layers = false);
|
bool enable_debug_utils = false, bool enable_layers = false);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue