graphics: name game Vulkan resources in debug dumps

This commit is contained in:
nmzik
2026-08-21 04:48:43 +02:00
parent 7022afa86e
commit 342fae06a6
5 changed files with 145 additions and 49 deletions
+4
View File
@@ -9,6 +9,7 @@
#include "graphics/host_gpu/renderer/commandScheduler.h" #include "graphics/host_gpu/renderer/commandScheduler.h"
#include "graphics/host_gpu/renderer/render.h" #include "graphics/host_gpu/renderer/render.h"
#include "graphics/host_gpu/renderer/renderContext.h" #include "graphics/host_gpu/renderer/renderContext.h"
#include "graphics/host_gpu/vulkanCommon.h"
#include "kernel/memory.h" #include "kernel/memory.h"
#include <algorithm> #include <algorithm>
@@ -435,6 +436,9 @@ BufferCache::CachedBuffer& BufferCache::GetOrCreateBuffer(CommandBuffer& command
cached->tick_accessed_last = m_gc_tick; cached->tick_accessed_last = m_gc_tick;
cached->buffer = std::make_shared<Buffer>(m_graphics, m_scheduler, MemoryUsage::DeviceLocal, cached->buffer = std::make_shared<Buffer>(m_graphics, m_scheduler, MemoryUsage::DeviceLocal,
merged.address, AllFlags, merged.size); 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) { for (const auto overlap: overlaps) {
const auto& old = *overlap->second; const auto& old = *overlap->second;
cached->buffer->CopyFrom(command, *old.buffer, 0, old.vaddr - cached->vaddr, old.size); cached->buffer->CopyFrom(command, *old.buffer, 0, old.vaddr - cached->vaddr, old.size);
+35 -2
View File
@@ -34,6 +34,36 @@ constexpr uint64_t NumFramesBeforeRemoval = 32;
thread_local const TextureCache* g_locked_cache = nullptr; 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 { class CacheLock final {
public: public:
CacheLock(const TextureCache& owner, TrackingSpinLock& lock): m_lock(lock) { 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 && cached.info.data.size / cached.info.resources.layers &&
!requested.HasStencil() && !cached.info.HasStencil() && !requested.HasMetadata() && !requested.HasStencil() && !cached.info.HasStencil() && !requested.HasMetadata() &&
!cached.info.HasMetadata(); !cached.info.HasMetadata();
bool recreate = cached.info.resources < requested.resources; bool recreate = cached.info.resources < requested.resources;
switch (binding) { switch (binding) {
case BindingType::Texture: case BindingType::Texture:
recreate |= requested.IsDepth() && !cached.info.IsDepth(); 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"); default: EXIT("TextureCache: invalid texture binding\n");
} }
const auto view = image.FindView(desc.view_info); const auto view = image.FindView(desc.view_info);
NameImageBinding(m_graphics, image, view, desc.type, desc.view_info);
RetainImage(m_scheduler.Current(), id); RetainImage(m_scheduler.Current(), id);
return view; return view;
} }
@@ -1392,6 +1423,7 @@ vk::ImageView TextureCache::FindRenderTarget(ImageId id, const ImageDesc& desc)
CommitGpuWrite(image); CommitGpuWrite(image);
TrackImageDownloadLocked(id, image); TrackImageDownloadLocked(id, image);
const auto view = image.FindView(desc.view_info); const auto view = image.FindView(desc.view_info);
NameImageBinding(m_graphics, image, view, desc.type, desc.view_info);
RetainImage(m_scheduler.Current(), id); RetainImage(m_scheduler.Current(), id);
return view; return view;
} }
@@ -1431,6 +1463,7 @@ vk::ImageView TextureCache::FindDepthTarget(ImageId id, const ImageDesc& desc) {
AssociateStencilLocked(id, desc.info.stencil); AssociateStencilLocked(id, desc.info.stencil);
} }
const auto view = image.FindView(desc.view_info); const auto view = image.FindView(desc.view_info);
NameImageBinding(m_graphics, image, view, desc.type, desc.view_info);
RetainImage(m_scheduler.Current(), id); RetainImage(m_scheduler.Current(), id);
return view; 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 // This dispatch may precede color-target discovery. Retain it in the shared
// metadata map, but PendingDcc remains invisible to IsMeta until registration. Returning // 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. // 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, .clear_mask = dcc_clear_mask,
.fill_value = fill_value, .fill_value = fill_value,
.fill_size = size}); .fill_size = size});
@@ -45,6 +45,16 @@
namespace Libs::Graphics { 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) { static void BindNullStorageBuffer(RenderContext& context, BufferView& dst) {
auto owner = context.GetBufferCache().ObtainNullBuffer(); auto owner = context.GetBufferCache().ObtainNullBuffer();
dst.buffer = owner->Handle(); dst.buffer = owner->Handle();
@@ -82,7 +92,8 @@ static bool IsMultisampledTexture(Prospero::ImageType type) {
static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& command_buffer, static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& command_buffer,
const ShaderBufferResource& descriptor, const ShaderBufferResource& descriptor,
const ShaderRecompiler::IR::BufferResource& resource, const ShaderRecompiler::IR::BufferResource& resource,
uint32_t& buffer_offset) { DescriptorCache::Stage stage, uint32_t slot,
uint32_t& buffer_offset) {
BufferView result; BufferView result;
buffer_offset = 0; buffer_offset = 0;
@@ -117,6 +128,11 @@ static BufferView NativeStorageBuffer(RenderContext& context, CommandBuffer& com
result.buffer = binding.buffer; result.buffer = binding.buffer;
result.offset = aligned_offset; result.offset = aligned_offset;
result.range = static_cast<vk::DeviceSize>(size + adjustment); 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; return result;
} }
@@ -124,7 +140,7 @@ static BufferView
NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer, NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer,
const ShaderRecompiler::IR::AddressResource& resource, const ShaderRecompiler::IR::AddressResource& resource,
const ShaderRecompiler::IR::ResourceSnapshot::Address& address, const ShaderRecompiler::IR::ResourceSnapshot::Address& address,
uint32_t& address_offset) { DescriptorCache::Stage stage, uint32_t slot, uint32_t& address_offset) {
BufferView result; BufferView result;
address_offset = 0; address_offset = 0;
if (address.binding_base == 0) { if (address.binding_base == 0) {
@@ -147,17 +163,20 @@ NativeAddressBuffer(RenderContext& context, CommandBuffer& command_buffer,
} }
const auto& graphics = context.GetGraphics(); const auto& graphics = context.GetGraphics();
const auto alignment = graphics.StorageMinAlignment(); const auto alignment = graphics.StorageMinAlignment();
auto binding = auto binding =
context.GetBufferCache().ObtainBuffer(command_buffer, address.binding_base, size); context.GetBufferCache().ObtainBuffer(command_buffer, address.binding_base, size);
const auto aligned_offset = binding.offset - binding.offset % alignment; const auto aligned_offset = binding.offset - binding.offset % alignment;
const auto adjustment = binding.offset - aligned_offset; const auto adjustment = binding.offset - aligned_offset;
const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange; const auto max_range = graphics.GetPhysicalDeviceProperties().limits.maxStorageBufferRange;
const auto visible_size = std::min(size, static_cast<uint64_t>(max_range - adjustment)); const auto visible_size = std::min(size, static_cast<uint64_t>(max_range - adjustment));
address_offset = static_cast<uint32_t>(adjustment); address_offset = static_cast<uint32_t>(adjustment);
result.owner = std::move(binding.owner); result.owner = std::move(binding.owner);
result.buffer = binding.buffer; result.buffer = binding.buffer;
result.offset = aligned_offset; result.offset = aligned_offset;
result.range = static_cast<vk::DeviceSize>(visible_size + adjustment); 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; return result;
} }
@@ -458,10 +477,9 @@ void ValidateStorageTexture(const ShaderRecompiler::IR::ImageResource& resource,
const bool raw_sint_storage = format == Prospero::BufferFormat::k32SInt && uint_resource && const bool raw_sint_storage = format == Prospero::BufferFormat::k32SInt && uint_resource &&
resource.written && !resource.read && !resource.atomic; resource.written && !resource.read && !resource.atomic;
const bool format_ok = const bool format_ok =
raw_sint_storage || raw_sint_storage || (Prospero::IsSampledTextureFormat(format) &&
(Prospero::IsSampledTextureFormat(format) && uint_resource == Prospero::IsUintTextureFormat(format) &&
uint_resource == Prospero::IsUintTextureFormat(format) && (!resource.atomic || format == Prospero::BufferFormat::k32UInt));
(!resource.atomic || format == Prospero::BufferFormat::k32UInt));
if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) { if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) {
return; return;
} }
@@ -568,8 +586,8 @@ static void PopulateTextureMipLayout(ImageInfo& info) {
static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource& resource, static ImageViewInfo TextureViewInfo(const ShaderRecompiler::IR::ImageResource& resource,
const ShaderTextureResource& descriptor, vk::Format format, const ShaderTextureResource& descriptor, vk::Format format,
bool shader_conversion, bool storage, bool shader_conversion, bool storage, uint32_t view_levels,
uint32_t view_levels, uint32_t image_layers) { uint32_t image_layers) {
ImageViewInfo view {}; ImageViewInfo view {};
view.format = format; view.format = format;
view.aspect = vk::ImageAspectFlagBits::eColor; view.aspect = vk::ImageAspectFlagBits::eColor;
@@ -684,10 +702,9 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
const bool shader_conversion = const bool shader_conversion =
surface_format.conversion_format != Prospero::BufferFormat::kInvalid; surface_format.conversion_format != Prospero::BufferFormat::kInvalid;
const bool sampled_numeric_class = const bool sampled_numeric_class =
storage || storage || (Prospero::IsSampledTextureFormat(format) &&
(Prospero::IsSampledTextureFormat(format) && (resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) ==
(resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) == Prospero::IsUintTextureFormat(format));
Prospero::IsUintTextureFormat(format));
if (!storage && if (!storage &&
(resource.kind == ShaderRecompiler::IR::ResourceKind::Image || (resource.kind == ShaderRecompiler::IR::ResourceKind::Image ||
resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) && resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) &&
@@ -752,7 +769,7 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
view_levels, desc.info.resources.layers); view_levels, desc.info.resources.layers);
desc.type = storage ? TextureCache::BindingType::Storage : TextureCache::BindingType::Texture; 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); auto* image = &texture_cache.GetImage(id);
const bool stencil_association = static_cast<bool>(image->depth_id); const bool stencil_association = static_cast<bool>(image->depth_id);
if (stencil_association) { if (stencil_association) {
@@ -910,17 +927,18 @@ void RenderExecutor::RebindBuffers(CommandBuffer& buffer,
CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields); CopyNativeDescriptor(snapshot.buffers[i], descriptor.fields);
uint32_t buffer_offset = 0; uint32_t buffer_offset = 0;
resources.buffers.push_back(NativeStorageBuffer(m_context, buffer, descriptor, 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); pack_memory_offset(i, buffer_offset);
} }
resources.addresses.clear(); resources.addresses.clear();
resources.addresses.reserve(program.info.addresses.size()); resources.addresses.reserve(program.info.addresses.size());
for (uint32_t i = 0; i < program.info.addresses.size(); i++) { for (uint32_t i = 0; i < program.info.addresses.size(); i++) {
uint32_t address_offset = 0; uint32_t address_offset = 0;
resources.addresses.push_back(NativeAddressBuffer( resources.addresses.push_back(
m_context, buffer, program.info.addresses[i], snapshot.addresses[i], address_offset)); NativeAddressBuffer(m_context, buffer, program.info.addresses[i], snapshot.addresses[i],
pack_memory_offset(static_cast<uint32_t>(program.info.buffers.size()) + i, prepared.stage, i, address_offset));
address_offset); pack_memory_offset(static_cast<uint32_t>(program.info.buffers.size()) + i, address_offset);
} }
} }
+42 -22
View File
@@ -142,18 +142,6 @@ static void LogMrtState(const char* draw_name, const RenderCommandBuffer& buffer
(bc0.separate_alpha_blend && (IsDualSourceBlendFactor(bc0.alpha_srcblend) || (bc0.separate_alpha_blend && (IsDualSourceBlendFactor(bc0.alpha_srcblend) ||
IsDualSourceBlendFactor(bc0.alpha_destblend))); 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); auto log_id = g_mrt_state_log_count.fetch_add(1);
if (log_id >= 32) { if (log_id >= 32) {
return; return;
@@ -553,8 +541,7 @@ struct DrawCallInfo {
}; };
static bool ResolveDccAttachmentClear(TextureCache& cache, const RenderColorInfo& target, static bool ResolveDccAttachmentClear(TextureCache& cache, const RenderColorInfo& target,
const ImageViewInfo& view, const ImageViewInfo& view, vk::ClearColorValue& clear_value) {
vk::ClearColorValue& clear_value) {
if (target.desc.info.metadata.kind != ImageMetadataKind::Dcc) { if (target.desc.info.metadata.kind != ImageMetadataKind::Dcc) {
return false; return false;
} }
@@ -641,6 +628,15 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
} }
target.image_view = cache.FindRenderTarget(target.image_id, target.desc); target.image_view = cache.FindRenderTarget(target.image_id, target.desc);
auto& image = cache.GetImage(target.image_id); 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); EXIT_IF(image.backing.samples != target.samples || target.image_view == nullptr);
if (attachment_samples == 0) { if (attachment_samples == 0) {
attachment_samples = target.samples; attachment_samples = target.samples;
@@ -657,15 +653,15 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo
ImageSubresourceRange {view.base_level, view.level_count, view.base_layer, ImageSubresourceRange {view.base_level, view.level_count, view.base_layer,
view.layer_count}, view.layer_count},
buffer.Handle()); buffer.Handle());
state.width = std::min(state.width, target.extent.width); state.width = std::min(state.width, target.extent.width);
state.height = std::min(state.height, target.extent.height); state.height = std::min(state.height, target.extent.height);
state.num_layers = std::min(state.num_layers, view.layer_count); state.num_layers = std::min(state.num_layers, view.layer_count);
auto& attachment = state.color_attachments[i]; auto& attachment = state.color_attachments[i];
attachment.image_view = target.image_view; attachment.image_view = target.image_view;
attachment.image_layout = layout; attachment.image_layout = layout;
attachment.clear_value = target.color_clear_value.uint32; attachment.clear_value = target.color_clear_value.uint32;
vk::ClearColorValue metadata_clear_value {}; vk::ClearColorValue metadata_clear_value {};
const bool metadata_clear = const bool metadata_clear =
ResolveDccAttachmentClear(cache, target, view, metadata_clear_value); ResolveDccAttachmentClear(cache, target, view, metadata_clear_value);
if (metadata_clear) { if (metadata_clear) {
attachment.clear_value = metadata_clear_value.uint32; 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"); EXIT("failed to consume HTile clear state\n");
} }
auto& image = cache.GetImage(depth.image_id); 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); EXIT_IF(depth.image_view == nullptr || image.backing.samples != depth.samples);
if (attachment_samples == 0) { if (attachment_samples == 0) {
attachment_samples = depth.samples; attachment_samples = depth.samples;
@@ -862,6 +866,9 @@ static PreparedVertexBuffers AcquireVertexBuffers(RenderCommandBuffer& b
Libs::LibKernel::Memory::ClampRangeSize(range.base_address, range.RequestedSize()); Libs::LibKernel::Memory::ClampRangeSize(range.base_address, range.RequestedSize());
range.acquired_end = range.base_address + size; range.acquired_end = range.base_address + size;
range.binding = cache.ObtainBuffer(buffer, 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. // 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.buffers[i] = range->binding.buffer;
prepared.offsets[i] = range->binding.offset + vertex.addr - range->base_address; 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) { if (null_owner != nullptr) {
@@ -1104,6 +1115,15 @@ static PreparedIndexBuffer PrepareIndexBuffer(RenderCommandBuffer& buffe
prepared.buffer = binding.buffer; prepared.buffer = binding.buffer;
prepared.offset = binding.offset; 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; return prepared;
} }
+21
View File
@@ -10,10 +10,13 @@
#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include "common/emulatorConfig.h"
#include "graphics/guest_gpu/gpu_defs.h" #include "graphics/guest_gpu/gpu_defs.h"
#include <cstdint> #include <cstdint>
#include <fmt/format.h>
#include <string> #include <string>
#include <utility>
#include <vector> #include <vector>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_hash.hpp> #include <vulkan/vulkan_hash.hpp>
@@ -29,6 +32,24 @@ std::string VulkanToString(vk::QueueFlags value);
vk::Format VulkanFormat(Prospero::BufferFormat guest_format); vk::Format VulkanFormat(Prospero::BufferFormat guest_format);
void RequireVulkanSuccess(vk::Result result, const char* operation); 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> template <typename T, typename Enumerator>
[[nodiscard]] std::vector<T> EnumerateVulkan(const char* operation, Enumerator&& enumerate) { [[nodiscard]] std::vector<T> EnumerateVulkan(const char* operation, Enumerator&& enumerate) {
for (;;) { for (;;) {