video_core/vulkan: Add debug object names (#7233)
* vk_platform: Add `SetObjectName` Creates a name-info struct and automatically deduces the object handle type using vulkan-hpp's handle trait data. Supports `string_view` and `fmt` arguments. * vk_texture_runtime: Use `SetObjectName` for surface handles Names both the image handle and the image-view. * vk_stream_buffer: Add debug object names Names the buffer and its device memory based on its size and type. * vk_swapchain: Set swapchain handle debug names Identifies the swapchain images themselves as well as the semaphores * vk_present_window: Set handle debug names * vk_resource_pool: Set debug handle names * vk_blit_helper: Set debug handle names * vk_platform: Use `VulkanHandleType` concept Use a new `concept`-type rather than `enable_if`-patterns to restrict this function to Vulkan handle-types only.
This commit is contained in:
parent
59df319f48
commit
4d9eedd0d8
7 changed files with 91 additions and 11 deletions
|
@ -198,7 +198,27 @@ BlitHelper::BlitHelper(const Instance& instance_, Scheduler& scheduler_, Descrip
|
||||||
MakeComputePipeline(depth_to_buffer_comp, compute_buffer_pipeline_layout)},
|
MakeComputePipeline(depth_to_buffer_comp, compute_buffer_pipeline_layout)},
|
||||||
depth_blit_pipeline{MakeDepthStencilBlitPipeline()},
|
depth_blit_pipeline{MakeDepthStencilBlitPipeline()},
|
||||||
linear_sampler{device.createSampler(SAMPLER_CREATE_INFO<vk::Filter::eLinear>)},
|
linear_sampler{device.createSampler(SAMPLER_CREATE_INFO<vk::Filter::eLinear>)},
|
||||||
nearest_sampler{device.createSampler(SAMPLER_CREATE_INFO<vk::Filter::eNearest>)} {}
|
nearest_sampler{device.createSampler(SAMPLER_CREATE_INFO<vk::Filter::eNearest>)} {
|
||||||
|
|
||||||
|
if (instance.HasDebuggingToolAttached()) {
|
||||||
|
SetObjectName(device, compute_pipeline_layout, "BlitHelper: compute_pipeline_layout");
|
||||||
|
SetObjectName(device, compute_buffer_pipeline_layout,
|
||||||
|
"BlitHelper: compute_buffer_pipeline_layout");
|
||||||
|
SetObjectName(device, two_textures_pipeline_layout,
|
||||||
|
"BlitHelper: two_textures_pipeline_layout");
|
||||||
|
SetObjectName(device, full_screen_vert, "BlitHelper: full_screen_vert");
|
||||||
|
SetObjectName(device, d24s8_to_rgba8_comp, "BlitHelper: d24s8_to_rgba8_comp");
|
||||||
|
SetObjectName(device, depth_to_buffer_comp, "BlitHelper: depth_to_buffer_comp");
|
||||||
|
SetObjectName(device, blit_depth_stencil_frag, "BlitHelper: blit_depth_stencil_frag");
|
||||||
|
SetObjectName(device, d24s8_to_rgba8_pipeline, "BlitHelper: d24s8_to_rgba8_pipeline");
|
||||||
|
SetObjectName(device, depth_to_buffer_pipeline, "BlitHelper: depth_to_buffer_pipeline");
|
||||||
|
if (depth_blit_pipeline) {
|
||||||
|
SetObjectName(device, depth_blit_pipeline, "BlitHelper: depth_blit_pipeline");
|
||||||
|
}
|
||||||
|
SetObjectName(device, linear_sampler, "BlitHelper: linear_sampler");
|
||||||
|
SetObjectName(device, nearest_sampler, "BlitHelper: nearest_sampler");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BlitHelper::~BlitHelper() {
|
BlitHelper::~BlitHelper() {
|
||||||
device.destroyPipelineLayout(compute_pipeline_layout);
|
device.destroyPipelineLayout(compute_pipeline_layout);
|
||||||
|
|
|
@ -33,4 +33,24 @@ vk::UniqueInstance CreateInstance(const Common::DynamicLibrary& library,
|
||||||
|
|
||||||
DebugCallback CreateDebugCallback(vk::Instance instance, bool& debug_utils_supported);
|
DebugCallback CreateDebugCallback(vk::Instance instance, bool& debug_utils_supported);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept VulkanHandleType = vk::isVulkanHandleType<T>::value;
|
||||||
|
|
||||||
|
template <VulkanHandleType HandleType>
|
||||||
|
void SetObjectName(vk::Device device, const HandleType& handle, std::string_view debug_name) {
|
||||||
|
const vk::DebugUtilsObjectNameInfoEXT name_info = {
|
||||||
|
.objectType = HandleType::objectType,
|
||||||
|
.objectHandle = reinterpret_cast<u64>(static_cast<typename HandleType::NativeType>(handle)),
|
||||||
|
.pObjectName = debug_name.data(),
|
||||||
|
};
|
||||||
|
device.setDebugUtilsObjectNameEXT(name_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <VulkanHandleType HandleType, typename... Args>
|
||||||
|
void SetObjectName(vk::Device device, const HandleType& handle, const char* format,
|
||||||
|
const Args&... args) {
|
||||||
|
const std::string debug_name = fmt::vformat(format, fmt::make_format_args(args...));
|
||||||
|
SetObjectName(device, handle, debug_name);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_present_window.h"
|
#include "video_core/renderer_vulkan/vk_present_window.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
|
#include "vk_platform.h"
|
||||||
|
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
|
@ -135,6 +136,16 @@ PresentWindow::PresentWindow(Frontend::EmuWindow& emu_window_, const Instance& i
|
||||||
free_queue.push(&frame);
|
free_queue.push(&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instance.HasDebuggingToolAttached()) {
|
||||||
|
for (u32 i = 0; i < num_images; ++i) {
|
||||||
|
Vulkan::SetObjectName(device, swap_chain[i].cmdbuf, "Swapchain Command Buffer {}", i);
|
||||||
|
Vulkan::SetObjectName(device, swap_chain[i].render_ready,
|
||||||
|
"Swapchain Semaphore: render_ready {}", i);
|
||||||
|
Vulkan::SetObjectName(device, swap_chain[i].present_done,
|
||||||
|
"Swapchain Fence: present_done {}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (use_present_thread) {
|
if (use_present_thread) {
|
||||||
present_thread = std::jthread([this](std::stop_token token) { PresentThread(token); });
|
present_thread = std::jthread([this](std::stop_token token) { PresentThread(token); });
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,15 @@ void CommandPool::Allocate(std::size_t begin, std::size_t end) {
|
||||||
|
|
||||||
auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
|
auto buffers = device.allocateCommandBuffers(buffer_alloc_info);
|
||||||
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin());
|
std::copy(buffers.begin(), buffers.end(), pool.cmdbufs.begin());
|
||||||
|
|
||||||
|
if (instance.HasDebuggingToolAttached()) {
|
||||||
|
Vulkan::SetObjectName(device, pool.handle, "CommandPool: Pool({})",
|
||||||
|
COMMAND_BUFFER_POOL_SIZE);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < pool.cmdbufs.size(); ++i) {
|
||||||
|
Vulkan::SetObjectName(device, pool.cmdbufs[i], "CommandPool: Command Buffer {}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::CommandBuffer CommandPool::Commit() {
|
vk::CommandBuffer CommandPool::Commit() {
|
||||||
|
|
|
@ -173,7 +173,7 @@ void StreamBuffer::CreateBuffers(u64 prefered_size) {
|
||||||
|
|
||||||
stream_buffer_size = static_cast<u64>(requirements.memoryRequirements.size);
|
stream_buffer_size = static_cast<u64>(requirements.memoryRequirements.size);
|
||||||
|
|
||||||
LOG_INFO(Render_Vulkan, "Creating {} buffer with size {} KB with flags {}",
|
LOG_INFO(Render_Vulkan, "Creating {} buffer with size {} KiB with flags {}",
|
||||||
BufferTypeName(type), stream_buffer_size / 1024,
|
BufferTypeName(type), stream_buffer_size / 1024,
|
||||||
vk::to_string(mem_type.propertyFlags));
|
vk::to_string(mem_type.propertyFlags));
|
||||||
|
|
||||||
|
@ -198,6 +198,14 @@ void StreamBuffer::CreateBuffers(u64 prefered_size) {
|
||||||
|
|
||||||
device.bindBufferMemory(buffer, memory, 0);
|
device.bindBufferMemory(buffer, memory, 0);
|
||||||
mapped = reinterpret_cast<u8*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
|
mapped = reinterpret_cast<u8*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
|
||||||
|
|
||||||
|
if (instance.HasDebuggingToolAttached()) {
|
||||||
|
Vulkan::SetObjectName(device, buffer, "StreamBuffer({}): {} KiB {}", BufferTypeName(type),
|
||||||
|
stream_buffer_size / 1024, vk::to_string(mem_type.propertyFlags));
|
||||||
|
Vulkan::SetObjectName(device, memory, "StreamBufferMemory({}): {} Kib {}",
|
||||||
|
BufferTypeName(type), stream_buffer_size / 1024,
|
||||||
|
vk::to_string(mem_type.propertyFlags));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamBuffer::ReserveWatches(std::vector<Watch>& watches, std::size_t grow_size) {
|
void StreamBuffer::ReserveWatches(std::vector<Watch>& watches, std::size_t grow_size) {
|
||||||
|
|
|
@ -247,12 +247,27 @@ void Swapchain::RefreshSemaphores() {
|
||||||
for (vk::Semaphore& semaphore : present_ready) {
|
for (vk::Semaphore& semaphore : present_ready) {
|
||||||
semaphore = device.createSemaphore({});
|
semaphore = device.createSemaphore({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instance.HasDebuggingToolAttached()) {
|
||||||
|
for (u32 i = 0; i < image_count; ++i) {
|
||||||
|
Vulkan::SetObjectName(device, image_acquired[i],
|
||||||
|
"Swapchain Semaphore: image_acquired {}", i);
|
||||||
|
Vulkan::SetObjectName(device, present_ready[i], "Swapchain Semaphore: present_ready {}",
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::SetupImages() {
|
void Swapchain::SetupImages() {
|
||||||
vk::Device device = instance.GetDevice();
|
vk::Device device = instance.GetDevice();
|
||||||
images = device.getSwapchainImagesKHR(swapchain);
|
images = device.getSwapchainImagesKHR(swapchain);
|
||||||
image_count = static_cast<u32>(images.size());
|
image_count = static_cast<u32>(images.size());
|
||||||
|
|
||||||
|
if (instance.HasDebuggingToolAttached()) {
|
||||||
|
for (u32 i = 0; i < image_count; ++i) {
|
||||||
|
Vulkan::SetObjectName(device, images[i], "Swapchain Image {}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -189,15 +189,6 @@ Handle MakeHandle(const Instance* instance, u32 width, u32 height, u32 levels, T
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug_name.empty() && instance->HasDebuggingToolAttached()) {
|
|
||||||
const vk::DebugUtilsObjectNameInfoEXT name_info = {
|
|
||||||
.objectType = vk::ObjectType::eImage,
|
|
||||||
.objectHandle = reinterpret_cast<u64>(unsafe_image),
|
|
||||||
.pObjectName = debug_name.data(),
|
|
||||||
};
|
|
||||||
instance->GetDevice().setDebugUtilsObjectNameEXT(name_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
const vk::Image image{unsafe_image};
|
const vk::Image image{unsafe_image};
|
||||||
const vk::ImageViewCreateInfo view_info = {
|
const vk::ImageViewCreateInfo view_info = {
|
||||||
.image = image,
|
.image = image,
|
||||||
|
@ -214,6 +205,12 @@ Handle MakeHandle(const Instance* instance, u32 width, u32 height, u32 levels, T
|
||||||
};
|
};
|
||||||
vk::UniqueImageView image_view = instance->GetDevice().createImageViewUnique(view_info);
|
vk::UniqueImageView image_view = instance->GetDevice().createImageViewUnique(view_info);
|
||||||
|
|
||||||
|
if (!debug_name.empty() && instance->HasDebuggingToolAttached()) {
|
||||||
|
Vulkan::SetObjectName(instance->GetDevice(), image, debug_name);
|
||||||
|
Vulkan::SetObjectName(instance->GetDevice(), image_view.get(), "{} View({})", debug_name,
|
||||||
|
vk::to_string(aspect));
|
||||||
|
}
|
||||||
|
|
||||||
return Handle{
|
return Handle{
|
||||||
.alloc = allocation,
|
.alloc = allocation,
|
||||||
.image = image,
|
.image = image,
|
||||||
|
|
Loading…
Reference in a new issue