GPU/Vulkan: Add debug utility functions

Adds a way to set the name of vulkan
objects, and automatically determining their `VkObjectType` enum value
at compile-time. As well as a utility-object for creating debug-scopes
for `VkQueue` and `VkCommandBuffer` objects. `DebugScope` objects will
automatically emit `Begin` and `End` commands within the ctor and dtor
and allow for C++ scopes to name and color sections of a vulkan command.
These DebugScopes are also able to be nested within each other and will
automatically pick a color depending on the current recursive depth.

These functions are all null-stubbed in non-debug compilations.
This commit is contained in:
Wunkolo 2021-07-23 16:46:01 -07:00
parent 494b6e029f
commit 98089180c0
7 changed files with 579 additions and 44 deletions

View File

@ -209,7 +209,7 @@ bool Context::SelectInstanceExtensions(ExtensionList* extension_list, const Wind
if (wi && wi->type == WindowInfo::Type::Display && !SupportsExtension(VK_KHR_DISPLAY_EXTENSION_NAME, true))
return false;
// VK_EXT_debug_utils
// VK_EXT_debug_utils
if (enable_debug_utils && !SupportsExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, false))
Log_WarningPrintf("Vulkan: Debug report requested, but extension is not available.");
@ -632,6 +632,7 @@ bool Context::CreateCommandBuffers()
{
VkResult res;
uint32_t frame_index = 0;
for (FrameResources& resources : m_frame_resources)
{
resources.needs_fence_wait = false;
@ -644,6 +645,8 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.command_pool, "Frame Command Pool %u",
frame_index);
VkCommandBufferAllocateInfo buffer_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr,
resources.command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
@ -654,6 +657,8 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkAllocateCommandBuffers failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.command_buffer, "Frame Command Buffer %u",
frame_index);
VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT};
@ -663,7 +668,7 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkCreateFence failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.fence, "Frame Fence %u", frame_index);
// TODO: A better way to choose the number of descriptors.
VkDescriptorPoolSize pool_sizes[] = {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1024},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024},
@ -683,6 +688,10 @@ bool Context::CreateCommandBuffers()
LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), resources.descriptor_pool, "Frame Descriptor Pool %u",
frame_index);
++frame_index;
}
ActivateCommandBuffer(0);
@ -741,7 +750,7 @@ bool Context::CreateGlobalDescriptorPool()
LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: ");
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_global_descriptor_pool, "Global Descriptor Pool");
return true;
}
@ -909,6 +918,7 @@ void Context::DoSubmitCommandBuffer(u32 index, VkSemaphore wait_semaphore, VkSem
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &signal_semaphore;
}
const Vulkan::Util::DebugScope debugScope(m_graphics_queue, "Context::DoSubmitCommandBuffer: %u", index);
VkResult res = vkQueueSubmit(m_graphics_queue, 1, &submit_info, resources.fence);
if (res != VK_SUCCESS)
@ -930,7 +940,7 @@ void Context::DoPresent(VkSemaphore wait_semaphore, VkSwapchainKHR present_swap_
&present_swap_chain,
&present_image_index,
nullptr};
const Vulkan::Util::DebugScope debugScope(m_present_queue, "Context::DoPresent: %u", present_image_index);
VkResult res = vkQueuePresentKHR(m_present_queue, &present_info);
if (res != VK_SUCCESS)
{
@ -1103,11 +1113,10 @@ void Context::DeferPipelineDestruction(VkPipeline pipeline)
resources.cleanup_resources.push_back([this, pipeline]() { vkDestroyPipeline(m_device, pipeline, nullptr); });
}
VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
LOGLEVEL level;
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
@ -1137,10 +1146,15 @@ bool Context::EnableDebugUtils()
}
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {
VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, nullptr, 0,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
DebugMessengerCallback, nullptr};
VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
nullptr,
0,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
DebugMessengerCallback,
nullptr};
VkResult res = vkCreateDebugUtilsMessengerEXT(m_instance, &messenger_info, nullptr, &m_debug_messenger_callback);
if (res != VK_SUCCESS)

View File

