preserve DB_DEPTH_SIZE_XY and add tiled readback

This commit is contained in:
nmzik 2026-07-17 21:56:09 +02:00
parent 42d42e3258
commit f136c46519
7 changed files with 88 additions and 5 deletions

View File

@ -4138,7 +4138,7 @@ void GraphicsInitJmpTablesCxIndirect() {
HW::DepthDepthSizeXY r;
r.x_max = KYTY_PM4_GET(value, DB_DEPTH_SIZE_XY, X_MAX);
r.y_max = KYTY_PM4_GET(value, DB_DEPTH_SIZE_XY, Y_MAX);
r.valid = (r.x_max != 0 || r.y_max != 0);
r.valid = true;
cp->GetCtx()->SetDepthDepthSizeXY(r);
};
g_hw_ctx_indirect_func[Pm4::DB_DEPTH_SIZE] = [](KYTY_HW_CTX_INDIRECT_ARGS) {

View File

@ -1793,6 +1793,32 @@ static void TileConvertTiledToLinearStandard64KB64Elements(
}
}
static void TileConvertLinearToTiledStandard64KB64Elements(
void* dst, const void* src, uint32_t width_elements, uint32_t height_elements,
uint32_t pitch_elements, uint64_t size, uint64_t dst_size, uint32_t dst_x, uint32_t dst_y) {
if (width_elements > pitch_elements) {
EXIT("invalid linear-to-Standard64KB64 tail conversion, extent=%ux%u pitch=%u "
"size=0x%016" PRIx64 " dst_size=0x%016" PRIx64 " dst=%u,%u\n",
width_elements, height_elements, pitch_elements, size, dst_size, dst_x, dst_y);
}
auto* dst64 = static_cast<uint64_t*>(dst);
const auto* src64 = static_cast<const uint64_t*>(src);
const auto& tables = GetStandard64KB64Tables();
const auto size_words = size >> 3u;
const auto dst_size_words = dst_size >> 3u;
for (uint32_t y = 0; y < height_elements; y++) {
const uint64_t src_row = static_cast<uint64_t>(y) * pitch_elements;
const uint64_t dst_row = tables.y_words[dst_y + y];
for (uint32_t x = 0; x < width_elements; x++) {
const uint64_t src_index = src_row + x;
const uint64_t dst_index = dst_row + tables.x_words[dst_x + x];
if (src_index < size_words && dst_index < dst_size_words) {
dst64[dst_index] = src64[src_index];
}
}
}
}
static void TileConvertTiledToLinearStandard64KB128Elements(
void* dst, const void* src, uint32_t width_elements, uint32_t height_elements,
uint32_t pitch_elements, uint64_t size, uint64_t src_size, uint32_t src_x, uint32_t src_y) {
@ -2474,8 +2500,20 @@ void TileConvertTiledToLinearRenderTarget(void* dst, const void* src, uint32_t w
void TileConvertLinearToTiledRenderTarget(void* dst, const void* src, uint32_t width,
uint32_t height, uint32_t pitch,
uint32_t bytes_per_element, uint64_t size) {
uint32_t bytes_per_element, uint64_t size,
uint64_t dst_size, uint32_t dst_x, uint32_t dst_y) {
KYTY_PROFILER_FUNCTION();
const bool tail_block = dst_size != 0 && (dst_x != 0 || dst_y != 0 || size < dst_size);
if (tail_block) {
//Not sure about this at all
if (bytes_per_element != 8) {
EXIT("unsupported linear-to-tiled render-target tail element size: %u\n",
bytes_per_element);
}
TileConvertLinearToTiledStandard64KB64Elements(dst, src, width, height, pitch, size,
dst_size, dst_x, dst_y);
return;
}
if (dst == nullptr || src == nullptr || width == 0 || height == 0 || pitch == 0 ||
width > pitch || bytes_per_element == 0 || size == 0 || size % bytes_per_element != 0) {

View File

@ -44,7 +44,9 @@ void TileConvertTiledToLinearRenderTarget(void* dst, const void* src, uint32_t w
uint32_t src_y = 0);
void TileConvertLinearToTiledRenderTarget(void* dst, const void* src, uint32_t width,
uint32_t height, uint32_t pitch,
uint32_t bytes_per_element, uint64_t size);
uint32_t bytes_per_element, uint64_t size,
uint64_t dst_size = 0, uint32_t dst_x = 0,
uint32_t dst_y = 0);
void TileConvertTiledToLinearStandard64KB(void* dst, const void* src, uint32_t format,
uint32_t width, uint32_t height, uint32_t pitch,
uint64_t size, uint64_t src_size = 0, uint32_t src_x = 0,

View File

@ -130,6 +130,10 @@ struct TextureVulkanImage: public GpuTextureVulkanImage {
};
struct StorageTextureVulkanImage: public GpuTextureVulkanImage {
struct StorageView {
uint32_t base_level = 0;
VkImageView view = nullptr;
};
struct SampledView {
VkFormat format = VK_FORMAT_UNDEFINED;
uint32_t swizzle = 0;
@ -141,6 +145,8 @@ struct StorageTextureVulkanImage: public GpuTextureVulkanImage {
StorageTextureVulkanImage(): GpuTextureVulkanImage(VulkanImageType::StorageTexture) {}
std::mutex sampled_view_mutex;
std::vector<SampledView> sampled_views;
std::mutex storage_view_mutex;
std::vector<StorageView> storage_views;
};
struct RenderTextureVulkanImage: public VulkanImage {

View File

@ -126,7 +126,10 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
z.htile_surface.prefetch_height == 0 && z.htile_surface.dst_outside_zero_to_one == 0 &&
z.z_read_base_addr == 0 && z.z_write_base_addr == 0 && z.stencil_read_base_addr == 0 &&
z.stencil_write_base_addr == 0 && z.htile_data_base_addr == 0 &&
!z.z_info.tile_surface_enable && !z.size.valid && !z.width_height_valid &&
// DB_DEPTH_SIZE_XY is independent state and may remain programmed after the attachment
// formats and addresses are unbound. A zero encoding is the valid 1x1 value, so its
// presence alone must not manufacture a depth attachment.
!z.z_info.tile_surface_enable && !z.width_height_valid &&
!z.pitch_height_valid && z.size.x_max == 0 && z.size.y_max == 0 &&
z.pitch_div8_minus1 == 0 && z.height_div8_minus1 == 0 && z.slice_div64_minus1 == 0 &&
z.width == 0 && z.height == 0;
@ -215,7 +218,7 @@ void ResolveRenderDepthTarget(uint64_t submit_id, CommandBuffer* buffer, const H
} else if (z.htile_data_base_addr != 0) {
DepthFatal("HTile address without an enabled tile surface");
}
const bool size_xy_valid = z.size.valid && (z.size.x_max != 0 || z.size.y_max != 0);
const bool size_xy_valid = z.size.valid;
const bool wh_valid = z.width_height_valid && z.width != 0 && z.height != 0;
if (!size_xy_valid && !wh_valid) {
DepthFatal("missing depth extent");

View File

@ -2,6 +2,7 @@
#include "common/assert.h"
#include "graphics/guest_gpu/gpu_defs.h"
#include "graphics/guest_gpu/gpu_format.h"
#include "graphics/guest_gpu/tile.h"
#include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/objects/textureCommon.h"
@ -170,6 +171,38 @@ void Tiler::TileImage(void* dst, const void* src, const RenderTargetInfo& info)
}
}
void Tiler::TileImage(void* dst, const void* src, const ImageInfo& info) const {
const bool image_2d = info.type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) &&
info.depth == 1;
const auto bytes_per_element = Prospero::RenderTargetBytesPerElement(info.format);
if (!image_2d || info.levels == 0 || info.levels > 16 ||
info.tile != Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
bytes_per_element == 0) {
EXIT("Tiler: unsupported storage-texture tile, addr=0x%016" PRIx64
"+0x%016" PRIx64 " extent=%ux%ux%u levels=%u tile=%u format=%u\n",
info.address, info.size, info.width, info.height, info.depth, info.levels, info.tile,
info.format);
}
auto layout = TextureCalcUploadLayout(info.format, info.width, info.height, info.levels,
info.depth, info.pitch, info.tile, info.size, true, false,
false, "StorageTextureReadback");
auto regions = TextureBuildUploadRegions(
layout, Prospero::SurfaceFormat(info.format), info.width, info.height, info.depth,
info.levels, false, false, TextureUploadDestination::MipLevels,
TextureUploadSliceLayout::MipChainPerSlice);
std::memset(dst, 0, info.size);
for (uint32_t level = 0; level < info.levels; level++) {
const auto& level_size = layout.level_sizes[level];
const auto guest_offset = level_size.src_size != 0 ? level_size.src_offset
: level_size.offset;
auto* guest = static_cast<uint8_t*>(dst) + guest_offset;
const auto* linear = static_cast<const uint8_t*>(src) + regions[level].offset;
TileConvertLinearToTiledRenderTarget(
guest, linear, regions[level].width, regions[level].height, regions[level].pitch,
bytes_per_element, level_size.size, level_size.src_size, level_size.x, level_size.y);
}
}
void Tiler::TileImage(void* dst, const void* src, const DepthTargetInfo& info) const {
if (info.stencil_address != 0 || info.stencil_size != 0 ||
info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kDepth) ||

View File

@ -25,6 +25,7 @@ public:
const DepthTargetInfo& info, const BufferImageCopySource& source,
bool refresh, uint32_t base_layer = 0) const;
void TileImage(void* dst, const void* src, const RenderTargetInfo& info) const;
void TileImage(void* dst, const void* src, const ImageInfo& info) const;
void TileImage(void* dst, const void* src, const DepthTargetInfo& info) const;
};