mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
graphics: name game Vulkan resources in debug dumps
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "graphics/host_gpu/renderer/commandScheduler.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
#include "graphics/host_gpu/vulkanCommon.h"
|
||||
#include "kernel/memory.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -435,6 +436,9 @@ BufferCache::CachedBuffer& BufferCache::GetOrCreateBuffer(CommandBuffer& command
|
||||
cached->tick_accessed_last = m_gc_tick;
|
||||
cached->buffer = std::make_shared<Buffer>(m_graphics, m_scheduler, MemoryUsage::DeviceLocal,
|
||||
merged.address, AllFlags, merged.size);
|
||||
SetVulkanObjectNameF(m_graphics.device, cached->buffer->Handle(),
|
||||
"Kyty.GameBuffer[guest=0x{:016x} size=0x{:x}]", cached->vaddr,
|
||||
cached->size);
|
||||
for (const auto overlap: overlaps) {
|
||||
const auto& old = *overlap->second;
|
||||
cached->buffer->CopyFrom(command, *old.buffer, 0, old.vaddr - cached->vaddr, old.size);
|
||||
|
||||
+35
-2
@@ -34,6 +34,36 @@ constexpr uint64_t NumFramesBeforeRemoval = 32;
|
||||
|
||||
thread_local const TextureCache* g_locked_cache = nullptr;
|
||||
|
||||
[[nodiscard]] const char* BindingTypeName(TextureCache::BindingType type) {
|
||||
switch (type) {
|
||||
case TextureCache::BindingType::Texture: return "Texture";
|
||||
case TextureCache::BindingType::Storage: return "StorageTexture";
|
||||
case TextureCache::BindingType::RenderTarget: return "ColorTarget";
|
||||
case TextureCache::BindingType::DepthTarget: return "DepthTarget";
|
||||
case TextureCache::BindingType::VideoOut: return "VideoOut";
|
||||
}
|
||||
return "Image";
|
||||
}
|
||||
|
||||
void NameImageBinding(GraphicContext& graphics, Image& image, vk::ImageView view,
|
||||
TextureCache::BindingType type, const ImageViewInfo& view_info) {
|
||||
const auto* role = BindingTypeName(type);
|
||||
SetVulkanObjectNameF(
|
||||
graphics.device, image.backing.image,
|
||||
"Kyty.{}.Image[guest=0x{:016x} size=0x{:x} extent={}x{}x{} format={} mips={} layers={} "
|
||||
"samples={}]",
|
||||
role, image.info.data.address, image.info.data.size, image.info.extent.width,
|
||||
image.info.extent.height, image.info.extent.depth,
|
||||
static_cast<uint32_t>(image.info.pixel_format), image.info.resources.levels,
|
||||
image.info.resources.layers, image.info.samples);
|
||||
SetVulkanObjectNameF(
|
||||
graphics.device, view,
|
||||
"Kyty.{}.View[guest=0x{:016x} format={} aspect=0x{:x} mip={}+{} layer={}+{}]", role,
|
||||
image.info.data.address, static_cast<uint32_t>(view_info.format),
|
||||
static_cast<vk::ImageAspectFlags::MaskType>(view_info.aspect), view_info.base_level,
|
||||
view_info.level_count, view_info.base_layer, view_info.layer_count);
|
||||
}
|
||||
|
||||
class CacheLock final {
|
||||
public:
|
||||
CacheLock(const TextureCache& owner, TrackingSpinLock& lock): m_lock(lock) {
|
||||
@@ -714,7 +744,7 @@ ImageId TextureCache::ResolveDepthOverlap(const ImageInfo& requested, BindingTyp
|
||||
cached.info.data.size / cached.info.resources.layers &&
|
||||
!requested.HasStencil() && !cached.info.HasStencil() && !requested.HasMetadata() &&
|
||||
!cached.info.HasMetadata();
|
||||
bool recreate = cached.info.resources < requested.resources;
|
||||
bool recreate = cached.info.resources < requested.resources;
|
||||
switch (binding) {
|
||||
case BindingType::Texture:
|
||||
recreate |= requested.IsDepth() && !cached.info.IsDepth();
|
||||
@@ -1359,6 +1389,7 @@ vk::ImageView TextureCache::FindTexture(ImageId id, const ImageDesc& desc) {
|
||||
default: EXIT("TextureCache: invalid texture binding\n");
|
||||
}
|
||||
const auto view = image.FindView(desc.view_info);
|
||||
NameImageBinding(m_graphics, image, view, desc.type, desc.view_info);
|
||||
RetainImage(m_scheduler.Current(), id);
|
||||
return view;
|
||||
}
|
||||
@@ -1392,6 +1423,7 @@ vk::ImageView TextureCache::FindRenderTarget(ImageId id, const ImageDesc& desc)
|
||||
CommitGpuWrite(image);
|
||||
TrackImageDownloadLocked(id, image);
|
||||
const auto view = image.FindView(desc.view_info);
|
||||
NameImageBinding(m_graphics, image, view, desc.type, desc.view_info);
|
||||
RetainImage(m_scheduler.Current(), id);
|
||||
return view;
|
||||
}
|
||||
@@ -1431,6 +1463,7 @@ vk::ImageView TextureCache::FindDepthTarget(ImageId id, const ImageDesc& desc) {
|
||||
AssociateStencilLocked(id, desc.info.stencil);
|
||||
}
|
||||
const auto view = image.FindView(desc.view_info);
|
||||
NameImageBinding(m_graphics, image, view, desc.type, desc.view_info);
|
||||
RetainImage(m_scheduler.Current(), id);
|
||||
return view;
|
||||
}
|
||||
@@ -1957,7 +1990,7 @@ bool TextureCache::TryConsumeDccFill(uint64_t address, uint64_t size, uint32_t f
|
||||
// This dispatch may precede color-target discovery. Retain it in the shared
|
||||
// metadata map, but PendingDcc remains invisible to IsMeta until registration. Returning
|
||||
// false lets the guest dispatch execute and initialize memory while the type is uncertain.
|
||||
m_surface_metas.emplace(address, MetaDataInfo {.type = MetaDataInfo::Type::PendingDcc,
|
||||
m_surface_metas.emplace(address, MetaDataInfo {.type = MetaDataInfo::Type::PendingDcc,
|
||||
.clear_mask = dcc_clear_mask,
|
||||
.fill_value = fill_value,
|
||||
.fill_size = size});
|
||||
|
||||
@@ -45,6 +45,16 @@
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
static const char* ShaderStageResourceName(DescriptorCache::Stage stage) {
|
||||
switch (stage) {
|
||||
case DescriptorCache::Stage::Vertex: return "Vertex";
|
||||
case DescriptorCache::Stage::Pixel: return "Pixel";
|
||||
case DescriptorCache::Stage::Compute: return "Compute";
|
||||
case DescriptorCache::Stage::Unknown: return "Unknown";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static void BindNullStorageBuffer(RenderContext& context, BufferView& dst) {
|
||||
auto owner = context.GetBufferCache().ObtainNullBuffer();
|
||||
dst.buffer = owner->Handle();
|
||||
@@ -82,7 +92,8 @@ static bool IsMultisampledTexture(Prospero::ImageType type) {
|
||||
static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& command_buffer,
|
||||
const ShaderBufferResource& descriptor,
|
||||
const ShaderRecompiler::IR::BufferResource& resource,
|
||||
uint32_t& buffer_offset) {
|
||||
DescriptorCache::Stage stage, uint32_t slot,
|
||||
uint32_t& buffer_offset) {
|
||||
BufferView result;
|
||||
buffer_offset = 0;
|
||||
|
||||
@@ -117,6 +128,11 @@ static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& com
|
||||
result.buffer = binding.buffer;
|
||||
result.offset = aligned_offset;
|
||||
result.range = static_cast<vk::DeviceSize>(size + adjustment);
|
||||
SetVulkanObjectNameF(
|
||||
graphics.device, result.buffer,
|
||||
"Kyty.{}.StorageBuffer[slot={} guest=0x{:016x} size=0x{:x} access={} formatted={}]",
|
||||
ShaderStageResourceName(stage), slot, address, size,
|
||||
resource.written ? (resource.read ? "ReadWrite" : "Write") : "Read", resource.formatted);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -124,7 +140,7 @@ static BufferView
|
||||
NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer,
|
||||
const ShaderRecompiler::IR::AddressResource& resource,
|
||||
const ShaderRecompiler::IR::ResourceSnapshot::Address& address,
|
||||
uint32_t& address_offset) {
|
||||
DescriptorCache::Stage stage, uint32_t slot, uint32_t& address_offset) {
|
||||
BufferView result;
|
||||
address_offset = 0;
|
||||
if (address.binding_base == 0) {
|
||||
@@ -147,17 +163,20 @@ NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer,
|
||||
}
|
||||
const auto& graphics = context.GetGraphics();
|
||||
const auto alignment = graphics.StorageMinAlignment();
|
||||
auto binding =
|
||||
auto binding =
|
||||
context.GetBufferCache().ObtainBuffer(command_buffer, address.binding_base, size);
|
||||
const auto aligned_offset = binding.offset - binding.offset % alignment;
|
||||
const auto adjustment = binding.offset - aligned_offset;
|
||||
const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange;
|
||||
const auto visible_size = std::min(size, static_cast<uint64_t>(max_range - adjustment));
|
||||
address_offset = static_cast<uint32_t>(adjustment);
|
||||
result.owner = std::move(binding.owner);
|
||||
result.buffer = binding.buffer;
|
||||
result.offset = aligned_offset;
|
||||
result.range = static_cast<vk::DeviceSize>(visible_size + adjustment);
|
||||
const auto visible_size = std::min(size, static_cast<uint64_t>(max_range - adjustment));
|
||||
address_offset = static_cast<uint32_t>(adjustment);
|
||||
result.owner = std::move(binding.owner);
|
||||
result.buffer = binding.buffer;
|
||||
result.offset = aligned_offset;
|
||||
result.range = static_cast<vk::DeviceSize>(visible_size + adjustment);
|
||||
SetVulkanObjectNameF(graphics.device, result.buffer,
|
||||
"Kyty.{}.AddressBuffer[slot={} guest=0x{:016x} size=0x{:x}]",
|
||||
ShaderStageResourceName(stage), slot, address.binding_base, visible_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -458,10 +477,9 @@ void ValidateStorageTexture(const ShaderRecompiler::IR::ImageResource& resource,
|
||||
const bool raw_sint_storage = format == Prospero::BufferFormat::k32SInt && uint_resource &&
|
||||
resource.written && !resource.read && !resource.atomic;
|
||||
const bool format_ok =
|
||||
raw_sint_storage ||
|
||||
(Prospero::IsSampledTextureFormat(format) &&
|
||||
uint_resource == Prospero::IsUintTextureFormat(format) &&
|
||||
(!resource.atomic || format == Prospero::BufferFormat::k32UInt));
|
||||
raw_sint_storage || (Prospero::IsSampledTextureFormat(format) &&
|
||||
uint_resource == Prospero::IsUintTextureFormat(format) &&
|
||||
(!resource.atomic || format == Prospero::BufferFormat::k32UInt));
|
||||
if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) {
|
||||
return;
|
||||
}
|
||||
@@ -568,8 +586,8 @@ static void PopulateTextureMipLayout(ImageInfo& info) {
|
||||
|
||||
static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource& resource,
|
||||
const ShaderTextureResource& descriptor, vk::Format format,
|
||||
bool shader_conversion, bool storage,
|
||||
uint32_t view_levels, uint32_t image_layers) {
|
||||
bool shader_conversion, bool storage, uint32_t view_levels,
|
||||
uint32_t image_layers) {
|
||||
ImageViewInfo view {};
|
||||
view.format = format;
|
||||
view.aspect = vk::ImageAspectFlagBits::eColor;
|
||||
@@ -684,10 +702,9 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
|
||||
const bool shader_conversion =
|
||||
surface_format.conversion_format != Prospero::BufferFormat::kInvalid;
|
||||
const bool sampled_numeric_class =
|
||||
storage ||
|
||||
(Prospero::IsSampledTextureFormat(format) &&
|
||||
(resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) ==
|
||||
Prospero::IsUintTextureFormat(format));
|
||||
storage || (Prospero::IsSampledTextureFormat(format) &&
|
||||
(resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) ==
|
||||
Prospero::IsUintTextureFormat(format));
|
||||
if (!storage &&
|
||||
(resource.kind == ShaderRecompiler::IR::ResourceKind::Image ||
|
||||
resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) &&
|
||||
@@ -752,7 +769,7 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
|
||||
view_levels, desc.info.resources.layers);
|
||||
desc.type = storage ? TextureCache::BindingType::Storage : TextureCache::BindingType::Texture;
|
||||
|
||||
auto id = texture_cache.FindImage(desc, shader_conversion);
|
||||
auto id = texture_cache.FindImage(desc, shader_conversion);
|
||||
auto* image = &texture_cache.GetImage(id);
|
||||
const bool stencil_association = static_cast<bool>(image->depth_id);
|
||||
if (stencil_association) {
|
||||
@@ -910,17 +927,18 @@ void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
|
||||
CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields);
|
||||
uint32_t buffer_offset = 0;
|
||||
resources.buffers.push_back(NativeStorageBuffer(m_context, buffer, descriptor,
|
||||
program.info.buffers[i], buffer_offset));
|
||||
program.info.buffers[i], prepared.stage, i,
|
||||
buffer_offset));
|
||||
pack_memory_offset(i, buffer_offset);
|
||||
}
|
||||
resources.addresses.clear();
|
||||
resources.addresses.reserve(program.info.addresses.size());
|
||||
for (uint32_t i = 0; i < program.info.addresses.size(); i++) {
|
||||
uint32_t address_offset = 0;
|
||||
resources.addresses.push_back(NativeAddressBuffer(
|
||||
m_context, buffer, program.info.addresses[i], snapshot.addresses[i], address_offset));
|
||||
pack_memory_offset(static_cast<uint32_t>(program.info.buffers.size()) + i,
|
||||
address_offset);
|
||||
resources.addresses.push_back(
|
||||
NativeAddressBuffer(m_context, buffer, program.info.addresses[i], snapshot.addresses[i],
|
||||
prepared.stage, i, address_offset));
|
||||
pack_memory_offset(static_cast<uint32_t>(program.info.buffers.size()) + i, address_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,18 +142,6 @@ static void LogMrtState(const char* draw_name, const RenderCommandBuffer& buffer
|
||||
(bc0.separate_alpha_blend && (IsDualSourceBlendFactor(bc0.alpha_srcblend) ||
|
||||
IsDualSourceBlendFactor(bc0.alpha_destblend)));
|
||||
|
||||
for (uint32_t i = 1; i < 8; i++) {
|
||||
const auto& rt = ctx.GetRenderTarget(i);
|
||||
if (rt.base.addr != 0 || ps_input_info.target_output_mode[i] != 0 ||
|
||||
((rt_mask >> (i * 4u)) & 0x0fu) != 0 || ((cb_shader_mask >> (i * 4u)) & 0x0fu) != 0) {
|
||||
interesting = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!interesting) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto log_id = g_mrt_state_log_count.fetch_add(1);
|
||||
if (log_id >= 32) {
|
||||
return;
|
||||
@@ -553,8 +541,7 @@ struct DrawCallInfo {
|
||||
};
|
||||
|
||||
static bool ResolveDccAttachmentClear(TextureCache& cache, const RenderColorInfo& target,
|
||||
const ImageViewInfo& view,
|
||||
vk::ClearColorValue& clear_value) {
|
||||
const ImageViewInfo& view, vk::ClearColorValue& clear_value) {
|
||||
if (target.desc.info.metadata.kind != ImageMetadataKind::Dcc) {
|
||||
return false;
|
||||
}
|
||||
@@ -641,6 +628,15 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
|
||||
}
|
||||
target.image_view = cache.FindRenderTarget(target.image_id, target.desc);
|
||||
auto& image = cache.GetImage(target.image_id);
|
||||
SetVulkanObjectNameF(m_context.GetGraphics().device, image.backing.image,
|
||||
"Kyty.MRT{}.Image[guest=0x{:016x} size=0x{:x} format={}]",
|
||||
target.target_slot, image.info.data.address, image.info.data.size,
|
||||
static_cast<uint32_t>(image.info.pixel_format));
|
||||
SetVulkanObjectNameF(m_context.GetGraphics().device, target.image_view,
|
||||
"Kyty.MRT{}.View[guest=0x{:016x} mip={} layer={}+{}]",
|
||||
target.target_slot, image.info.data.address,
|
||||
target.desc.view_info.base_level, target.desc.view_info.base_layer,
|
||||
target.desc.view_info.layer_count);
|
||||
EXIT_IF(image.backing.samples != target.samples || target.image_view == nullptr);
|
||||
if (attachment_samples == 0) {
|
||||
attachment_samples = target.samples;
|
||||
@@ -657,15 +653,15 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
|
||||
ImageSubresourceRange {view.base_level, view.level_count, view.base_layer,
|
||||
view.layer_count},
|
||||
buffer.Handle());
|
||||
state.width = std::min(state.width, target.extent.width);
|
||||
state.height = std::min(state.height, target.extent.height);
|
||||
state.num_layers = std::min(state.num_layers, view.layer_count);
|
||||
auto& attachment = state.color_attachments[i];
|
||||
attachment.image_view = target.image_view;
|
||||
attachment.image_layout = layout;
|
||||
attachment.clear_value = target.color_clear_value.uint32;
|
||||
state.width = std::min(state.width, target.extent.width);
|
||||
state.height = std::min(state.height, target.extent.height);
|
||||
state.num_layers = std::min(state.num_layers, view.layer_count);
|
||||
auto& attachment = state.color_attachments[i];
|
||||
attachment.image_view = target.image_view;
|
||||
attachment.image_layout = layout;
|
||||
attachment.clear_value = target.color_clear_value.uint32;
|
||||
vk::ClearColorValue metadata_clear_value {};
|
||||
const bool metadata_clear =
|
||||
const bool metadata_clear =
|
||||
ResolveDccAttachmentClear(cache, target, view, metadata_clear_value);
|
||||
if (metadata_clear) {
|
||||
attachment.clear_value = metadata_clear_value.uint32;
|
||||
@@ -690,6 +686,14 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
|
||||
EXIT("failed to consume HTile clear state\n");
|
||||
}
|
||||
auto& image = cache.GetImage(depth.image_id);
|
||||
SetVulkanObjectNameF(m_context.GetGraphics().device, image.backing.image,
|
||||
"Kyty.DepthTarget.Image[guest=0x{:016x} size=0x{:x} format={}]",
|
||||
image.info.data.address, image.info.data.size,
|
||||
static_cast<uint32_t>(image.info.pixel_format));
|
||||
SetVulkanObjectNameF(m_context.GetGraphics().device, depth.image_view,
|
||||
"Kyty.DepthTarget.View[guest=0x{:016x} layer={}+{}]",
|
||||
image.info.data.address, depth.desc.view_info.base_layer,
|
||||
depth.desc.view_info.layer_count);
|
||||
EXIT_IF(depth.image_view == nullptr || image.backing.samples != depth.samples);
|
||||
if (attachment_samples == 0) {
|
||||
attachment_samples = depth.samples;
|
||||
@@ -862,6 +866,9 @@ static PreparedVertexBuffers AcquireVertexBuffers(RenderCommandBuffer& b
|
||||
Libs::LibKernel::Memory::ClampRangeSize(range.base_address, range.RequestedSize());
|
||||
range.acquired_end = range.base_address + size;
|
||||
range.binding = cache.ObtainBuffer(buffer, range.base_address, size);
|
||||
SetVulkanObjectNameF(buffer.GetContext().GetGraphics().device, range.binding.buffer,
|
||||
"Kyty.VertexBufferRange[guest=0x{:016x} size=0x{:x}]",
|
||||
range.base_address, size);
|
||||
}
|
||||
|
||||
// Rebuild slot bindings, offsetting non-empty slots into their acquired merged range.
|
||||
@@ -894,6 +901,10 @@ static PreparedVertexBuffers AcquireVertexBuffers(RenderCommandBuffer& b
|
||||
|
||||
prepared.buffers[i] = range->binding.buffer;
|
||||
prepared.offsets[i] = range->binding.offset + vertex.addr - range->base_address;
|
||||
SetVulkanObjectNameF(
|
||||
buffer.GetContext().GetGraphics().device, prepared.buffers[i],
|
||||
"Kyty.VertexBuffer[slot={} guest=0x{:016x} size=0x{:x} stride={} records={}]", i,
|
||||
vertex.addr, size, vertex.stride, vertex.num_records);
|
||||
}
|
||||
|
||||
if (null_owner != nullptr) {
|
||||
@@ -1104,6 +1115,15 @@ static PreparedIndexBuffer PrepareIndexBuffer(RenderCommandBuffer& buffe
|
||||
prepared.buffer = binding.buffer;
|
||||
prepared.offset = binding.offset;
|
||||
}
|
||||
if (source.host_data != nullptr) {
|
||||
SetVulkanObjectNameF(buffer.GetContext().GetGraphics().device, prepared.buffer,
|
||||
"Kyty.IndexBuffer[guest=transient size=0x{:x} type={}]", source.size,
|
||||
static_cast<uint32_t>(source.type));
|
||||
} else {
|
||||
SetVulkanObjectNameF(buffer.GetContext().GetGraphics().device, prepared.buffer,
|
||||
"Kyty.IndexBuffer[guest=0x{:016x} size=0x{:x} type={}]",
|
||||
source.address, source.size, static_cast<uint32_t>(source.type));
|
||||
}
|
||||
return prepared;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <fmt/format.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <vulkan/vulkan_hash.hpp>
|
||||
@@ -29,6 +32,24 @@ std::string VulkanToString(vk::QueueFlags value);
|
||||
vk::Format VulkanFormat(Prospero::BufferFormat guest_format);
|
||||
void RequireVulkanSuccess(vk::Result result, const char* operation);
|
||||
|
||||
template <typename Handle, typename... Args>
|
||||
void SetVulkanObjectNameF(vk::Device device, Handle handle, fmt::format_string<Args...> format,
|
||||
Args&&... args) {
|
||||
if (!Config::GraphicsDebugDumpEnabled() || device == nullptr || handle == nullptr ||
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.vkSetDebugUtilsObjectNameEXT == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto name = fmt::format(format, std::forward<Args>(args)...);
|
||||
vk::DebugUtilsObjectNameInfoEXT info {};
|
||||
info.sType = vk::StructureType::eDebugUtilsObjectNameInfoEXT;
|
||||
info.objectType = Handle::objectType;
|
||||
info.objectHandle = static_cast<uint64_t>(
|
||||
reinterpret_cast<uintptr_t>(static_cast<typename Handle::CType>(handle)));
|
||||
info.pObjectName = name.c_str();
|
||||
(void)device.setDebugUtilsObjectNameEXT(&info);
|
||||
}
|
||||
|
||||
template <typename T, typename Enumerator>
|
||||
[[nodiscard]] std::vector<T> EnumerateVulkan(const char* operation, Enumerator&& enumerate) {
|
||||
for (;;) {
|
||||
|
||||
Reference in New Issue
Block a user