mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
VK refactoring Part 2 (#9542)
This commit is contained in:
parent
65f81aca0f
commit
11db3151ae
@ -435,11 +435,14 @@ target_sources(rpcs3_emu PRIVATE
|
||||
|
||||
if(TARGET 3rdparty_vulkan)
|
||||
target_sources(rpcs3_emu PRIVATE
|
||||
RSX/VK/vkutils/buffer_view.cpp
|
||||
RSX/VK/vkutils/chip_class.cpp
|
||||
RSX/VK/vkutils/command_pool.cpp
|
||||
RSX/VK/vkutils/fence.cpp
|
||||
RSX/VK/vkutils/mem_allocator.cpp
|
||||
RSX/VK/vkutils/memory_block.cpp
|
||||
RSX/VK/vkutils/physical_device.cpp
|
||||
RSX/VK/vkutils/render_device.cpp
|
||||
RSX/VK/vkutils/sampler.cpp
|
||||
RSX/VK/vkutils/shared.cpp
|
||||
RSX/VK/VKCommandStream.cpp
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../Common/BufferUtils.h"
|
||||
#include "../rsx_methods.h"
|
||||
#include "VKGSRender.h"
|
||||
#include "vkutils/buffer_view.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "VKRenderPass.h"
|
||||
#include "VKResourceManager.h"
|
||||
#include "VKCommandStream.h"
|
||||
#include "vkutils/buffer_view.h"
|
||||
#include "Emu/RSX/rsx_methods.h"
|
||||
#include "Emu/Memory/vm_locking.h"
|
||||
|
||||
|
@ -53,6 +53,8 @@ extern u64 get_system_time();
|
||||
|
||||
namespace vk
|
||||
{
|
||||
struct buffer_view;
|
||||
|
||||
struct command_buffer_chunk: public vk::command_buffer
|
||||
{
|
||||
vk::fence* submit_fence = nullptr;
|
||||
|
@ -21,12 +21,11 @@
|
||||
#include "../Common/TextureUtils.h"
|
||||
#include "../display.h"
|
||||
#include "../rsx_utils.h"
|
||||
#include "vkutils/chip_class.h"
|
||||
#include "vkutils/command_pool.h"
|
||||
#include "vkutils/fence.h"
|
||||
#include "vkutils/mem_allocator.h"
|
||||
#include "vkutils/memory_block.h"
|
||||
#include "vkutils/physical_device.h"
|
||||
#include "vkutils/pipeline_binding_table.h"
|
||||
#include "vkutils/render_device.h"
|
||||
#include "vkutils/shared.h"
|
||||
#include "vkutils/supported_extensions.h"
|
||||
|
||||
@ -45,11 +44,6 @@
|
||||
//using enum rsx::format_class;
|
||||
using namespace ::rsx::format_class_;
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
class fragment_texture;
|
||||
}
|
||||
|
||||
namespace vk
|
||||
{
|
||||
VKAPI_ATTR void *VKAPI_CALL mem_realloc(void *pUserData, void *pOriginal, usz size, usz alignment, VkSystemAllocationScope allocationScope);
|
||||
@ -77,7 +71,6 @@ namespace vk
|
||||
|
||||
class context;
|
||||
class render_device;
|
||||
class swap_chain_image;
|
||||
class command_buffer;
|
||||
class image;
|
||||
struct image_view;
|
||||
@ -192,325 +185,6 @@ namespace vk
|
||||
// TODO: Move queries out of the renderer!
|
||||
void do_query_cleanup(vk::command_buffer& cmd);
|
||||
|
||||
class render_device
|
||||
{
|
||||
physical_device *pgpu = nullptr;
|
||||
memory_type_mapping memory_map{};
|
||||
gpu_formats_support m_formats_support{};
|
||||
pipeline_binding_table m_pipeline_binding_table{};
|
||||
std::unique_ptr<mem_allocator_base> m_allocator;
|
||||
VkDevice dev = VK_NULL_HANDLE;
|
||||
|
||||
public:
|
||||
// Exported device endpoints
|
||||
PFN_vkCmdBeginConditionalRenderingEXT cmdBeginConditionalRenderingEXT = nullptr;
|
||||
PFN_vkCmdEndConditionalRenderingEXT cmdEndConditionalRenderingEXT = nullptr;
|
||||
|
||||
public:
|
||||
render_device() = default;
|
||||
~render_device() = default;
|
||||
|
||||
void create(vk::physical_device &pdev, u32 graphics_queue_idx)
|
||||
{
|
||||
float queue_priorities[1] = { 0.f };
|
||||
pgpu = &pdev;
|
||||
|
||||
VkDeviceQueueCreateInfo queue = {};
|
||||
queue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue.pNext = NULL;
|
||||
queue.queueFamilyIndex = graphics_queue_idx;
|
||||
queue.queueCount = 1;
|
||||
queue.pQueuePriorities = queue_priorities;
|
||||
|
||||
// Set up instance information
|
||||
std::vector<const char *>requested_extensions =
|
||||
{
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||
};
|
||||
|
||||
// Enable hardware features manually
|
||||
// Currently we require:
|
||||
// 1. Anisotropic sampling
|
||||
// 2. DXT support
|
||||
// 3. Indexable storage buffers
|
||||
VkPhysicalDeviceFeatures enabled_features{};
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
requested_extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (pgpu->conditional_render_support)
|
||||
{
|
||||
requested_extensions.push_back(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (pgpu->unrestricted_depth_range_support)
|
||||
{
|
||||
requested_extensions.push_back(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
enabled_features.robustBufferAccess = VK_TRUE;
|
||||
enabled_features.fullDrawIndexUint32 = VK_TRUE;
|
||||
enabled_features.independentBlend = VK_TRUE;
|
||||
enabled_features.logicOp = VK_TRUE;
|
||||
enabled_features.depthClamp = VK_TRUE;
|
||||
enabled_features.depthBounds = VK_TRUE;
|
||||
enabled_features.wideLines = VK_TRUE;
|
||||
enabled_features.largePoints = VK_TRUE;
|
||||
enabled_features.shaderFloat64 = VK_TRUE;
|
||||
|
||||
if (g_cfg.video.antialiasing_level != msaa_level::none)
|
||||
{
|
||||
// MSAA features
|
||||
if (!pgpu->features.shaderStorageImageMultisample ||
|
||||
!pgpu->features.shaderStorageImageWriteWithoutFormat)
|
||||
{
|
||||
// TODO: Slow fallback to emulate this
|
||||
// Just warn and let the driver decide whether to crash or not
|
||||
rsx_log.fatal("Your GPU driver does not support some required MSAA features. Expect problems.");
|
||||
}
|
||||
|
||||
enabled_features.sampleRateShading = VK_TRUE;
|
||||
enabled_features.alphaToOne = VK_TRUE;
|
||||
enabled_features.shaderStorageImageMultisample = VK_TRUE;
|
||||
// enabled_features.shaderStorageImageReadWithoutFormat = VK_TRUE; // Unused currently, may be needed soon
|
||||
enabled_features.shaderStorageImageWriteWithoutFormat = VK_TRUE;
|
||||
}
|
||||
|
||||
// enabled_features.shaderSampledImageArrayDynamicIndexing = TRUE; // Unused currently but will be needed soon
|
||||
enabled_features.shaderClipDistance = VK_TRUE;
|
||||
// enabled_features.shaderCullDistance = VK_TRUE; // Alt notation of clip distance
|
||||
|
||||
enabled_features.samplerAnisotropy = VK_TRUE;
|
||||
enabled_features.textureCompressionBC = VK_TRUE;
|
||||
enabled_features.shaderStorageBufferArrayDynamicIndexing = VK_TRUE;
|
||||
|
||||
// Optionally disable unsupported stuff
|
||||
if (!pgpu->features.shaderFloat64)
|
||||
{
|
||||
rsx_log.error("Your GPU does not support double precision floats in shaders. Graphics may not work correctly.");
|
||||
enabled_features.shaderFloat64 = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.depthBounds)
|
||||
{
|
||||
rsx_log.error("Your GPU does not support depth bounds testing. Graphics may not work correctly.");
|
||||
enabled_features.depthBounds = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.sampleRateShading && enabled_features.sampleRateShading)
|
||||
{
|
||||
rsx_log.error("Your GPU does not support sample rate shading for multisampling. Graphics may be inaccurate when MSAA is enabled.");
|
||||
enabled_features.sampleRateShading = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.alphaToOne && enabled_features.alphaToOne)
|
||||
{
|
||||
// AMD proprietary drivers do not expose alphaToOne support
|
||||
rsx_log.error("Your GPU does not support alpha-to-one for multisampling. Graphics may be inaccurate when MSAA is enabled.");
|
||||
enabled_features.alphaToOne = VK_FALSE;
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo device = {};
|
||||
device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
device.pNext = nullptr;
|
||||
device.queueCreateInfoCount = 1;
|
||||
device.pQueueCreateInfos = &queue;
|
||||
device.enabledLayerCount = 0;
|
||||
device.ppEnabledLayerNames = nullptr; // Deprecated
|
||||
device.enabledExtensionCount = ::size32(requested_extensions);
|
||||
device.ppEnabledExtensionNames = requested_extensions.data();
|
||||
device.pEnabledFeatures = &enabled_features;
|
||||
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{};
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
// Allow use of f16 type in shaders if possible
|
||||
shader_support_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
|
||||
shader_support_info.shaderFloat16 = VK_TRUE;
|
||||
device.pNext = &shader_support_info;
|
||||
|
||||
rsx_log.notice("GPU/driver supports float16 data types natively. Using native float16_t variables if possible.");
|
||||
}
|
||||
else
|
||||
{
|
||||
rsx_log.notice("GPU/driver lacks support for float16 data types. All float16_t arithmetic will be emulated with float32_t.");
|
||||
}
|
||||
|
||||
CHECK_RESULT(vkCreateDevice(*pgpu, &device, nullptr, &dev));
|
||||
|
||||
// Import optional function endpoints
|
||||
if (pgpu->conditional_render_support)
|
||||
{
|
||||
cmdBeginConditionalRenderingEXT = reinterpret_cast<PFN_vkCmdBeginConditionalRenderingEXT>(vkGetDeviceProcAddr(dev, "vkCmdBeginConditionalRenderingEXT"));
|
||||
cmdEndConditionalRenderingEXT = reinterpret_cast<PFN_vkCmdEndConditionalRenderingEXT>(vkGetDeviceProcAddr(dev, "vkCmdEndConditionalRenderingEXT"));
|
||||
}
|
||||
|
||||
memory_map = vk::get_memory_mapping(pdev);
|
||||
m_formats_support = vk::get_optimal_tiling_supported_formats(pdev);
|
||||
m_pipeline_binding_table = vk::get_pipeline_binding_table(pdev);
|
||||
|
||||
if (g_cfg.video.disable_vulkan_mem_allocator)
|
||||
m_allocator = std::make_unique<vk::mem_allocator_vk>(dev, pdev);
|
||||
else
|
||||
m_allocator = std::make_unique<vk::mem_allocator_vma>(dev, pdev);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if (dev && pgpu)
|
||||
{
|
||||
if (m_allocator)
|
||||
{
|
||||
m_allocator->destroy();
|
||||
m_allocator.reset();
|
||||
}
|
||||
|
||||
vkDestroyDevice(dev, nullptr);
|
||||
dev = nullptr;
|
||||
memory_map = {};
|
||||
m_formats_support = {};
|
||||
}
|
||||
}
|
||||
|
||||
const VkFormatProperties get_format_properties(VkFormat format)
|
||||
{
|
||||
auto found = pgpu->format_properties.find(format);
|
||||
if (found != pgpu->format_properties.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
auto& props = pgpu->format_properties[format];
|
||||
vkGetPhysicalDeviceFormatProperties(*pgpu, format, &props);
|
||||
return props;
|
||||
}
|
||||
|
||||
bool get_compatible_memory_type(u32 typeBits, u32 desired_mask, u32 *type_index) const
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties mem_infos = pgpu->get_memory_properties();
|
||||
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
if ((typeBits & 1) == 1)
|
||||
{
|
||||
if ((mem_infos.memoryTypes[i].propertyFlags & desired_mask) == desired_mask)
|
||||
{
|
||||
if (type_index)
|
||||
{
|
||||
*type_index = i;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
typeBits >>= 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const physical_device& gpu() const
|
||||
{
|
||||
return *pgpu;
|
||||
}
|
||||
|
||||
const memory_type_mapping& get_memory_mapping() const
|
||||
{
|
||||
return memory_map;
|
||||
}
|
||||
|
||||
const gpu_formats_support& get_formats_support() const
|
||||
{
|
||||
return m_formats_support;
|
||||
}
|
||||
|
||||
const pipeline_binding_table& get_pipeline_binding_table() const
|
||||
{
|
||||
return m_pipeline_binding_table;
|
||||
}
|
||||
|
||||
const gpu_shader_types_support& get_shader_types_support() const
|
||||
{
|
||||
return pgpu->shader_types_support;
|
||||
}
|
||||
|
||||
bool get_shader_stencil_export_support() const
|
||||
{
|
||||
return pgpu->stencil_export_support;
|
||||
}
|
||||
|
||||
bool get_depth_bounds_support() const
|
||||
{
|
||||
return pgpu->features.depthBounds != VK_FALSE;
|
||||
}
|
||||
|
||||
bool get_alpha_to_one_support() const
|
||||
{
|
||||
return pgpu->features.alphaToOne != VK_FALSE;
|
||||
}
|
||||
|
||||
bool get_conditional_render_support() const
|
||||
{
|
||||
return pgpu->conditional_render_support;
|
||||
}
|
||||
|
||||
bool get_unrestricted_depth_range_support() const
|
||||
{
|
||||
return pgpu->unrestricted_depth_range_support;
|
||||
}
|
||||
|
||||
mem_allocator_base* get_allocator() const
|
||||
{
|
||||
return m_allocator.get();
|
||||
}
|
||||
|
||||
operator VkDevice() const
|
||||
{
|
||||
return dev;
|
||||
}
|
||||
};
|
||||
|
||||
class command_pool
|
||||
{
|
||||
vk::render_device *owner = nullptr;
|
||||
VkCommandPool pool = nullptr;
|
||||
|
||||
public:
|
||||
command_pool() = default;
|
||||
~command_pool() = default;
|
||||
|
||||
void create(vk::render_device &dev)
|
||||
{
|
||||
owner = &dev;
|
||||
VkCommandPoolCreateInfo infos = {};
|
||||
infos.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
infos.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
|
||||
CHECK_RESULT(vkCreateCommandPool(dev, &infos, nullptr, &pool));
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
vkDestroyCommandPool((*owner), pool, nullptr);
|
||||
pool = nullptr;
|
||||
}
|
||||
|
||||
vk::render_device& get_owner()
|
||||
{
|
||||
return (*owner);
|
||||
}
|
||||
|
||||
operator VkCommandPool()
|
||||
{
|
||||
return pool;
|
||||
}
|
||||
};
|
||||
|
||||
class command_buffer
|
||||
{
|
||||
private:
|
||||
@ -1125,53 +799,6 @@ namespace vk
|
||||
VkDevice m_device;
|
||||
};
|
||||
|
||||
struct buffer_view
|
||||
{
|
||||
VkBufferView value;
|
||||
VkBufferViewCreateInfo info = {};
|
||||
|
||||
buffer_view(VkDevice dev, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size)
|
||||
: m_device(dev)
|
||||
{
|
||||
info.buffer = buffer;
|
||||
info.format = format;
|
||||
info.offset = offset;
|
||||
info.range = size;
|
||||
info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
||||
CHECK_RESULT(vkCreateBufferView(m_device, &info, nullptr, &value));
|
||||
}
|
||||
|
||||
~buffer_view()
|
||||
{
|
||||
vkDestroyBufferView(m_device, value, nullptr);
|
||||
}
|
||||
|
||||
buffer_view(const buffer_view&) = delete;
|
||||
buffer_view(buffer_view&&) = delete;
|
||||
|
||||
bool in_range(u32 address, u32 size, u32& offset) const
|
||||
{
|
||||
if (address < info.offset)
|
||||
return false;
|
||||
|
||||
const u32 _offset = address - static_cast<u32>(info.offset);
|
||||
if (info.range < _offset)
|
||||
return false;
|
||||
|
||||
const auto remaining = info.range - _offset;
|
||||
if (size <= remaining)
|
||||
{
|
||||
offset = _offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
VkDevice m_device;
|
||||
};
|
||||
|
||||
class event
|
||||
{
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "VKGSRender.h"
|
||||
#include "vkutils/buffer_view.h"
|
||||
#include "Emu/Cell/Modules/cellVideoOut.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "VKGSRender.h"
|
||||
#include "../Common/BufferUtils.h"
|
||||
#include "../rsx_methods.h"
|
||||
#include "vkutils/buffer_view.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
|
40
rpcs3/Emu/RSX/VK/vkutils/buffer_view.cpp
Normal file
40
rpcs3/Emu/RSX/VK/vkutils/buffer_view.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "buffer_view.h"
|
||||
#include "shared.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
buffer_view::buffer_view(VkDevice dev, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size)
|
||||
: m_device(dev)
|
||||
{
|
||||
info.buffer = buffer;
|
||||
info.format = format;
|
||||
info.offset = offset;
|
||||
info.range = size;
|
||||
info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
||||
CHECK_RESULT(vkCreateBufferView(m_device, &info, nullptr, &value));
|
||||
}
|
||||
|
||||
buffer_view::~buffer_view()
|
||||
{
|
||||
vkDestroyBufferView(m_device, value, nullptr);
|
||||
}
|
||||
|
||||
bool buffer_view::in_range(u32 address, u32 size, u32& offset) const
|
||||
{
|
||||
if (address < info.offset)
|
||||
return false;
|
||||
|
||||
const u32 _offset = address - static_cast<u32>(info.offset);
|
||||
if (info.range < _offset)
|
||||
return false;
|
||||
|
||||
const auto remaining = info.range - _offset;
|
||||
if (size <= remaining)
|
||||
{
|
||||
offset = _offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
23
rpcs3/Emu/RSX/VK/vkutils/buffer_view.h
Normal file
23
rpcs3/Emu/RSX/VK/vkutils/buffer_view.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "../VulkanAPI.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
struct buffer_view
|
||||
{
|
||||
VkBufferView value;
|
||||
VkBufferViewCreateInfo info = {};
|
||||
|
||||
buffer_view(VkDevice dev, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size);
|
||||
~buffer_view();
|
||||
|
||||
buffer_view(const buffer_view&) = delete;
|
||||
buffer_view(buffer_view&&) = delete;
|
||||
|
||||
bool in_range(u32 address, u32 size, u32& offset) const;
|
||||
|
||||
private:
|
||||
VkDevice m_device;
|
||||
};
|
||||
}
|
35
rpcs3/Emu/RSX/VK/vkutils/command_pool.cpp
Normal file
35
rpcs3/Emu/RSX/VK/vkutils/command_pool.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "command_pool.h"
|
||||
#include "render_device.h"
|
||||
#include "shared.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
void command_pool::create(vk::render_device& dev)
|
||||
{
|
||||
owner = &dev;
|
||||
VkCommandPoolCreateInfo infos = {};
|
||||
infos.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
infos.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
|
||||
CHECK_RESULT(vkCreateCommandPool(dev, &infos, nullptr, &pool));
|
||||
}
|
||||
|
||||
void command_pool::destroy()
|
||||
{
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
vkDestroyCommandPool((*owner), pool, nullptr);
|
||||
pool = nullptr;
|
||||
}
|
||||
|
||||
vk::render_device& command_pool::get_owner()
|
||||
{
|
||||
return (*owner);
|
||||
}
|
||||
|
||||
command_pool::operator VkCommandPool()
|
||||
{
|
||||
return pool;
|
||||
}
|
||||
}
|
25
rpcs3/Emu/RSX/VK/vkutils/command_pool.h
Normal file
25
rpcs3/Emu/RSX/VK/vkutils/command_pool.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "../VulkanAPI.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
class render_device;
|
||||
|
||||
class command_pool
|
||||
{
|
||||
vk::render_device* owner = nullptr;
|
||||
VkCommandPool pool = nullptr;
|
||||
|
||||
public:
|
||||
command_pool() = default;
|
||||
~command_pool() = default;
|
||||
|
||||
void create(vk::render_device& dev);
|
||||
void destroy();
|
||||
|
||||
vk::render_device& get_owner();
|
||||
|
||||
operator VkCommandPool();
|
||||
};
|
||||
}
|
265
rpcs3/Emu/RSX/VK/vkutils/render_device.cpp
Normal file
265
rpcs3/Emu/RSX/VK/vkutils/render_device.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
#include "render_device.h"
|
||||
#include "mem_allocator.h"
|
||||
#include "shared.h"
|
||||
|
||||
#include "Emu/system_config.h"
|
||||
|
||||
namespace vk
|
||||
{
|
||||
void render_device::create(vk::physical_device& pdev, u32 graphics_queue_idx)
|
||||
{
|
||||
float queue_priorities[1] = {0.f};
|
||||
pgpu = &pdev;
|
||||
|
||||
VkDeviceQueueCreateInfo queue = {};
|
||||
queue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue.pNext = NULL;
|
||||
queue.queueFamilyIndex = graphics_queue_idx;
|
||||
queue.queueCount = 1;
|
||||
queue.pQueuePriorities = queue_priorities;
|
||||
|
||||
// Set up instance information
|
||||
std::vector<const char*> requested_extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||
|
||||
// Enable hardware features manually
|
||||
// Currently we require:
|
||||
// 1. Anisotropic sampling
|
||||
// 2. DXT support
|
||||
// 3. Indexable storage buffers
|
||||
VkPhysicalDeviceFeatures enabled_features{};
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
requested_extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (pgpu->conditional_render_support)
|
||||
{
|
||||
requested_extensions.push_back(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (pgpu->unrestricted_depth_range_support)
|
||||
{
|
||||
requested_extensions.push_back(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
enabled_features.robustBufferAccess = VK_TRUE;
|
||||
enabled_features.fullDrawIndexUint32 = VK_TRUE;
|
||||
enabled_features.independentBlend = VK_TRUE;
|
||||
enabled_features.logicOp = VK_TRUE;
|
||||
enabled_features.depthClamp = VK_TRUE;
|
||||
enabled_features.depthBounds = VK_TRUE;
|
||||
enabled_features.wideLines = VK_TRUE;
|
||||
enabled_features.largePoints = VK_TRUE;
|
||||
enabled_features.shaderFloat64 = VK_TRUE;
|
||||
|
||||
if (g_cfg.video.antialiasing_level != msaa_level::none)
|
||||
{
|
||||
// MSAA features
|
||||
if (!pgpu->features.shaderStorageImageMultisample || !pgpu->features.shaderStorageImageWriteWithoutFormat)
|
||||
{
|
||||
// TODO: Slow fallback to emulate this
|
||||
// Just warn and let the driver decide whether to crash or not
|
||||
rsx_log.fatal("Your GPU driver does not support some required MSAA features. Expect problems.");
|
||||
}
|
||||
|
||||
enabled_features.sampleRateShading = VK_TRUE;
|
||||
enabled_features.alphaToOne = VK_TRUE;
|
||||
enabled_features.shaderStorageImageMultisample = VK_TRUE;
|
||||
// enabled_features.shaderStorageImageReadWithoutFormat = VK_TRUE; // Unused currently, may be needed soon
|
||||
enabled_features.shaderStorageImageWriteWithoutFormat = VK_TRUE;
|
||||
}
|
||||
|
||||
// enabled_features.shaderSampledImageArrayDynamicIndexing = TRUE; // Unused currently but will be needed soon
|
||||
enabled_features.shaderClipDistance = VK_TRUE;
|
||||
// enabled_features.shaderCullDistance = VK_TRUE; // Alt notation of clip distance
|
||||
|
||||
enabled_features.samplerAnisotropy = VK_TRUE;
|
||||
enabled_features.textureCompressionBC = VK_TRUE;
|
||||
enabled_features.shaderStorageBufferArrayDynamicIndexing = VK_TRUE;
|
||||
|
||||
// Optionally disable unsupported stuff
|
||||
if (!pgpu->features.shaderFloat64)
|
||||
{
|
||||
rsx_log.error("Your GPU does not support double precision floats in shaders. Graphics may not work correctly.");
|
||||
enabled_features.shaderFloat64 = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.depthBounds)
|
||||
{
|
||||
rsx_log.error("Your GPU does not support depth bounds testing. Graphics may not work correctly.");
|
||||
enabled_features.depthBounds = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.sampleRateShading && enabled_features.sampleRateShading)
|
||||
{
|
||||
rsx_log.error("Your GPU does not support sample rate shading for multisampling. Graphics may be inaccurate when MSAA is enabled.");
|
||||
enabled_features.sampleRateShading = VK_FALSE;
|
||||
}
|
||||
|
||||
if (!pgpu->features.alphaToOne && enabled_features.alphaToOne)
|
||||
{
|
||||
// AMD proprietary drivers do not expose alphaToOne support
|
||||
rsx_log.error("Your GPU does not support alpha-to-one for multisampling. Graphics may be inaccurate when MSAA is enabled.");
|
||||
enabled_features.alphaToOne = VK_FALSE;
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo device = {};
|
||||
device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
device.pNext = nullptr;
|
||||
device.queueCreateInfoCount = 1;
|
||||
device.pQueueCreateInfos = &queue;
|
||||
device.enabledLayerCount = 0;
|
||||
device.ppEnabledLayerNames = nullptr; // Deprecated
|
||||
device.enabledExtensionCount = ::size32(requested_extensions);
|
||||
device.ppEnabledExtensionNames = requested_extensions.data();
|
||||
device.pEnabledFeatures = &enabled_features;
|
||||
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{};
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
// Allow use of f16 type in shaders if possible
|
||||
shader_support_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
|
||||
shader_support_info.shaderFloat16 = VK_TRUE;
|
||||
device.pNext = &shader_support_info;
|
||||
|
||||
rsx_log.notice("GPU/driver supports float16 data types natively. Using native float16_t variables if possible.");
|
||||
}
|
||||
else
|
||||
{
|
||||
rsx_log.notice("GPU/driver lacks support for float16 data types. All float16_t arithmetic will be emulated with float32_t.");
|
||||
}
|
||||
|
||||
CHECK_RESULT(vkCreateDevice(*pgpu, &device, nullptr, &dev));
|
||||
|
||||
// Import optional function endpoints
|
||||
if (pgpu->conditional_render_support)
|
||||
{
|
||||
cmdBeginConditionalRenderingEXT = reinterpret_cast<PFN_vkCmdBeginConditionalRenderingEXT>(vkGetDeviceProcAddr(dev, "vkCmdBeginConditionalRenderingEXT"));
|
||||
cmdEndConditionalRenderingEXT = reinterpret_cast<PFN_vkCmdEndConditionalRenderingEXT>(vkGetDeviceProcAddr(dev, "vkCmdEndConditionalRenderingEXT"));
|
||||
}
|
||||
|
||||
memory_map = vk::get_memory_mapping(pdev);
|
||||
m_formats_support = vk::get_optimal_tiling_supported_formats(pdev);
|
||||
m_pipeline_binding_table = vk::get_pipeline_binding_table(pdev);
|
||||
|
||||
if (g_cfg.video.disable_vulkan_mem_allocator)
|
||||
m_allocator = std::make_unique<vk::mem_allocator_vk>(dev, pdev);
|
||||
else
|
||||
m_allocator = std::make_unique<vk::mem_allocator_vma>(dev, pdev);
|
||||
}
|
||||
|
||||
void render_device::destroy()
|
||||
{
|
||||
if (dev && pgpu)
|
||||
{
|
||||
if (m_allocator)
|
||||
{
|
||||
m_allocator->destroy();
|
||||
m_allocator.reset();
|
||||
}
|
||||
|
||||
vkDestroyDevice(dev, nullptr);
|
||||
dev = nullptr;
|
||||
memory_map = {};
|
||||
m_formats_support = {};
|
||||
}
|
||||
}
|
||||
|
||||
const VkFormatProperties render_device::get_format_properties(VkFormat format)
|
||||
{
|
||||
auto found = pgpu->format_properties.find(format);
|
||||
if (found != pgpu->format_properties.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
auto& props = pgpu->format_properties[format];
|
||||
vkGetPhysicalDeviceFormatProperties(*pgpu, format, &props);
|
||||
return props;
|
||||
}
|
||||
|
||||
bool render_device::get_compatible_memory_type(u32 typeBits, u32 desired_mask, u32* type_index) const
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties mem_infos = pgpu->get_memory_properties();
|
||||
|
||||
for (u32 i = 0; i < 32; i++)
|
||||
{
|
||||
if ((typeBits & 1) == 1)
|
||||
{
|
||||
if ((mem_infos.memoryTypes[i].propertyFlags & desired_mask) == desired_mask)
|
||||
{
|
||||
if (type_index)
|
||||
{
|
||||
*type_index = i;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
typeBits >>= 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const physical_device& render_device::gpu() const
|
||||
{
|
||||
return *pgpu;
|
||||
}
|
||||
|
||||
const memory_type_mapping& render_device::get_memory_mapping() const
|
||||
{
|
||||
return memory_map;
|
||||
}
|
||||
|
||||
const gpu_formats_support& render_device::get_formats_support() const
|
||||
{
|
||||
return m_formats_support;
|
||||
}
|
||||
|
||||
const pipeline_binding_table& render_device::get_pipeline_binding_table() const
|
||||
{
|
||||
return m_pipeline_binding_table;
|
||||
}
|
||||
|
||||
const gpu_shader_types_support& render_device::get_shader_types_support() const
|
||||
{
|
||||
return pgpu->shader_types_support;
|
||||
}
|
||||
|
||||
bool render_device::get_shader_stencil_export_support() const
|
||||
{
|
||||
return pgpu->stencil_export_support;
|
||||
}
|
||||
|
||||
bool render_device::get_depth_bounds_support() const
|
||||
{
|
||||
return pgpu->features.depthBounds != VK_FALSE;
|
||||
}
|
||||
|
||||
bool render_device::get_alpha_to_one_support() const
|
||||
{
|
||||
return pgpu->features.alphaToOne != VK_FALSE;
|
||||
}
|
||||
|
||||
bool render_device::get_conditional_render_support() const
|
||||
{
|
||||
return pgpu->conditional_render_support;
|
||||
}
|
||||
|
||||
bool render_device::get_unrestricted_depth_range_support() const
|
||||
{
|
||||
return pgpu->unrestricted_depth_range_support;
|
||||
}
|
||||
|
||||
mem_allocator_base* render_device::get_allocator() const
|
||||
{
|
||||
return m_allocator.get();
|
||||
}
|
||||
|
||||
render_device::operator VkDevice() const
|
||||
{
|
||||
return dev;
|
||||
}
|
||||
}
|
51
rpcs3/Emu/RSX/VK/vkutils/render_device.h
Normal file
51
rpcs3/Emu/RSX/VK/vkutils/render_device.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "physical_device.h"
|
||||
#include <memory>
|
||||
|
||||
namespace vk
|
||||
{
|
||||
class mem_allocator_base;
|
||||
|
||||
class render_device
|
||||
{
|
||||
physical_device* pgpu = nullptr;
|
||||
memory_type_mapping memory_map{};
|
||||
gpu_formats_support m_formats_support{};
|
||||
pipeline_binding_table m_pipeline_binding_table{};
|
||||
std::unique_ptr<mem_allocator_base> m_allocator;
|
||||
VkDevice dev = VK_NULL_HANDLE;
|
||||
|
||||
public:
|
||||
// Exported device endpoints
|
||||
PFN_vkCmdBeginConditionalRenderingEXT cmdBeginConditionalRenderingEXT = nullptr;
|
||||
PFN_vkCmdEndConditionalRenderingEXT cmdEndConditionalRenderingEXT = nullptr;
|
||||
|
||||
public:
|
||||
render_device() = default;
|
||||
~render_device() = default;
|
||||
|
||||
void create(vk::physical_device& pdev, u32 graphics_queue_idx);
|
||||
void destroy();
|
||||
|
||||
const VkFormatProperties get_format_properties(VkFormat format);
|
||||
|
||||
bool get_compatible_memory_type(u32 typeBits, u32 desired_mask, u32* type_index) const;
|
||||
|
||||
const physical_device& gpu() const;
|
||||
const memory_type_mapping& get_memory_mapping() const;
|
||||
const gpu_formats_support& get_formats_support() const;
|
||||
const pipeline_binding_table& get_pipeline_binding_table() const;
|
||||
const gpu_shader_types_support& get_shader_types_support() const;
|
||||
|
||||
bool get_shader_stencil_export_support() const;
|
||||
bool get_depth_bounds_support() const;
|
||||
bool get_alpha_to_one_support() const;
|
||||
bool get_conditional_render_support() const;
|
||||
bool get_unrestricted_depth_range_support() const;
|
||||
|
||||
mem_allocator_base* get_allocator() const;
|
||||
|
||||
operator VkDevice() const;
|
||||
};
|
||||
}
|
@ -40,7 +40,9 @@
|
||||
<ClInclude Include="Emu\RSX\VK\VKShaderInterpreter.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\VKTextOut.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\VKTextureCache.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\buffer_view.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\chip_class.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\command_pool.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\fence.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\graphics_pipeline_state.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\memory_block.h" />
|
||||
@ -48,6 +50,7 @@
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\physical_device.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\pipeline_binding_table.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\query_pool.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\render_device.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\sampler.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\shared.h" />
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\supported_extensions.h" />
|
||||
@ -73,11 +76,14 @@
|
||||
<ClCompile Include="Emu\RSX\VK\VKResourceManager.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\VKShaderInterpreter.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\VKTexture.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\buffer_view.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\chip_class.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\command_pool.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\fence.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\memory_block.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\mem_allocator.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\physical_device.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\render_device.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\sampler.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\shared.cpp" />
|
||||
<ClCompile Include="Emu\RSX\VK\VKVertexBuffers.cpp" />
|
||||
|
@ -44,6 +44,15 @@
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\shared.cpp">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\buffer_view.cpp">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\render_device.cpp">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\VK\vkutils\command_pool.cpp">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" />
|
||||
@ -102,6 +111,15 @@
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\supported_extensions.h">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\buffer_view.h">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\render_device.h">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\VK\vkutils\command_pool.h">
|
||||
<Filter>vkutils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="vkutils">
|
||||
|
Loading…
Reference in New Issue
Block a user