mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02:00
6aa3846fb2
Add in-game performance panel Co-authored-by: nmzik <Nmzik@mail.ru>
156 lines
6.8 KiB
C++
156 lines
6.8 KiB
C++
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_
|
|
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_
|
|
|
|
#include "common/abi.h"
|
|
#include "common/common.h"
|
|
#include "common/threads.h"
|
|
#include "graphics/host_gpu/vulkanCommon.h" // IWYU pragma: export
|
|
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <span>
|
|
#include <tuple>
|
|
#include <vector>
|
|
#include <vk_mem_alloc.h>
|
|
|
|
namespace Libs::Graphics {
|
|
|
|
struct VulkanImage;
|
|
|
|
inline constexpr uint32_t VULKAN_TARGET_API_VERSION = VK_API_VERSION_1_3;
|
|
|
|
struct GraphicContext {
|
|
vk::Instance instance = nullptr;
|
|
vk::DebugUtilsMessengerEXT debug_messenger = nullptr;
|
|
vk::PhysicalDevice physical_device = nullptr;
|
|
vk::PhysicalDeviceProperties physical_device_properties = {};
|
|
vk::PhysicalDeviceMemoryProperties physical_device_memory_properties = {};
|
|
vk::Device device = nullptr;
|
|
VmaAllocator allocator = nullptr;
|
|
bool memory_budget_ext_enabled = false;
|
|
bool compute_subgroup_size_control_enabled = false;
|
|
bool sample_rate_shading_enabled = false;
|
|
bool shader_image_int64_atomics_enabled = false;
|
|
// bool fp64_denorm_preserve = false; // Temporarily disabled.
|
|
bool attachment_feedback_loop_enabled = false;
|
|
bool provoking_vertex_last_enabled = false;
|
|
bool maintenance8_enabled = false;
|
|
bool supports_block_texel_view = false;
|
|
bool mesh_shader_enabled = false;
|
|
vk::PhysicalDeviceMeshShaderPropertiesEXT mesh_shader_properties = {};
|
|
uint32_t subgroup_size = 0;
|
|
uint32_t min_subgroup_size = 0;
|
|
uint32_t max_subgroup_size = 0;
|
|
uint32_t max_push_descriptors = 0;
|
|
vk::ShaderStageFlags required_subgroup_size_stages = {};
|
|
Common::Mutex queue_mutex;
|
|
uint32_t queue_family = static_cast<uint32_t>(-1);
|
|
vk::Queue queue = nullptr;
|
|
|
|
[[nodiscard]] const vk::PhysicalDeviceProperties& GetPhysicalDeviceProperties() const {
|
|
return physical_device_properties;
|
|
}
|
|
|
|
[[nodiscard]] const vk::PhysicalDeviceMemoryProperties&
|
|
GetPhysicalDeviceMemoryProperties() const {
|
|
return physical_device_memory_properties;
|
|
}
|
|
|
|
[[nodiscard]] vk::FormatProperties GetFormatProperties(vk::Format format) const {
|
|
std::scoped_lock lock(m_format_properties_mutex);
|
|
auto [it, inserted] = m_format_properties.try_emplace(format);
|
|
if (inserted) {
|
|
physical_device.getFormatProperties(format, &it->second);
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
[[nodiscard]] vk::Result GetImageFormatProperties(vk::Format format, vk::ImageType type,
|
|
vk::ImageTiling tiling,
|
|
vk::ImageUsageFlags usage,
|
|
vk::ImageCreateFlags flags,
|
|
vk::ImageFormatProperties* properties) const {
|
|
using Key = std::tuple<vk::Format, vk::ImageType, vk::ImageTiling, vk::ImageUsageFlags,
|
|
vk::ImageCreateFlags>;
|
|
std::scoped_lock lock(m_image_format_properties_mutex);
|
|
auto [it, inserted] =
|
|
m_image_format_properties.try_emplace(Key {format, type, tiling, usage, flags});
|
|
if (inserted) {
|
|
it->second.first = physical_device.getImageFormatProperties(format, type, tiling, usage,
|
|
flags, &it->second.second);
|
|
}
|
|
if (properties != nullptr) {
|
|
*properties = it->second.second;
|
|
}
|
|
return it->second.first;
|
|
}
|
|
|
|
[[nodiscard]] bool SupportsComputeWave64() const noexcept {
|
|
return subgroup_size == 64u || compute_subgroup_size_control_enabled;
|
|
}
|
|
|
|
[[nodiscard]] vk::DeviceSize StorageMinAlignment() const {
|
|
const auto alignment = physical_device_properties.limits.minStorageBufferOffsetAlignment;
|
|
return alignment != 0 ? alignment : 1;
|
|
}
|
|
|
|
[[nodiscard]] bool CreateAllocator();
|
|
void DestroyAllocator();
|
|
void LogMemoryBudget() const;
|
|
[[nodiscard]] bool CanReportMemoryUsage() const noexcept { return memory_budget_ext_enabled; }
|
|
[[nodiscard]] uint64_t GetDeviceMemoryUsage() const;
|
|
[[nodiscard]] uint64_t GetTotalMemoryBudget() const;
|
|
|
|
struct HeapUsage {
|
|
uint64_t usage = 0; // Whole process, as reported by VK_EXT_memory_budget.
|
|
uint64_t budget = 0;
|
|
uint32_t allocations = 0;
|
|
bool device_local = false;
|
|
};
|
|
[[nodiscard]] uint32_t GetHeapUsage(std::span<HeapUsage, VK_MAX_MEMORY_HEAPS> heaps) const;
|
|
[[nodiscard]] bool CreateImage(const vk::ImageCreateInfo& info, VulkanImage& image);
|
|
void DeleteImage(VulkanImage& image);
|
|
|
|
uint32_t screen_width = 0;
|
|
uint32_t screen_height = 0;
|
|
|
|
private:
|
|
mutable std::mutex m_format_properties_mutex;
|
|
mutable std::map<vk::Format, vk::FormatProperties> m_format_properties;
|
|
mutable std::mutex m_image_format_properties_mutex;
|
|
mutable std::map<std::tuple<vk::Format, vk::ImageType, vk::ImageTiling, vk::ImageUsageFlags,
|
|
vk::ImageCreateFlags>,
|
|
std::pair<vk::Result, vk::ImageFormatProperties>>
|
|
m_image_format_properties;
|
|
};
|
|
|
|
struct VulkanImageState {
|
|
vk::PipelineStageFlags2 pl_stage = vk::PipelineStageFlagBits2::eAllCommands;
|
|
vk::AccessFlags2 access_mask = vk::AccessFlagBits2::eNone;
|
|
vk::ImageLayout layout = vk::ImageLayout::eUndefined;
|
|
};
|
|
|
|
struct VulkanImage {
|
|
VulkanImage() = default;
|
|
KYTY_CLASS_NO_COPY(VulkanImage);
|
|
|
|
vk::Format format = vk::Format::eUndefined;
|
|
vk::ImageType image_type = vk::ImageType::e2D;
|
|
vk::Extent3D extent = {1, 1, 1};
|
|
uint32_t layers = 1;
|
|
uint32_t mip_levels = 1;
|
|
uint32_t samples = 1;
|
|
vk::ImageUsageFlags usage = {};
|
|
vk::ImageCreateFlags flags = {};
|
|
vk::Image image = nullptr;
|
|
VulkanImageState state;
|
|
std::vector<VulkanImageState> subresource_states;
|
|
VmaAllocation allocation = nullptr;
|
|
};
|
|
|
|
|
|
|
|
} // namespace Libs::Graphics
|
|
|
|
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GRAPHICCONTEXT_H_ */
|