Files
Mihawk 7a736e3a1c Enable XMB as the default menu on the Vulkan GPU path
Ship the pinned monochrome icons/font, refresh configure flags before builds,
and seed the title asset directory. Correct strip expansion/counts and padded
texture coordinates, populate ribbon descriptors, and retain startup asset logs.
Use single-level static images until mip-chain sampling is separately verified.
RGUI and video_ps5 remain available; PS5_Vulkan is unchanged.

The named edit count grows from 86 to 100 for these XMB changes. All five
tools/verify.sh gates pass (31 unit tests); fresh patch replay/idempotence passes.
The owner confirms flawless rendering, backed by GPU framebuffer readback.
The final normal title runs for 45 seconds with zero refusals/API failures,
loaded assets, successful presentations, and no screenshot instrumentation.

Evidence: evidence/xmb-default/{capture,expectation}.json
Reproduce: tools/verify.sh; tools/run-title.sh --no-build --watch 45;
python3 tools/evidence.py compare evidence/
2026-09-19 12:16:46 -04:00

61 lines
2.6 KiB
C++

/* PS5 RetroArch - bounded diagnostic readback through the driver's debug API.
* Copyright (C) 2026 Mihawk
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "gfx/include/vulkan/vulkan.h"
#include <cstdio>
extern "C" void *ps5vk_debug_image_storage(VkImage image, size_t *bytes);
struct Stage
{
void *address;
size_t bytes;
};
extern "C" uint32_t ps5vk_debug_pipeline_stages(VkDevice, Stage *, uint32_t);
extern "C" uint32_t ps5vk_debug_buffers(VkDevice, Stage *, uint32_t);
extern "C" uint32_t ps5vk_debug_table_chunks(VkDevice, Stage *, uint32_t);
extern "C" void ps5_capture_images(unsigned frame, VkImage menu, VkImage target, VkDevice device)
{
if (frame == 120)
{
Stage stages[64] = {};
for (unsigned kind = 0; kind < 3; ++kind)
{
const char *name = kind == 0 ? "stages" : kind == 1 ? "buffers" : "tables";
uint32_t count = kind == 0 ? ps5vk_debug_pipeline_stages(device, stages, 64)
: kind == 1 ? ps5vk_debug_buffers(device, stages, 64)
: ps5vk_debug_table_chunks(device, stages, 64);
for (uint32_t i = 0; i < count && i < 64; ++i)
{
if (stages[i].bytes > 4 * 1024 * 1024)
continue;
char path[96];
std::snprintf(path, sizeof(path), "/app0/gpu-%s-%u.bin", name, i);
FILE *file = std::fopen(path, "wb");
const size_t written =
file ? std::fwrite(stages[i].address, 1, stages[i].bytes, file) : 0;
const int closed = file ? std::fclose(file) : -1;
std::fprintf(stderr,
"gpu resources: %s %u address=%p bytes=%zu written=%zu close=%d\n",
name, i, stages[i].address, stages[i].bytes, written, closed);
}
}
}
const VkImage images[] = {menu, target};
const char *names[] = {"menu", "target"};
for (unsigned i = 0; i < 2; ++i)
{
size_t bytes = 0;
const void *pixels = ps5vk_debug_image_storage(images[i], &bytes);
char path[96];
std::snprintf(path, sizeof(path), "/app0/gpu-%s-%u.bin", names[i], frame);
FILE *file = pixels && bytes ? std::fopen(path, "wb") : nullptr;
size_t written = file ? std::fwrite(pixels, 1, bytes, file) : 0;
const int closed = file ? std::fclose(file) : -1;
std::fprintf(stderr, "gpu capture: %s frame=%u bytes=%zu written=%zu close=%d\n", names[i],
frame, bytes, written, closed);
}
}