mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
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:
@@ -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};
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user