@ -100,6 +100,10 @@ void StagingTexture::CopyFromTexture(VkCommandBuffer command_buffer, Texture& sr
Assert((src_x + width) <= src_texture.GetWidth() && (src_y + height) <= src_texture.GetHeight());
Assert((dst_x + width) <= m_width && (dst_y + height) <= m_height);
const Vulkan::Util::DebugScope debugScope(command_buffer,
"StagingTexture::CopyFromTexture: {%u,%u} Lyr:%u Lvl:%u {%u,%u} %ux%u",
src_x, src_y, src_layer, src_level, dst_x, dst_y, width, height);
VkImageLayout old_layout = src_texture.GetLayout();
src_texture.TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
@ -123,6 +127,9 @@ void StagingTexture::CopyFromTexture(VkCommandBuffer command_buffer, Texture& sr
void StagingTexture::CopyFromTexture(Texture& src_texture, u32 src_x, u32 src_y, u32 src_layer, u32 src_level,
u32 dst_x, u32 dst_y, u32 width, u32 height)
{
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"StagingTexture::CopyFromTexture: {%u,%u} Lyr:%u Lvl:%u {%u,%u} %ux%u",
src_x, src_y, src_layer, src_level, dst_x, dst_y, width, height);
CopyFromTexture(g_vulkan_context->GetCurrentCommandBuffer(), src_texture, src_x, src_y, src_layer, src_level, dst_x,
dst_y, width, height);
@ -162,6 +169,9 @@ void StagingTexture::CopyToTexture(VkCommandBuffer command_buffer, u32 src_x, u3
void StagingTexture::CopyToTexture(u32 src_x, u32 src_y, Texture& dst_texture, u32 dst_x, u32 dst_y, u32 dst_layer,
u32 dst_level, u32 width, u32 height)
{
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"StagingTexture::CopyToTexture: {%u,%u} | {%u,%u} Lyr:%u Lvl:%u %ux%u",
src_x, src_y, dst_x, dst_y, dst_layer, dst_level, width, height);
CopyToTexture(g_vulkan_context->GetCurrentCommandBuffer(), src_x, src_y, dst_texture, dst_x, dst_y, dst_layer,
dst_level, width, height);

View File

@ -239,6 +239,8 @@ void Texture::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout n
{
if (m_layout == new_layout)
return;
const Vulkan::Util::DebugScope debugScope(command_buffer, "Texture::TransitionToLayout: %s",
Vulkan::Util::VkImageLayoutToString(new_layout));
TransitionSubresourcesToLayout(command_buffer, 0, m_levels, 0, m_layers, m_layout, new_layout);
@ -249,6 +251,11 @@ void Texture::TransitionSubresourcesToLayout(VkCommandBuffer command_buffer, u32
u32 start_layer, u32 num_layers, VkImageLayout old_layout,
VkImageLayout new_layout)
{
const Vulkan::Util::DebugScope debugScope(
command_buffer, "Texture::TransitionSubresourcesToLayout: Lvl:[%u,%u) Lyr:[%u,%u) %s -> %s", start_level,
start_level + num_levels, start_layer, start_layer + num_layers, Vulkan::Util::VkImageLayoutToString(old_layout),
Vulkan::Util::VkImageLayoutToString(new_layout));
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
@ -359,7 +366,6 @@ void Texture::TransitionSubresourcesToLayout(VkCommandBuffer command_buffer, u32
dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break;
}
vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &barrier);
}
@ -382,6 +388,8 @@ void Texture::UpdateFromBuffer(VkCommandBuffer cmdbuf, u32 level, u32 layer, u32
VkBuffer buffer, u32 buffer_offset)
{
const VkImageLayout old_layout = m_layout;
const Vulkan::Util::DebugScope debugScope(cmdbuf, "Texture::UpdateFromBuffer: Lvl:%u Lyr:%u {%u,%u} %ux%u", level,
layer, x, y, width, height);
TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
const VkBufferImageCopy bic = {static_cast<VkDeviceSize>(buffer_offset),

View File

@ -10,6 +10,8 @@
#include "context.h"
#include "shader_compiler.h"
#include <cmath>
namespace Vulkan {
namespace Util {
bool IsDepthFormat(VkFormat format)
@ -417,6 +419,71 @@ const char* VkResultToString(VkResult res)
return "UNKNOWN_VK_RESULT";
}
}
const char* VkImageLayoutToString(VkImageLayout layout)
{
switch (layout)
{
case VK_IMAGE_LAYOUT_UNDEFINED:
return "VK_IMAGE_LAYOUT_UNDEFINED";
case VK_IMAGE_LAYOUT_GENERAL:
return "VK_IMAGE_LAYOUT_GENERAL";
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
return "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL";
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL";
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
return "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL";
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
return "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL";
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
return "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL";
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
return "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL";
case VK_IMAGE_LAYOUT_PREINITIALIZED:
return "VK_IMAGE_LAYOUT_PREINITIALIZED";
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL";
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL";
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
return "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL";
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
return "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL";
case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
return "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL";
case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
return "VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL";
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
return "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR";
case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
return "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR";
case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV:
return "VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV";
case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
return "VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT";
default:
return "UNKNOWN_VK_RESULT";
}
}
void LogVulkanResult(int level, const char* func_name, VkResult res, const char* msg, ...)
{
@ -429,6 +496,78 @@ void LogVulkanResult(int level, const char* func_name, VkResult res, const char*
static_cast<int>(res), VkResultToString(res));
}
#ifdef _DEBUG
u8 DebugScope<VkCommandBuffer>::depth = 0;
u8 DebugScope<VkQueue>::depth = 0;
static std::array<float, 4> Palette(float phase, const std::array<float, 3>& a, const std::array<float, 3>& b,
const std::array<float, 3>& c, const std::array<float, 3>& d)
{
std::array<float, 4> result;
result[0] = a[0] + b[0] * std::cos(6.28318f * (c[0] * phase + d[0]));
result[1] = a[1] + b[1] * std::cos(6.28318f * (c[1] * phase + d[1]));
result[2] = a[2] + b[2] * std::cos(6.28318f * (c[2] * phase + d[2]));
result[3] = 1.0f;
return result;
}
DebugScope<VkCommandBuffer>::DebugScope(VkCommandBuffer context, const char* format, ...) : command_buffer(context)
{
if (command_buffer)
{
std::va_list ap;
SmallString str;
va_start(ap, format);
str.FormatVA(format, ap);
va_end(ap);
++depth;
const float depth_phase = depth / static_cast<float>(max_depth);
BeginDebugScope(command_buffer, str,
Palette(depth_phase, {0.5, 0.5, 0.5}, {0.5, 0.5, 0.5}, {1.0, 1.0, 0.5}, {0.8, 0.90, 0.30}));
}
}
DebugScope<VkCommandBuffer>::~DebugScope()
{
if (command_buffer)
{
--depth;
EndDebugScope(command_buffer);
}
}
DebugScope<VkQueue>::DebugScope(VkQueue context, const char* format, ...) : queue(context)
{
if (queue)
{
std::va_list ap;
va_start(ap, format);
SmallString str;
str.FormatVA(format, ap);
va_end(ap);
const float depth_phase = depth / static_cast<float>(max_depth);
BeginDebugScope(queue, str,
Palette(depth_phase, {0.5, 0.5, 0.5}, {0.5, 0.5, 0.5}, {2.0, 1.0, 0.0}, {0.5, 0.20, 0.25}));
++depth;
}
}
DebugScope<VkQueue>::~DebugScope()
{
if (queue)
{
--depth;
EndDebugScope(queue);
}
}
#endif
} // namespace Util
} // namespace Vulkan

View File

@ -5,11 +5,13 @@
#pragma once
#include "../string.h"
#include "../types.h"
#include "vulkan_loader.h"
#include <algorithm>
#include <array>
#include <cstdarg>
#include <string_view>
namespace Vulkan {
namespace Util {
@ -74,10 +76,202 @@ VkShaderModule CompileAndCreateFragmentShader(std::string_view source_code);
VkShaderModule CompileAndCreateComputeShader(std::string_view source_code);
const char* VkResultToString(VkResult res);
const char* VkImageLayoutToString(VkImageLayout layout);
void LogVulkanResult(int level, const char* func_name, VkResult res, const char* msg, ...) printflike(4, 5);
#define LOG_VULKAN_ERROR(res, ...) ::Vulkan::Util::LogVulkanResult(1, __func__, res, __VA_ARGS__)
// Provides a compile-time mapping between a Vulkan-type into its matching VkObjectType
template<typename T>
struct VkObjectTypeMap;
// clang-format off
template<> struct VkObjectTypeMap<VkInstance > { using type = VkInstance ; static constexpr VkObjectType value = VK_OBJECT_TYPE_INSTANCE; };
template<> struct VkObjectTypeMap<VkPhysicalDevice > { using type = VkPhysicalDevice ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PHYSICAL_DEVICE; };
template<> struct VkObjectTypeMap<VkDevice > { using type = VkDevice ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DEVICE; };
template<> struct VkObjectTypeMap<VkQueue > { using type = VkQueue ; static constexpr VkObjectType value = VK_OBJECT_TYPE_QUEUE; };
template<> struct VkObjectTypeMap<VkSemaphore > { using type = VkSemaphore ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SEMAPHORE; };
template<> struct VkObjectTypeMap<VkCommandBuffer > { using type = VkCommandBuffer ; static constexpr VkObjectType value = VK_OBJECT_TYPE_COMMAND_BUFFER; };
template<> struct VkObjectTypeMap<VkFence > { using type = VkFence ; static constexpr VkObjectType value = VK_OBJECT_TYPE_FENCE; };
template<> struct VkObjectTypeMap<VkDeviceMemory > { using type = VkDeviceMemory ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DEVICE_MEMORY; };
template<> struct VkObjectTypeMap<VkBuffer > { using type = VkBuffer ; static constexpr VkObjectType value = VK_OBJECT_TYPE_BUFFER; };
template<> struct VkObjectTypeMap<VkImage > { using type = VkImage ; static constexpr VkObjectType value = VK_OBJECT_TYPE_IMAGE; };
template<> struct VkObjectTypeMap<VkEvent > { using type = VkEvent ; static constexpr VkObjectType value = VK_OBJECT_TYPE_EVENT; };
template<> struct VkObjectTypeMap<VkQueryPool > { using type = VkQueryPool ; static constexpr VkObjectType value = VK_OBJECT_TYPE_QUERY_POOL; };
template<> struct VkObjectTypeMap<VkBufferView > { using type = VkBufferView ; static constexpr VkObjectType value = VK_OBJECT_TYPE_BUFFER_VIEW; };
template<> struct VkObjectTypeMap<VkImageView > { using type = VkImageView ; static constexpr VkObjectType value = VK_OBJECT_TYPE_IMAGE_VIEW; };
template<> struct VkObjectTypeMap<VkShaderModule > { using type = VkShaderModule ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SHADER_MODULE; };
template<> struct VkObjectTypeMap<VkPipelineCache > { using type = VkPipelineCache ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PIPELINE_CACHE; };
template<> struct VkObjectTypeMap<VkPipelineLayout > { using type = VkPipelineLayout ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PIPELINE_LAYOUT; };
template<> struct VkObjectTypeMap<VkRenderPass > { using type = VkRenderPass ; static constexpr VkObjectType value = VK_OBJECT_TYPE_RENDER_PASS; };
template<> struct VkObjectTypeMap<VkPipeline > { using type = VkPipeline ; static constexpr VkObjectType value = VK_OBJECT_TYPE_PIPELINE; };
template<> struct VkObjectTypeMap<VkDescriptorSetLayout > { using type = VkDescriptorSetLayout ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT; };
template<> struct VkObjectTypeMap<VkSampler > { using type = VkSampler ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SAMPLER; };
template<> struct VkObjectTypeMap<VkDescriptorPool > { using type = VkDescriptorPool ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_POOL; };
template<> struct VkObjectTypeMap<VkDescriptorSet > { using type = VkDescriptorSet ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_SET; };
template<> struct VkObjectTypeMap<VkFramebuffer > { using type = VkFramebuffer ; static constexpr VkObjectType value = VK_OBJECT_TYPE_FRAMEBUFFER; };
template<> struct VkObjectTypeMap<VkCommandPool > { using type = VkCommandPool ; static constexpr VkObjectType value = VK_OBJECT_TYPE_COMMAND_POOL; };
template<> struct VkObjectTypeMap<VkDescriptorUpdateTemplate> { using type = VkDescriptorUpdateTemplate; static constexpr VkObjectType value = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE; };
template<> struct VkObjectTypeMap<VkSurfaceKHR > { using type = VkSurfaceKHR ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SURFACE_KHR; };
template<> struct VkObjectTypeMap<VkSwapchainKHR > { using type = VkSwapchainKHR ; static constexpr VkObjectType value = VK_OBJECT_TYPE_SWAPCHAIN_KHR; };
template<> struct VkObjectTypeMap<VkDebugUtilsMessengerEXT > { using type = VkDebugUtilsMessengerEXT ; static constexpr VkObjectType value = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT; };
// clang-format on
inline void SetObjectName(VkDevice device, void* object_handle, VkObjectType object_type, const char* format, ...)
{
#ifdef _DEBUG
if (!vkSetDebugUtilsObjectNameEXT)
{
return;
}
std::va_list ap;
SmallString str;
va_start(ap, format);
str.FormatVA(format, ap);
va_end(ap);
const VkDebugUtilsObjectNameInfoEXT nameInfo{VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, nullptr, object_type,
reinterpret_cast<uint64_t>(object_handle), str};
vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
#endif
}
template<typename T>
inline void SetObjectName(VkDevice device, T object_handle, const char* format, ...)
{
#ifdef _DEBUG
std::va_list ap;
va_start(ap, format);
SetObjectName(device, reinterpret_cast<void*>((typename VkObjectTypeMap<T>::type)object_handle),
VkObjectTypeMap<T>::value, format, ap);
va_end(ap);
#endif
}
// Command buffer debug utils
inline void BeginDebugScope(VkCommandBuffer command_buffer, const char* scope_name,
const std::array<float, 4>& scope_color = {0.5, 0.5, 0.5, 1.0})
{
#ifdef _DEBUG
if (!vkCmdBeginDebugUtilsLabelEXT)
{
return;
}
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
nullptr,
scope_name,
{scope_color[0], scope_color[1], scope_color[2], scope_color[3]}};
vkCmdBeginDebugUtilsLabelEXT(command_buffer, &label);
#endif
}
inline void EndDebugScope(VkCommandBuffer command_buffer)
{
#ifdef _DEBUG
if (!vkCmdEndDebugUtilsLabelEXT)
{
return;
}
vkCmdEndDebugUtilsLabelEXT(command_buffer);
#endif
}
inline void InsertDebugLabel(VkCommandBuffer command_buffer, const char* label_name,
const std::array<float, 4>& label_color = {0.5, 0.5, 0.5, 1.0})
{
#ifdef _DEBUG
if (!vkCmdInsertDebugUtilsLabelEXT)
{
return;
}
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
nullptr,
label_name,
{label_color[0], label_color[1], label_color[2], label_color[3]}};
vkCmdInsertDebugUtilsLabelEXT(command_buffer, &label);
#endif
}
// Queue debug utils
inline void BeginDebugScope(VkQueue queue, const char* scope_name,
const std::array<float, 4>& scope_color = {0.75, 0.75, 0.75, 1.0})
{
#ifdef _DEBUG
if (!vkQueueBeginDebugUtilsLabelEXT)
{
return;
}
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
nullptr,
scope_name,
{scope_color[0], scope_color[1], scope_color[2], scope_color[3]}};
vkQueueBeginDebugUtilsLabelEXT(queue, &label);
#endif
}
inline void EndDebugScope(VkQueue queue)
{
#ifdef _DEBUG
if (!vkQueueEndDebugUtilsLabelEXT)
{
return;
}
vkQueueEndDebugUtilsLabelEXT(queue);
#endif
}
inline void InsertDebugLabel(VkQueue queue, const char* label_name,
const std::array<float, 4>& label_color = {0.75, 0.75, 0.75, 1.0})
{
#ifdef _DEBUG
if (!vkQueueInsertDebugUtilsLabelEXT)
{
return;
}
const VkDebugUtilsLabelEXT label{VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
nullptr,
label_name,
{label_color[0], label_color[1], label_color[2], label_color[3]}};
vkQueueInsertDebugUtilsLabelEXT(queue, &label);
#endif
}
template<typename T>
class DebugScope
{
public:
DebugScope(T context, const char* format, ...) {}
};
#ifdef _DEBUG
template<>
class DebugScope<VkCommandBuffer>
{
public:
DebugScope(VkCommandBuffer context, const char* format, ...);
~DebugScope();
private:
static constexpr u8 max_depth = 8u;
static u8 depth;
VkCommandBuffer command_buffer;
};
template<>
class DebugScope<VkQueue>
{
public:
DebugScope(VkQueue context, const char* format, ...);
~DebugScope();
private:
static constexpr u8 max_depth = 8u;
static u8 depth;
VkQueue queue;
};
#endif
} // namespace Util
} // namespace Vulkan

