libretro: Vulkan renderer support

This commit is contained in:
Connor McLaughlin
2020-07-04 20:06:04 +10:00
parent 218f6721d3
commit b9ffca1ddf
16 changed files with 431 additions and 36 deletions

View File

@ -19,8 +19,8 @@ std::unique_ptr<Vulkan::Context> g_vulkan_context;
namespace Vulkan {
Context::Context(VkInstance instance, VkPhysicalDevice physical_device)
: m_instance(instance), m_physical_device(physical_device)
Context::Context(VkInstance instance, VkPhysicalDevice physical_device, bool owns_device)
: m_instance(instance), m_physical_device(physical_device), m_owns_device(owns_device)
{
// Read device physical memory properties, we need it for allocating buffers
vkGetPhysicalDeviceProperties(physical_device, &m_device_properties);
@ -44,13 +44,17 @@ Context::~Context()
DestroyGlobalDescriptorPool();
DestroyCommandBuffers();
if (m_device != VK_NULL_HANDLE)
if (m_owns_device && m_device != VK_NULL_HANDLE)
vkDestroyDevice(m_device, nullptr);
if (m_debug_report_callback != VK_NULL_HANDLE)
DisableDebugReports();
vkDestroyInstance(m_instance, nullptr);
if (m_owns_device)
{
vkDestroyInstance(m_instance, nullptr);
Vulkan::UnloadVulkanLibrary();
}
}
bool Context::CheckValidationLayerAvailablility()
@ -344,14 +348,14 @@ bool Context::Create(std::string_view gpu_name, const WindowInfo* wi, std::uniqu
return false;
}
g_vulkan_context.reset(new Context(instance, gpus[gpu_index]));
g_vulkan_context.reset(new Context(instance, gpus[gpu_index], true));
// Enable debug reports if the "Host GPU" log category is enabled.
if (enable_debug_reports)
g_vulkan_context->EnableDebugReports();
// Attempt to create the device.
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer) ||
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer, nullptr, 0, nullptr, 0, nullptr) ||
!g_vulkan_context->CreateGlobalDescriptorPool() || !g_vulkan_context->CreateCommandBuffers() ||
(enable_surface && (*out_swap_chain = SwapChain::Create(wi_copy, surface, true)) == nullptr))
{
@ -359,7 +363,33 @@ bool Context::Create(std::string_view gpu_name, const WindowInfo* wi, std::uniqu
if (surface != VK_NULL_HANDLE)
vkDestroySurfaceKHR(instance, surface, nullptr);
Vulkan::UnloadVulkanLibrary();
g_vulkan_context.reset();
return false;
}
return true;
}
bool Context::CreateFromExistingInstance(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface,
bool take_ownership, bool enable_validation_layer, bool enable_debug_reports,
const char** required_device_extensions /* = nullptr */,
u32 num_required_device_extensions /* = 0 */,
const char** required_device_layers /* = nullptr */,
u32 num_required_device_layers /* = 0 */,
const VkPhysicalDeviceFeatures* required_features /* = nullptr */)
{
g_vulkan_context.reset(new Context(instance, gpu, take_ownership));
// Enable debug reports if the "Host GPU" log category is enabled.
if (enable_debug_reports)
g_vulkan_context->EnableDebugReports();
// Attempt to create the device.
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer, required_device_extensions,
num_required_device_extensions, required_device_layers,
num_required_device_layers, required_features) ||
!g_vulkan_context->CreateGlobalDescriptorPool() || !g_vulkan_context->CreateCommandBuffers())
{
g_vulkan_context.reset();
return false;
}
@ -403,8 +433,13 @@ bool Context::SelectDeviceExtensions(ExtensionList* extension_list, bool enable_
return !strcmp(name, properties.extensionName);
}) != available_extension_list.end())
{
Log_InfoPrintf("Enabling extension: %s", name);
extension_list->push_back(name);
if (std::none_of(extension_list->begin(), extension_list->end(),
[&](const char* existing_name) { return (std::strcmp(existing_name, name) == 0); }))
{
Log_InfoPrintf("Enabling extension: %s", name);
extension_list->push_back(name);
}
return true;
}
@ -420,7 +455,7 @@ bool Context::SelectDeviceExtensions(ExtensionList* extension_list, bool enable_
return true;
}
bool Context::SelectDeviceFeatures()
bool Context::SelectDeviceFeatures(const VkPhysicalDeviceFeatures* required_features)
{
VkPhysicalDeviceFeatures available_features;
vkGetPhysicalDeviceFeatures(m_physical_device, &available_features);
@ -431,6 +466,9 @@ bool Context::SelectDeviceFeatures()
return false;
}
if (required_features)
std::memcpy(&m_device_features, required_features, sizeof(m_device_features));
// Enable the features we use.
m_device_features.dualSrcBlend = available_features.dualSrcBlend;
m_device_features.geometryShader = available_features.geometryShader;
@ -438,7 +476,9 @@ bool Context::SelectDeviceFeatures()
return true;
}
bool Context::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer)
bool Context::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer, const char** required_device_extensions,
u32 num_required_device_extensions, const char** required_device_layers,
u32 num_required_device_layers, const VkPhysicalDeviceFeatures* required_features)
{
u32 queue_family_count;
vkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &queue_family_count, nullptr);
@ -536,16 +576,18 @@ bool Context::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer)
device_info.pQueueCreateInfos = queue_infos.data();
ExtensionList enabled_extensions;
for (u32 i = 0; i < num_required_device_extensions; i++)
enabled_extensions.emplace_back(required_device_extensions[i]);
if (!SelectDeviceExtensions(&enabled_extensions, surface != VK_NULL_HANDLE))
return false;
device_info.enabledLayerCount = 0;
device_info.ppEnabledLayerNames = nullptr;
device_info.enabledLayerCount = num_required_device_layers;
device_info.ppEnabledLayerNames = required_device_layers;
device_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
device_info.ppEnabledExtensionNames = enabled_extensions.data();
// Check for required features before creating.
if (!SelectDeviceFeatures())
if (!SelectDeviceFeatures(required_features))
return false;
device_info.pEnabledFeatures = &m_device_features;

