Support layered PS5 image alias transitions

This commit is contained in:
nmzik committed 2026-07-16 21:56:09 +02:00
1 parent f743a48c03
commit ae86249765
17 files changed
+1740 -814

No files matched your search

+81 -34
View File
@@ -8,11 +8,12 @@
#include "graphics/host_gpu/renderer/image.h"
#include "graphics/host_gpu/utils.h"
#include <vector>
namespace Libs::Graphics {
void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image,
const ImageInfo& info, const BufferImageCopySource& source,
bool refresh, bool storage) const {
void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image, const ImageInfo& info,
const BufferImageCopySource& source, bool refresh, bool storage) const {
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
info.width == 0 || info.height == 0 || info.depth == 0 || info.levels == 0 ||
info.levels >= 16 || !source.cpu_current || source.address != info.address ||
@@ -50,16 +51,19 @@ void Tiler::DetileImage(GraphicContext* ctx, GpuTextureVulkanImage* image,
}
void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
const DepthTargetInfo& info, const BufferImageCopySource& source,
bool refresh) const {
const bool d16 = info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2;
const DepthTargetInfo& info, const BufferImageCopySource& source,
bool refresh, uint32_t base_layer) const {
const bool d16 =
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k16UNorm) &&
info.format == VK_FORMAT_D16_UNORM && info.bytes_per_element == 2;
const bool d32 =
info.guest_format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) &&
(info.format == VK_FORMAT_D32_SFLOAT || info.format == VK_FORMAT_D32_SFLOAT_S8_UINT) &&
info.bytes_per_element == 4;
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
info.width == 0 || info.height == 0 || info.pitch < info.width ||
info.width == 0 || info.height == 0 || info.pitch < info.width || info.layers == 0 ||
info.size % info.layers != 0 || base_layer > image->layers ||
info.layers > image->layers - base_layer || info.size > UINT32_MAX ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || (!d16 && !d32) ||
!source.cpu_current || source.address != info.address || source.size != info.size ||
(source.buffer == nullptr && source.offset != 0)) {
@@ -76,38 +80,55 @@ void Tiler::DetileImage(GraphicContext* ctx, DepthStencilVulkanImage* image,
if (refresh) {
VulkanDeviceWaitIdle(ctx);
}
UtilScratchBuffer linear(info.size);
TileConvertTiledToLinearDepth(linear.Data(), reinterpret_cast<const void*>(source.address),
info.guest_format, info.width, info.height, info.pitch,
info.size);
UtilFillImage(ctx, image, linear.Data(), info.size, info.pitch, VK_IMAGE_ASPECT_DEPTH_BIT);
const auto slice_size = info.size / info.layers;
UtilScratchBuffer linear(info.size);
std::vector<BufferImageCopy> regions;
regions.reserve(info.layers);
for (uint32_t layer = 0; layer < info.layers; layer++) {
auto* linear_slice = static_cast<uint8_t*>(linear.Data()) + slice_size * layer;
auto* guest_slice = reinterpret_cast<const uint8_t*>(source.address) + slice_size * layer;
TileConvertTiledToLinearDepth(linear_slice, guest_slice, info.guest_format, info.width,
info.height, info.pitch, slice_size);
BufferImageCopy region {};
region.offset = static_cast<uint32_t>(slice_size * layer);
region.pitch = info.pitch;
region.width = info.width;
region.height = info.height;
region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
regions.push_back(region);
}
UtilFillImage(ctx, image, linear.Data(), info.size, regions,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
const DepthTargetInfo& info, const BufferImageCopySource& source,
bool refresh) const {
bool refresh, uint32_t base_layer) const {
TileSizeAlign stencil_size {};
TileSizeAlign htile_size {};
TileSizeAlign depth_size {};
const auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
const auto stencil_pitch = TileGetTexturePitch(
stencil_format, info.width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
const bool supported_layout =
const auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
const auto stencil_pitch = TileGetTexturePitch(
stencil_format, info.width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
const bool supported_layout =
TileGetDepthSize(info.width, info.height, 0,
Prospero::GpuEnumValue(Prospero::DepthFormat::kZ32F),
Prospero::GpuEnumValue(Prospero::StencilFormat::k8UInt),
info.htile_address != 0, &stencil_size, &htile_size, &depth_size) &&
stencil_size.size == info.stencil_size && stencil_size.align == 65536 &&
info.layers != 0 && info.stencil_size % info.layers == 0 &&
stencil_size.size == info.stencil_size / info.layers && stencil_size.align == 65536 &&
stencil_pitch != 0;
if (ctx == nullptr || image == nullptr || info.address == 0 || info.size == 0 ||
info.stencil_address == 0 || info.stencil_size == 0 || info.width == 0 ||
info.height == 0 || info.format != VK_FORMAT_D32_SFLOAT_S8_UINT ||
info.guest_format != Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float) ||
info.bytes_per_element != 4 ||
info.bytes_per_element != 4 || base_layer > image->layers ||
info.layers > image->layers - base_layer || info.stencil_size > UINT32_MAX ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||
info.stencil_htile_compressed || !supported_layout || !source.cpu_current ||
source.address != info.stencil_address ||
source.size != info.stencil_size || (source.buffer == nullptr && source.offset != 0)) {
source.address != info.stencil_address || source.size != info.stencil_size ||
(source.buffer == nullptr && source.offset != 0)) {
EXIT("Tiler: unsupported stencil detile, ctx=%p image=%p source_buffer=%p "
"source=0x%016" PRIx64 "+0x%016" PRIx64 " offset=0x%016" PRIx64
" current=%d stencil=0x%016" PRIx64 "+0x%016" PRIx64
@@ -122,12 +143,26 @@ void Tiler::DetileStencil(GraphicContext* ctx, DepthStencilVulkanImage* image,
if (refresh) {
VulkanDeviceWaitIdle(ctx);
}
UtilScratchBuffer linear(info.stencil_size);
TileConvertTiledToLinearDepth(linear.Data(), reinterpret_cast<const void*>(source.address),
stencil_format, info.width, info.height, stencil_pitch,
info.stencil_size);
UtilFillImage(ctx, image, linear.Data(), info.stencil_size, stencil_pitch,
VK_IMAGE_ASPECT_STENCIL_BIT);
const auto slice_size = info.stencil_size / info.layers;
UtilScratchBuffer linear(info.stencil_size);
std::vector<BufferImageCopy> regions;
regions.reserve(info.layers);
for (uint32_t layer = 0; layer < info.layers; layer++) {
auto* linear_slice = static_cast<uint8_t*>(linear.Data()) + slice_size * layer;
auto* guest_slice = reinterpret_cast<const uint8_t*>(source.address) + slice_size * layer;
TileConvertTiledToLinearDepth(linear_slice, guest_slice, stencil_format, info.width,
info.height, stencil_pitch, slice_size);
BufferImageCopy region {};
region.offset = static_cast<uint32_t>(slice_size * layer);
region.pitch = stencil_pitch;
region.width = info.width;
region.height = info.height;
region.dst_layer = base_layer + layer;
region.aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
regions.push_back(region);
}
UtilFillImage(ctx, image, linear.Data(), info.stencil_size, regions,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info) const {
@@ -135,7 +170,8 @@ void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info)
info.bytes_per_element == 4 || info.bytes_per_element == 8;
if (dst == nullptr || src == nullptr || info.address == 0 || info.size == 0 ||
info.width == 0 || info.height == 0 || info.pitch < info.width ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) || info.levels != 1 ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
info.levels != 1 || info.layers == 0 || info.size % info.layers != 0 ||
!supported_element) {
EXIT("Tiler: unsupported render-target tile, dst=%p src=%p "
"addr=0x%016" PRIx64 "+0x%016" PRIx64
@@ -143,8 +179,13 @@ void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info)
dst, src, info.address, info.size, info.width, info.height, info.pitch, info.levels,
info.tile_mode, info.bytes_per_element);
}
TileConvertLinearToTiledRenderTarget(dst, src, info.width, info.height, info.pitch,
info.bytes_per_element, info.size);
const auto slice_size = info.size / info.layers;
for (uint32_t layer = 0; layer < info.layers; layer++) {
auto* guest_slice = static_cast<uint8_t*>(dst) + slice_size * layer;
auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer;
TileConvertLinearToTiledRenderTarget(guest_slice, linear_slice, info.width, info.height,
info.pitch, info.bytes_per_element, slice_size);
}
}
void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) const {
@@ -156,7 +197,8 @@ void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) c
if (dst == nullptr || src == nullptr || info.address == 0 || info.size == 0 ||
info.stencil_address != 0 || info.stencil_size != 0 || info.width == 0 ||
info.height == 0 || info.pitch < info.width ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || !supported_format) {
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) || info.layers == 0 ||
info.size % info.layers != 0 || !supported_format) {
EXIT("Tiler: unsupported depth-target tile, dst=%p src=%p "
"depth=0x%016" PRIx64 "+0x%016" PRIx64 " stencil=0x%016" PRIx64 "+0x%016" PRIx64
" extent=%ux%u pitch=%u tile=%u format=%d guest_format=%u bpe=%u\n",
@@ -164,8 +206,13 @@ void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) c
info.height, info.pitch, info.tile_mode, static_cast<int>(info.format),
info.guest_format, info.bytes_per_element);
}
TileConvertLinearToTiledDepth(dst, src, info.guest_format, info.width, info.height, info.pitch,
info.size);
const auto slice_size = info.size / info.layers;
for (uint32_t layer = 0; layer < info.layers; layer++) {
auto* guest_slice = static_cast<uint8_t*>(dst) + slice_size * layer;
auto* linear_slice = static_cast<const uint8_t*>(src) + slice_size * layer;
TileConvertLinearToTiledDepth(guest_slice, linear_slice, info.guest_format, info.width,
info.height, info.pitch, slice_size);
}
}
} // namespace Libs::Graphics