View File

@ -115,6 +115,9 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
{0, 0, 0},
{m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1u}};
VkCommandBuffer buf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(buf, "GPU_HW_Vulkan::DoState");
if (sw.IsReading())
{
Vulkan::Texture* tex = static_cast<Vulkan::Texture*>((*host_texture)->GetHandle());
@ -124,7 +127,6 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
return false;
}
VkCommandBuffer buf = g_vulkan_context->GetCurrentCommandBuffer();
const VkImageLayout old_tex_layout = tex->GetLayout();
const VkImageLayout old_vram_layout = m_vram_texture.GetLayout();
tex->TransitionToLayout(buf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
@ -158,7 +160,6 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
return false;
}
VkCommandBuffer buf = g_vulkan_context->GetCurrentCommandBuffer();
const VkImageLayout old_vram_layout = m_vram_texture.GetLayout();
tex->TransitionToLayout(buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
m_vram_texture.TransitionToLayout(buf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
@ -191,6 +192,7 @@ void GPU_HW_Vulkan::ResetGraphicsAPIState()
void GPU_HW_Vulkan::RestoreGraphicsAPIState()
{
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::RestoreGraphicsAPIState");
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkDeviceSize vertex_buffer_offset = 0;
@ -389,6 +391,7 @@ void GPU_HW_Vulkan::BeginRenderPass(VkRenderPass render_pass, VkFramebuffer fram
{{static_cast<s32>(x), static_cast<s32>(y)}, {width, height}},
(clear_value ? 1u : 0u),
clear_value};
Vulkan::Util::BeginDebugScope(g_vulkan_context->GetCurrentCommandBuffer(), "GPU_HW_Vulkan::BeginRenderPass");
vkCmdBeginRenderPass(g_vulkan_context->GetCurrentCommandBuffer(), &bi, VK_SUBPASS_CONTENTS_INLINE);
m_current_render_pass = render_pass;
}
@ -408,6 +411,7 @@ void GPU_HW_Vulkan::EndRenderPass()
return;
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
Vulkan::Util::EndDebugScope(g_vulkan_context->GetCurrentCommandBuffer());
m_current_render_pass = VK_NULL_HANDLE;
}
@ -432,11 +436,16 @@ bool GPU_HW_Vulkan::CreatePipelineLayouts()
if (m_batch_descriptor_set_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_batch_descriptor_set_layout,
"Batch Descriptor Set Layout");
// textures start at 1
dslbuilder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
m_single_sampler_descriptor_set_layout = dslbuilder.Create(device);
if (m_single_sampler_descriptor_set_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_single_sampler_descriptor_set_layout,
"Single Sampler Descriptor Set Layout");
if (m_use_ssbos_for_vram_writes)
dslbuilder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
@ -445,47 +454,64 @@ bool GPU_HW_Vulkan::CreatePipelineLayouts()
m_vram_write_descriptor_set_layout = dslbuilder.Create(device);
if (m_vram_write_descriptor_set_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_write_descriptor_set_layout,
"VRAM Write Descriptor Set Layout");
Vulkan::PipelineLayoutBuilder plbuilder;
plbuilder.AddDescriptorSet(m_batch_descriptor_set_layout);
m_batch_pipeline_layout = plbuilder.Create(device);
if (m_batch_pipeline_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_batch_pipeline_layout, "Batch Pipeline Layout");
plbuilder.AddDescriptorSet(m_single_sampler_descriptor_set_layout);
plbuilder.AddPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT, 0, MAX_PUSH_CONSTANTS_SIZE);
m_single_sampler_pipeline_layout = plbuilder.Create(device);
if (m_single_sampler_pipeline_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_single_sampler_pipeline_layout,
"Single Sampler Pipeline Layout");
plbuilder.AddPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT, 0, MAX_PUSH_CONSTANTS_SIZE);
m_no_samplers_pipeline_layout = plbuilder.Create(device);
if (m_no_samplers_pipeline_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_no_samplers_pipeline_layout,
"No Samplers Pipeline Layout");
plbuilder.AddDescriptorSet(m_vram_write_descriptor_set_layout);
plbuilder.AddPushConstants(VK_SHADER_STAGE_FRAGMENT_BIT, 0, MAX_PUSH_CONSTANTS_SIZE);
m_vram_write_pipeline_layout = plbuilder.Create(device);
if (m_vram_write_pipeline_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_write_pipeline_layout,
"VRAM Write Pipeline Layout");
plbuilder.AddDescriptorSet(m_single_sampler_descriptor_set_layout);
plbuilder.AddPushConstants(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, MAX_PUSH_CONSTANTS_SIZE);
m_downsample_pipeline_layout = plbuilder.Create(device);
if (m_downsample_pipeline_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_pipeline_layout,
"Downsample Pipeline Layout");
dslbuilder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslbuilder.AddBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
m_downsample_composite_descriptor_set_layout = dslbuilder.Create(device);
if (m_downsample_composite_descriptor_set_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(),
m_downsample_composite_descriptor_set_layout,
"Downsample Composite Descriptor Set Layout");
plbuilder.AddDescriptorSet(m_downsample_composite_descriptor_set_layout);
plbuilder.AddPushConstants(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, MAX_PUSH_CONSTANTS_SIZE);
m_downsample_composite_pipeline_layout = plbuilder.Create(device);
if (m_downsample_composite_pipeline_layout == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_composite_pipeline_layout,
"Downsample Composite Pipeline Layout");
return true;
}
@ -501,6 +527,7 @@ bool GPU_HW_Vulkan::CreateSamplers()
m_point_sampler = sbuilder.Create(device);
if (m_point_sampler == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_point_sampler, "Point Sampler");
sbuilder.SetLinearSampler(false, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
sbuilder.SetAddressMode(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
@ -508,11 +535,13 @@ bool GPU_HW_Vulkan::CreateSamplers()
m_linear_sampler = sbuilder.Create(device);
if (m_linear_sampler == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_linear_sampler, "Linear Sampler");
sbuilder.SetLinearSampler(true, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
m_trilinear_sampler = sbuilder.Create(device);
if (m_trilinear_sampler == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_trilinear_sampler, "Trilinear Sampler");
return true;
}
@ -553,6 +582,32 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_texture.GetImage(), "VRAM Texture");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_texture.GetView(), "VRAM Texture View");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_texture.GetDeviceMemory(), "VRAM Texture Memory");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_depth_texture.GetImage(), "VRAM Depth Texture");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_depth_texture.GetView(), "VRAM Depth Texture View");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_depth_texture.GetDeviceMemory(),
"VRAM Depth Texture Memory");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_read_texture.GetImage(), "VRAM Read Texture");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_read_texture.GetView(), "VRAM Read Texture View");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_read_texture.GetDeviceMemory(),
"VRAM Read Texture Memory");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_display_texture.GetImage(), "Display Texture");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_display_texture.GetView(), "Display Texture View");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_display_texture.GetDeviceMemory(),
"Display Texture Memory");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_readback_texture.GetImage(),
"VRAM Readback Texture");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_readback_texture.GetView(),
"VRAM Readback Texture View");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_readback_texture.GetDeviceMemory(),
"VRAM Readback Texture Memory");
m_vram_render_pass =
g_vulkan_context->GetRenderPass(texture_format, depth_format, samples, VK_ATTACHMENT_LOAD_OP_LOAD);
m_vram_update_depth_render_pass =
@ -572,6 +627,12 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_render_pass, "VRAM Render Pass");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_update_depth_render_pass,
"VRAM Update Depth Render Pass");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_display_load_render_pass, "Display Load Render Pass");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_readback_render_pass, "VRAM Readback Render Pass");
// vram framebuffer has both colour and depth
Vulkan::FramebufferBuilder fbb;
fbb.AddAttachment(m_vram_texture.GetView());
@ -581,6 +642,7 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
m_vram_framebuffer = fbb.Create(g_vulkan_context->GetDevice());
if (m_vram_framebuffer == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_framebuffer, "VRAM Framebuffer");
m_vram_update_depth_framebuffer = m_vram_depth_texture.CreateFramebuffer(m_vram_update_depth_render_pass);
m_vram_readback_framebuffer = m_vram_readback_texture.CreateFramebuffer(m_vram_readback_render_pass);
@ -590,8 +652,14 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
{
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_update_depth_framebuffer,
"VRAM Update Depth Framebuffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_readback_framebuffer, "VRAM Readback Framebuffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_display_framebuffer, "Display Framebuffer");
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::CreateFramebuffer");
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
m_vram_depth_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
m_vram_read_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@ -780,12 +848,26 @@ void GPU_HW_Vulkan::DestroyFramebuffer()
bool GPU_HW_Vulkan::CreateVertexBuffer()
{
return m_vertex_stream_buffer.Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VERTEX_BUFFER_SIZE);
if (!m_vertex_stream_buffer.Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VERTEX_BUFFER_SIZE))
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vertex_stream_buffer.GetBuffer(),
"Vertex Stream Buffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vertex_stream_buffer.GetDeviceMemory(),
"Vertex Stream Buffer Memory");
return true;
}
bool GPU_HW_Vulkan::CreateUniformBuffer()
{
return m_uniform_stream_buffer.Create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, UNIFORM_BUFFER_SIZE);
if (!m_uniform_stream_buffer.Create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, UNIFORM_BUFFER_SIZE))
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_uniform_stream_buffer.GetBuffer(),
"Uniform Stream Buffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_uniform_stream_buffer.GetDeviceMemory(),
"Uniform Stream Buffer Memory");
return true;
}
bool GPU_HW_Vulkan::CreateTextureBuffer()
@ -810,7 +892,6 @@ bool GPU_HW_Vulkan::CreateTextureBuffer()
{
if (!m_texture_stream_buffer.Create(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VRAM_UPDATE_TEXTURE_BUFFER_SIZE))
return false;
Vulkan::BufferViewBuilder bvbuilder;
bvbuilder.Set(m_texture_stream_buffer.GetBuffer(), VK_FORMAT_R16_UINT, 0, m_texture_stream_buffer.GetCurrentSize());
m_texture_stream_buffer_view = bvbuilder.Create(g_vulkan_context->GetDevice());
@ -827,6 +908,13 @@ bool GPU_HW_Vulkan::CreateTextureBuffer()
dsubuilder.Update(g_vulkan_context->GetDevice());
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_texture_stream_buffer.GetBuffer(),
"Texture Stream Buffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_texture_stream_buffer.GetDeviceMemory(),
"Texture Stream Buffer Memory");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_write_descriptor_set, "VRAM Write Descriptor Set");
return true;
}
@ -1100,6 +1188,8 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(device, fs, nullptr);
if (m_vram_update_depth_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_update_depth_pipeline,
"VRAM Update Depth Pipeline");
progress.Increment();
}
@ -1125,6 +1215,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(device, fs, nullptr);
if (m_vram_readback_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_readback_pipeline, "VRAM Read Pipeline");
progress.Increment();
}
@ -1183,6 +1274,8 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(g_vulkan_context->GetDevice(), fs, nullptr);
if (m_downsample_first_pass_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_first_pass_pipeline,
"Downsample First Pass Pipeline");
fs = g_vulkan_shader_cache->GetFragmentShader(shadergen.GenerateAdaptiveDownsampleMipFragmentShader(false));
if (fs == VK_NULL_HANDLE)
@ -1193,6 +1286,8 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(g_vulkan_context->GetDevice(), fs, nullptr);
if (m_downsample_mid_pass_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_mid_pass_pipeline,
"Downsample Mid Pass Pipeline");
fs = g_vulkan_shader_cache->GetFragmentShader(shadergen.GenerateAdaptiveDownsampleBlurFragmentShader());
if (fs == VK_NULL_HANDLE)
@ -1204,6 +1299,8 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(g_vulkan_context->GetDevice(), fs, nullptr);
if (m_downsample_blur_pass_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_blur_pass_pipeline,
"Downsample Blur Pass Pipeline");
fs = g_vulkan_shader_cache->GetFragmentShader(shadergen.GenerateAdaptiveDownsampleCompositeFragmentShader());
if (fs == VK_NULL_HANDLE)
@ -1216,6 +1313,9 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(g_vulkan_context->GetDevice(), fs, nullptr);
if (m_downsample_composite_pass_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_composite_pass_pipeline,
"Downsample Composite Pass Pipeline");
}
else if (m_downsample_mode == GPUDownsampleMode::Box)
{
@ -1237,6 +1337,9 @@ bool GPU_HW_Vulkan::CompilePipelines()
vkDestroyShaderModule(g_vulkan_context->GetDevice(), fs, nullptr);
if (m_downsample_first_pass_pipeline == VK_NULL_HANDLE)
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_downsample_first_pass_pipeline,
"Downsample First Pass Pipeline");
}
progress.Increment();
@ -1274,6 +1377,8 @@ void GPU_HW_Vulkan::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vert
BeginVRAMRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::DrawBatchVertices: [%u,%u)", base_vertex,
base_vertex + num_vertices);
// [depth_test][render_mode][texture_mode][transparency_mode][dithering][interlacing]
const u8 depth_test = m_batch.use_depth_buffer ? static_cast<u8>(2) : BoolToUInt8(m_batch.check_mask_before_draw);
@ -1289,7 +1394,9 @@ void GPU_HW_Vulkan::SetScissorFromDrawingArea()
{
int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom);
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"GPU_HW_Vulkan::SetScissorFromDrawingArea: {%u,%u} {%u,%u}", left, top,
right, bottom);
Vulkan::Util::SetScissor(g_vulkan_context->GetCurrentCommandBuffer(), left, top, right - left, bottom - top);
}
@ -1301,6 +1408,7 @@ void GPU_HW_Vulkan::ClearDisplay()
m_host_display->ClearDisplayTexture();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::ClearDisplay");
m_display_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
static const VkClearColorValue cc = {{0.0f, 0.0f, 0.0f, 1.0f}};
@ -1313,6 +1421,9 @@ void GPU_HW_Vulkan::UpdateDisplay()
GPU_HW::UpdateDisplay();
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::UpdateDisplay");
if (g_settings.debugging.show_vram)
{
if (IsUsingMultisampling())
@ -1380,7 +1491,6 @@ void GPU_HW_Vulkan::UpdateDisplay()
const u32 uniforms[4] = {reinterpret_start_x, scaled_vram_offset_y + reinterpret_field_offset,
reinterpret_crop_left, reinterpret_field_offset};
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
m_display_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
@ -1399,6 +1509,7 @@ void GPU_HW_Vulkan::UpdateDisplay()
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_single_sampler_pipeline_layout, 0, 1,
&m_vram_read_descriptor_set, 0, nullptr);
Vulkan::Util::SetViewportAndScissor(cmdbuf, 0, 0, scaled_display_width, scaled_display_height);
vkCmdDraw(cmdbuf, 3, 1, 0, 0);
EndRenderPass();
@ -1442,6 +1553,8 @@ void GPU_HW_Vulkan::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::ReadVRAM: %u %u %ux%u", x, y, width, height);
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_vram_readback_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -1460,7 +1573,6 @@ void GPU_HW_Vulkan::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
&m_vram_read_descriptor_set, 0, nullptr);
Vulkan::Util::SetViewportAndScissor(cmdbuf, 0, 0, encoded_width, encoded_height);
vkCmdDraw(cmdbuf, 3, 1, 0, 0);
EndRenderPass();
m_vram_readback_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
@ -1487,6 +1599,9 @@ void GPU_HW_Vulkan::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
BeginVRAMRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::FillVRAM: {%u,%u} %ux%u %08x", x, y, width, height,
color);
const VRAMFillUBOData uniforms = GetVRAMFillUBOData(x, y, width, height, color);
vkCmdPushConstants(cmdbuf, m_no_samplers_pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(uniforms),
&uniforms);
@ -1539,9 +1654,11 @@ void GPU_HW_Vulkan::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
std::memcpy(m_texture_stream_buffer.GetCurrentHostPointer(), data, data_size);
m_texture_stream_buffer.CommitMemory(data_size);
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::UpdateVRAM: {%u,%u} %ux%u", x, y, width, height);
BeginVRAMRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const VRAMWriteUBOData uniforms = GetVRAMWriteUBOData(x, y, width, height, start_index, set_mask, check_mask);
vkCmdPushConstants(cmdbuf, m_vram_write_pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(uniforms),
&uniforms);
@ -1561,6 +1678,9 @@ void GPU_HW_Vulkan::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
void GPU_HW_Vulkan::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height)
{
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::CopyVRAM: {%u, %u} {%u, %u} %ux%u", src_x, src_y,
dst_x, dst_y, width, height);
if (IsUsingSoftwareRendererForReadbacks())
CopySoftwareRendererVRAM(src_x, src_y, dst_x, dst_y, width, height);
@ -1577,7 +1697,6 @@ void GPU_HW_Vulkan::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
BeginVRAMRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS,
m_vram_copy_pipelines[BoolToUInt8(m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer)]);
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_single_sampler_pipeline_layout, 0, 1,
@ -1606,8 +1725,6 @@ void GPU_HW_Vulkan::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_GENERAL);
const VkImageCopy ic{{VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u},
@ -1626,6 +1743,7 @@ void GPU_HW_Vulkan::UpdateVRAMReadTexture()
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::UpdateVRAMReadTexture");
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_vram_read_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@ -1655,7 +1773,6 @@ void GPU_HW_Vulkan::UpdateVRAMReadTexture()
m_vram_read_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
GPU_HW::UpdateVRAMReadTexture();
}
@ -1665,8 +1782,8 @@ void GPU_HW_Vulkan::UpdateDepthBufferFromMaskBit()
return;
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::UpdateDepthBufferFromMaskBit");
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
BeginRenderPass(m_vram_update_depth_render_pass, m_vram_update_depth_framebuffer, 0, 0, m_vram_texture.GetWidth(),
@ -1690,6 +1807,7 @@ void GPU_HW_Vulkan::ClearDepthBuffer()
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::ClearDepthBuffer");
m_vram_depth_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
static const VkClearDepthStencilValue cds = {1.0f};
@ -1712,12 +1830,20 @@ bool GPU_HW_Vulkan::CreateTextureReplacementStreamBuffer()
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_texture_replacment_stream_buffer.GetBuffer(),
"Texture Replacement Stream Buffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_texture_replacment_stream_buffer.GetDeviceMemory(),
"Texture Replacement Stream Buffer Memory");
return true;
}
bool GPU_HW_Vulkan::BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u32 dst_x, u32 dst_y, u32 width,
u32 height)
{
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::BlitVRAMReplacementTexture: {%u,%u} %ux%u", dst_x,
dst_y, width, height);
if (!CreateTextureReplacementStreamBuffer())
return false;
@ -1752,7 +1878,6 @@ bool GPU_HW_Vulkan::BlitVRAMReplacementTexture(const TextureReplacementTexture*
m_texture_replacment_stream_buffer.CommitMemory(required_size);
// buffer -> texture
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
m_vram_write_replacement_texture.UpdateFromBuffer(cmdbuf, 0, 0, 0, 0, tex->GetWidth(), tex->GetHeight(),
m_texture_replacment_stream_buffer.GetBuffer(), buffer_offset);
@ -1786,6 +1911,8 @@ void GPU_HW_Vulkan::DownsampleFramebuffer(Vulkan::Texture& source, u32 left, u32
void GPU_HW_Vulkan::DownsampleFramebufferBoxFilter(Vulkan::Texture& source, u32 left, u32 top, u32 width, u32 height)
{
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::DownsampleFramebufferBoxFilter: {%u,%u} %ux%u",
left, top, width, height);
source.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_downsample_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -1825,6 +1952,8 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
{width, height, 1u}};
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "Downsample Framebuffer Adaptive:");
source.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_downsample_texture.TransitionSubresourcesToLayout(cmdbuf, 0, 1, 0, 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@ -1838,6 +1967,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
const u32 levels = m_downsample_texture.GetLevels();
for (u32 level = 1; level < levels; level++)
{
const Vulkan::Util::DebugScope debugScope(cmdbuf, "Generate Mip: %u", level);
m_downsample_texture.TransitionSubresourcesToLayout(
cmdbuf, level, 1, 0, 1, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -1865,6 +1995,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
// blur pass at lowest resolution
{
const Vulkan::Util::DebugScope debugScope(cmdbuf, "Blur Pass at lowest resolution");
const u32 last_level = levels - 1;
m_downsample_weight_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -1892,6 +2023,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
// resolve pass
{
const Vulkan::Util::DebugScope debugScope(cmdbuf, "Resolve pass");
m_display_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
BeginRenderPass(m_display_load_render_pass, m_display_framebuffer, left, top, width, height);
@ -1901,10 +2033,8 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
&m_downsample_composite_descriptor_set, 0, nullptr);
vkCmdDraw(cmdbuf, 3, 1, 0, 0);
EndRenderPass();
m_display_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
RestoreGraphicsAPIState();
m_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),

View File

@ -185,7 +185,8 @@ std::unique_ptr<HostDisplayTexture> VulkanHostDisplay::CreateTexture(u32 width,
return {};
}
}
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"VulkanHostDisplay::CreateTexture");
texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
if (data)
@ -632,20 +633,24 @@ bool VulkanHostDisplay::Render()
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
Vulkan::Texture& swap_chain_texture = m_swap_chain->GetCurrentTexture();
// Swap chain images start in undefined
swap_chain_texture.OverrideImageLayout(VK_IMAGE_LAYOUT_UNDEFINED);
swap_chain_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
{
const Vulkan::Util::DebugScope debugScope(cmdbuffer, "VulkanHostDisplay::Render");
// Swap chain images start in undefined
swap_chain_texture.OverrideImageLayout(VK_IMAGE_LAYOUT_UNDEFINED);
swap_chain_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
RenderDisplay();
RenderDisplay();
if (ImGui::GetCurrentContext())
RenderImGui();
if (ImGui::GetCurrentContext())
RenderImGui();
RenderSoftwareCursor();
RenderSoftwareCursor();
vkCmdEndRenderPass(cmdbuffer);
vkCmdEndRenderPass(cmdbuffer);
Vulkan::Util::EndDebugScope(cmdbuffer);
swap_chain_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
swap_chain_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
}
g_vulkan_context->SubmitCommandBuffer(m_swap_chain->GetImageAvailableSemaphore(),
m_swap_chain->GetRenderingFinishedSemaphore(), m_swap_chain->GetSwapChain(),
@ -722,7 +727,8 @@ bool VulkanHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>
const VkFramebuffer fb = tex.CreateFramebuffer(rp);
if (!fb)
return false;
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"VulkanHostDisplay::RenderScreenshot: %ux%u", width, height);
tex.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
const auto [left, top, draw_width, draw_height] = CalculateDrawRect(width, height, 0);
@ -742,6 +748,7 @@ bool VulkanHostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>
}
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
Vulkan::Util::EndDebugScope(g_vulkan_context->GetCurrentCommandBuffer());
tex.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
staging_tex.CopyFromTexture(tex, 0, 0, 0, 0, 0, 0, width, height);
staging_tex.ReadTexels(0, 0, width, height, out_pixels->data(), *out_stride);
@ -764,11 +771,15 @@ void VulkanHostDisplay::BeginSwapChainRenderPass(VkFramebuffer framebuffer, u32
{{0, 0}, {width, height}},
1u,
&clear_value};
Vulkan::Util::BeginDebugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"VulkanHostDisplay::BeginSwapChainRenderPass");
vkCmdBeginRenderPass(g_vulkan_context->GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
}
void VulkanHostDisplay::RenderDisplay()
{
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"VulkanHostDisplay::RenderDisplay");
if (!HasDisplayTexture())
{
BeginSwapChainRenderPass(m_swap_chain->GetCurrentFramebuffer(), m_swap_chain->GetWidth(),
@ -798,6 +809,9 @@ void VulkanHostDisplay::RenderDisplay(s32 left, s32 top, s32 width, s32 height,
s32 texture_view_width, s32 texture_view_height, bool linear_filter)
{
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(
cmdbuffer, "VulkanHostDisplay::RenderDisplay: {%u,%u} %ux%u | %ux%u | {%u,%u} %ux%u", left, top, width, height,
texture_height, texture_width, texture_view_x, texture_view_y, texture_view_width, texture_view_height);
VkDescriptorSet ds = g_vulkan_context->AllocateDescriptorSet(m_descriptor_set_layout);
if (ds == VK_NULL_HANDLE)
@ -830,6 +844,7 @@ void VulkanHostDisplay::RenderDisplay(s32 left, s32 top, s32 width, s32 height,
void VulkanHostDisplay::RenderImGui()
{
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(), "Imgui");
ImGui::Render();
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), g_vulkan_context->GetCurrentCommandBuffer());
}
@ -846,6 +861,8 @@ void VulkanHostDisplay::RenderSoftwareCursor()
void VulkanHostDisplay::RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 height, HostDisplayTexture* texture)
{
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuffer, "VulkanHostDisplay::RenderSoftwareCursor: {%u,%u} %ux%u", left,
top, width, height);
VkDescriptorSet ds = g_vulkan_context->AllocateDescriptorSet(m_descriptor_set_layout);
if (ds == VK_NULL_HANDLE)
@ -997,6 +1014,7 @@ bool VulkanHostDisplay::SetPostProcessingChain(const std::string_view& config)
m_post_processing_chain.ClearStages();
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), stage.pipeline, (shader.GetName() + "Pipeline").c_str());
m_post_processing_stages.push_back(std::move(stage));
}
@ -1010,7 +1028,10 @@ bool VulkanHostDisplay::SetPostProcessingChain(const std::string_view& config)
m_post_processing_chain.ClearStages();
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_post_processing_ubo.GetBuffer(),
"Post Processing Uniform Buffer");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_post_processing_ubo.GetDeviceMemory(),
"Post Processing Uniform Buffer Memory");
return true;
}
@ -1035,6 +1056,12 @@ bool VulkanHostDisplay::CheckPostProcessingRenderTargets(u32 target_width, u32 t
{
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_post_processing_input_texture.GetImage(),
"Post Processing Input Texture");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_post_processing_input_texture.GetView(),
"Post Processing Input Texture View");
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_post_processing_input_texture.GetDeviceMemory(),
"Post Processing Input Texture Memory");
}
const u32 target_count = (static_cast<u32>(m_post_processing_stages.size()) - 1);
@ -1056,6 +1083,12 @@ bool VulkanHostDisplay::CheckPostProcessingRenderTargets(u32 target_width, u32 t
{
return false;
}
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), pps.output_texture.GetImage(),
"Post Processing Output Texture %u", i);
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), pps.output_texture.GetDeviceMemory(),
"Post Processing Output Texture Memory %u", i);
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), pps.output_texture.GetView(),
"Post Processing Output Texture View %u", i);
}
}
@ -1068,6 +1101,9 @@ void VulkanHostDisplay::ApplyPostProcessingChain(VkFramebuffer target_fb, s32 fi
s32 texture_view_y, s32 texture_view_width, s32 texture_view_height,
u32 target_width, u32 target_height)
{
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuffer, "VulkanHostDisplay::ApplyPostProcessingChain");
if (!CheckPostProcessingRenderTargets(target_width, target_height))
{
BeginSwapChainRenderPass(target_fb, target_width, target_height);
@ -1077,12 +1113,12 @@ void VulkanHostDisplay::ApplyPostProcessingChain(VkFramebuffer target_fb, s32 fi
}
// downsample/upsample - use same viewport for remainder
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
m_post_processing_input_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
BeginSwapChainRenderPass(m_post_processing_input_framebuffer, target_width, target_height);
RenderDisplay(final_left, final_top, final_width, final_height, texture_handle, texture_width, texture_height,
texture_view_x, texture_view_y, texture_view_width, texture_view_height, m_display_linear_filtering);
vkCmdEndRenderPass(cmdbuffer);
Vulkan::Util::EndDebugScope(g_vulkan_context->GetCurrentCommandBuffer());
m_post_processing_input_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
texture_handle = &m_post_processing_input_texture;
@ -1097,6 +1133,9 @@ void VulkanHostDisplay::ApplyPostProcessingChain(VkFramebuffer target_fb, s32 fi
for (u32 i = 0; i < static_cast<u32>(m_post_processing_stages.size()); i++)
{
PostProcessingStage& pps = m_post_processing_stages[i];
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(), "Post Processing Stage: %s",
m_post_processing_chain.GetShaderStage(i).GetName().c_str());
if (i != final_stage)
{
pps.output_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
@ -1163,6 +1202,7 @@ void VulkanHostDisplay::ApplyPostProcessingChain(VkFramebuffer target_fb, s32 fi
if (i != final_stage)
{
vkCmdEndRenderPass(cmdbuffer);
Vulkan::Util::EndDebugScope(g_vulkan_context->GetCurrentCommandBuffer());
pps.output_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
texture_handle = &pps.output_texture;
}