View File

@ -46,6 +46,15 @@ public:
static bool Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
bool enable_debug_reports, bool enable_validation_layer);
// Creates a new context from a pre-existing instance.
static bool CreateFromExistingInstance(VkInstance instance, VkPhysicalDevice gpu, VkSurfaceKHR surface,
bool take_ownership, bool enable_validation_layer, bool enable_debug_reports,
const char** required_device_extensions = nullptr,
u32 num_required_device_extensions = 0,
const char** required_device_layers = nullptr,
u32 num_required_device_layers = 0,
const VkPhysicalDeviceFeatures* required_features = nullptr);
// Destroys context.
static void Destroy();
@ -162,13 +171,15 @@ public:
void WaitForGPUIdle();
private:
Context(VkInstance instance, VkPhysicalDevice physical_device);
Context(VkInstance instance, VkPhysicalDevice physical_device, bool owns_device);
using ExtensionList = std::vector<const char*>;
static bool SelectInstanceExtensions(ExtensionList* extension_list, bool enable_surface, bool enable_debug_report);
bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface);
bool SelectDeviceFeatures();
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
bool SelectDeviceFeatures(const VkPhysicalDeviceFeatures* required_features);
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer, const char** required_device_extensions,
u32 num_required_device_extensions, const char** required_device_layers,
u32 num_required_device_layers, const VkPhysicalDeviceFeatures* required_features);
bool CreateCommandBuffers();
void DestroyCommandBuffers();
@ -210,6 +221,7 @@ private:
u64 m_completed_fence_counter = 0;
u32 m_current_frame;
bool m_owns_device = false;
bool m_last_present_failed = false;
// Render pass cache

View File

@ -232,6 +232,15 @@ void SafeDestroySampler(VkSampler& samp)
}
}
void SafeDestroySemaphore(VkSemaphore& sem)
{
if (sem != VK_NULL_HANDLE)
{
vkDestroySemaphore(g_vulkan_context->GetDevice(), sem, nullptr);
sem = VK_NULL_HANDLE;
}
}
void SafeFreeGlobalDescriptorSet(VkDescriptorSet& ds)
{
if (ds != VK_NULL_HANDLE)

View File

@ -41,6 +41,7 @@ void SafeDestroyPipelineLayout(VkPipelineLayout& pl);
void SafeDestroyDescriptorSetLayout(VkDescriptorSetLayout& dsl);
void SafeDestroyBufferView(VkBufferView& bv);
void SafeDestroySampler(VkSampler& samp);
void SafeDestroySemaphore(VkSemaphore& sem);
void SafeFreeGlobalDescriptorSet(VkDescriptorSet& ds);
void SetViewport(VkCommandBuffer command_buffer, int x, int y, int width, int height, float min_depth = 0.0f,