graphics: image, tiling and video-out fixes for this title

- Treat tile mode 0x10 as linear when computing a texture layout; it reaches
  here from this title and has no tiled interpretation.
- Add the video-out format policies this title asks for.
- Assorted swapchain, window and presenter handling needed to keep flipping
  through the intro.
This commit is contained in:
Mac
2026-08-31 23:41:37 +05:30
parent e6ad3dc8a5
commit b56807b75d
14 changed files with 741 additions and 38 deletions
+113
View File
@@ -1,4 +1,5 @@
#include "common/assert.h"
#include "common/timer.h"
#include "common/common.h"
#include "common/profiler.h"
#include "common/threads.h"
@@ -13,8 +14,13 @@
#include "graphics/host_gpu/vulkanCommon.h"
#include <algorithm>
#include <array>
#include <atomic>
#include <bit>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
namespace Libs::Graphics {
CommandBuffer::CommandBuffer(CommandScheduler& scheduler)
@@ -29,6 +35,90 @@ vk::CommandBuffer CommandBuffer::Handle() const {
return m_buffer;
}
static constexpr size_t CHECKPOINT_RING_SIZE = 4096;
static std::array<GpuCheckpoint, CHECKPOINT_RING_SIZE> g_checkpoints {};
static std::atomic<uint64_t> g_checkpoint_next {0};
static GpuCheckpoint* AllocateCheckpoint(uint32_t phase) {
const auto index = g_checkpoint_next.fetch_add(1, std::memory_order_relaxed);
auto* entry = &g_checkpoints[index % CHECKPOINT_RING_SIZE];
*entry = GpuCheckpoint {};
entry->phase = phase;
return entry;
}
static void DumpDeviceFaultInfo(GraphicContext& graphics) {
vk::DeviceFaultCountsEXT counts {};
counts.sType = vk::StructureType::eDeviceFaultCountsEXT;
auto result = graphics.device.getFaultInfoEXT(&counts, nullptr);
if (result != vk::Result::eSuccess) {
return;
}
std::vector<vk::DeviceFaultAddressInfoEXT> addresses(counts.addressInfoCount);
std::vector<vk::DeviceFaultVendorInfoEXT> vendors(counts.vendorInfoCount);
vk::DeviceFaultInfoEXT info {};
info.sType = vk::StructureType::eDeviceFaultInfoEXT;
info.pAddressInfos = addresses.empty() ? nullptr : addresses.data();
info.pVendorInfos = vendors.empty() ? nullptr : vendors.data();
counts.vendorBinarySize = 0; // vendor binary is a crash dump blob, not useful in the log
result = graphics.device.getFaultInfoEXT(&counts, &info);
if (result != vk::Result::eSuccess && result != vk::Result::eIncomplete) {
return;
}
for (uint32_t i = 0; i < counts.addressInfoCount; i++) {
const auto& a = addresses[i];
const uint64_t precision = a.addressPrecision != 0 ? a.addressPrecision : 1;
}
for (uint32_t i = 0; i < counts.vendorInfoCount; i++) {
const auto& v = vendors[i];
}
}
void GpuCrashDiagnosticsDump(GraphicContext& graphics, const char* context_text) {
if (!graphics.diagnostic_checkpoints_enabled && !graphics.device_fault_enabled) {
return;
}
if (graphics.diagnostic_checkpoints_enabled) {
Common::LockGuard lock(graphics.queue_mutex);
auto checkpoints2 = graphics.queue.getCheckpointData2NV();
for (const auto& data: checkpoints2) {
const auto* entry = static_cast<const GpuCheckpoint*>(data.pCheckpointMarker);
const bool ours =
entry >= g_checkpoints.data() && entry < g_checkpoints.data() + CHECKPOINT_RING_SIZE;
if (!ours) {
continue;
}
}
const auto recorded = g_checkpoint_next.load(std::memory_order_relaxed);
const auto show = std::min<uint64_t>(recorded, 12);
for (uint64_t i = recorded - show; i < recorded; i++) {
const auto& entry = g_checkpoints[i % CHECKPOINT_RING_SIZE];
}
auto checkpoints = graphics.queue.getCheckpointDataNV();
for (const auto& data: checkpoints) {
const auto* entry = static_cast<const GpuCheckpoint*>(data.pCheckpointMarker);
if (entry < g_checkpoints.data() || entry >= g_checkpoints.data() + CHECKPOINT_RING_SIZE ||
(reinterpret_cast<uintptr_t>(entry) - reinterpret_cast<uintptr_t>(g_checkpoints.data())) %
sizeof(GpuCheckpoint) !=
0) {
continue;
}
}
}
if (graphics.device_fault_enabled) {
DumpDeviceFaultInfo(graphics);
}
}
void CommandBuffer::Begin() {
EXIT_IF(m_rendering || IsInvalid());
auto buffer = Handle();
@@ -42,12 +132,23 @@ void CommandBuffer::Begin() {
auto result = buffer.begin(&begin_info);
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
if (m_graphics.diagnostic_checkpoints_enabled) {
m_checkpoint_begin = AllocateCheckpoint(0);
m_checkpoint_end = nullptr;
buffer.setCheckpointNV(m_checkpoint_begin);
}
}
void CommandBuffer::End() const {
EndRendering();
auto buffer = Handle();
if (m_graphics.diagnostic_checkpoints_enabled) {
m_checkpoint_end = AllocateCheckpoint(1);
buffer.setCheckpointNV(m_checkpoint_end);
}
auto result = buffer.end();
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
@@ -62,6 +163,18 @@ void CommandBuffer::SetDebugInfo(uint32_t op, uint64_t submit_id, uint32_t arg0,
m_debug_arg2 = arg2;
m_debug_arg3 = arg3;
m_debug_arg4 = arg4;
if (m_graphics.diagnostic_checkpoints_enabled && !IsInvalid()) {
auto* entry = AllocateCheckpoint(2);
entry->debug_op = op;
entry->submit_id = submit_id;
entry->arg0 = arg0;
entry->arg1 = arg1;
entry->arg2 = arg2;
entry->arg3 = arg3;
entry->arg4 = arg4;
Handle().setCheckpointNV(entry);
}
}
void CommandBuffer::BeginRendering(const RenderState& state) const {
@@ -358,7 +358,7 @@ struct VideoOutFormatPolicy {
VideoOutPixelFormatInfo info;
};
inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {{
inline constexpr std::array<VideoOutFormatPolicy, 12> VIDEO_OUT_FORMAT_POLICIES {{
{0x8000000022000000ull,
{vk::Format::eR8G8B8A8Srgb, Prospero::BufferFormat::k8_8_8_8Srgb, 4, false}},
{0x8000000000000000ull,
@@ -371,6 +371,18 @@ inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {
{vk::Format::eR16G16B16A16Sfloat, Prospero::BufferFormat::k16_16_16_16Float, 8, false}},
{0xc001000600000000ull,
{vk::Format::eR16G16B16A16Sfloat, Prospero::BufferFormat::k16_16_16_16Float, 8, true}},
{0x8100000622000000ull,
{vk::Format::eA2B10G10R10UnormPack32, Prospero::BufferFormat::k10_10_10_2UNorm, 4, false}},
{0x8100000600000000ull,
{vk::Format::eA2R10G10B10UnormPack32, Prospero::BufferFormat::k10_10_10_2UNorm, 4, false}},
{0x8100070422000000ull,
{vk::Format::eA2B10G10R10UnormPack32, Prospero::BufferFormat::k10_10_10_2UNorm, 4, false}},
{0x8100070400000000ull,
{vk::Format::eA2R10G10B10UnormPack32, Prospero::BufferFormat::k10_10_10_2UNorm, 4, false}},
{0xc001070722000000ull,
{vk::Format::eR16G16B16A16Sfloat, Prospero::BufferFormat::k16_16_16_16Float, 8, false}},
{0xc001070700000000ull,
{vk::Format::eR16G16B16A16Sfloat, Prospero::BufferFormat::k16_16_16_16Float, 8, true}},
}};
[[nodiscard]] inline bool DecodeVideoOutPixelFormat(uint64_t pixel_format,
@@ -212,7 +212,12 @@ TextureUploadLayout TextureCalcUploadLayout(Prospero::BufferFormat format, uint3
levels);
}
switch (tile_mode) {
auto effective_tile_mode = tile_mode;
if (static_cast<uint32_t>(tile_mode) == 0x10u) {
effective_tile_mode = Prospero::TileMode::kLinear;
}
switch (effective_tile_mode) {
case Prospero::TileMode::kLinear:
if (!TileGetTextureElementLayout(format, element)) {
EXIT("%s: unsupported linear texture format: fmt=%u\n", owner,
@@ -239,7 +244,7 @@ TextureUploadLayout TextureCalcUploadLayout(Prospero::BufferFormat format, uint3
break;
}
if (tile_mode != Prospero::TileMode::kLinear) {
if (effective_tile_mode != Prospero::TileMode::kLinear) {
element = {layout.surface.texture.block.bytes_per_element,
layout.surface.texture.texel_width, layout.surface.texture.texel_height};
}
+1
View File
@@ -38,6 +38,7 @@ constexpr FormatMapping kFormatMappings[] = {
{Prospero::BufferFormat::k11_11_10Float, vk::Format::eB10G11R11UfloatPack32},
{Prospero::BufferFormat::k10_10_10_2UNorm, vk::Format::eA2B10G10R10UnormPack32},
{Prospero::BufferFormat::k10_10_10_2UInt, vk::Format::eA2B10G10R10UintPack32},
{Prospero::BufferFormat::k10_10_10_2SInt, vk::Format::eA2B10G10R10UintPack32},
{Prospero::BufferFormat::k8_8_8_8UNorm, vk::Format::eR8G8B8A8Unorm},
{Prospero::BufferFormat::k8_8_8_8SNorm, vk::Format::eR8G8B8A8Snorm},
{Prospero::BufferFormat::k8_8_8_8UInt, vk::Format::eR8G8B8A8Uint},
+8 -2
View File
@@ -16,6 +16,7 @@
#include <cstdint>
#include <fmt/format.h>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <vulkan/vulkan.hpp>
@@ -44,8 +45,13 @@ void SetVulkanObjectNameF(vk::Device device, Handle handle, fmt::format_string<A
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)));
using CType = typename Handle::CType;
if constexpr (std::is_pointer_v<CType>) {
info.objectHandle =
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(static_cast<CType>(handle)));
} else {
info.objectHandle = static_cast<uint64_t>(static_cast<CType>(handle));
}
info.pObjectName = name.c_str();
(void)device.setDebugUtilsObjectNameEXT(&info);
}