mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 13:26:52 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0685bffb2f |
+30
-30
@@ -488,16 +488,15 @@ void TextureCache::RefreshCopySource(ImageId id) {
|
||||
}
|
||||
|
||||
bool TextureCache::CopyD16(Image& destination, Image& source) {
|
||||
const bool source_depth = source.info.IsDepth();
|
||||
const bool destination_depth = destination.info.IsDepth();
|
||||
if (source_depth == destination_depth) {
|
||||
// Converts guest D16 between a four-byte host depth aspect and two-byte color or D16 depth.
|
||||
const bool source_wide = DepthAspectTransferBytes(source.backing.format) == sizeof(uint32_t);
|
||||
if (source_wide == (DepthAspectTransferBytes(destination.backing.format) == sizeof(uint32_t))) {
|
||||
return false;
|
||||
}
|
||||
auto& depth = source_depth ? source : destination;
|
||||
auto& color = source_depth ? destination : source;
|
||||
const auto transfer_bytes = DepthAspectTransferBytes(depth.backing.format);
|
||||
auto& depth = source_wide ? source : destination;
|
||||
auto& narrow = source_wide ? destination : source;
|
||||
if (depth.info.bytes_per_block != sizeof(uint16_t) ||
|
||||
color.info.bytes_per_block != sizeof(uint16_t) || transfer_bytes != sizeof(uint32_t)) {
|
||||
narrow.info.bytes_per_block != sizeof(uint16_t)) {
|
||||
return false;
|
||||
}
|
||||
EXIT_IF(source.backing.samples != 1 || destination.backing.samples != 1 ||
|
||||
@@ -507,42 +506,42 @@ bool TextureCache::CopyD16(Image& destination, Image& source) {
|
||||
|
||||
const auto layers = depth.info.resources.layers;
|
||||
const uint64_t depth_slice =
|
||||
static_cast<uint64_t>(depth.info.pitch) * depth.info.extent.height * transfer_bytes;
|
||||
const uint64_t color_slice =
|
||||
static_cast<uint64_t>(color.info.pitch) * color.info.extent.height * sizeof(uint16_t);
|
||||
EXIT_IF(layers == 0 || depth_slice > UINT64_MAX / layers || color_slice > UINT64_MAX / layers);
|
||||
const auto depth_size = depth_slice * layers;
|
||||
const auto color_size = color_slice * layers;
|
||||
const std::array depth_copies {
|
||||
static_cast<uint64_t>(depth.info.pitch) * depth.info.extent.height * sizeof(uint32_t);
|
||||
const uint64_t narrow_slice =
|
||||
static_cast<uint64_t>(narrow.info.pitch) * narrow.info.extent.height * sizeof(uint16_t);
|
||||
EXIT_IF(layers == 0 || depth_slice > UINT64_MAX / layers || narrow_slice > UINT64_MAX / layers);
|
||||
const std::array depth_copies {
|
||||
vk::BufferImageCopy {0,
|
||||
depth.info.pitch,
|
||||
depth.info.extent.height,
|
||||
{vk::ImageAspectFlagBits::eDepth, 0, 0, layers},
|
||||
{},
|
||||
depth.info.extent}};
|
||||
const std::array color_copies {
|
||||
const std::array narrow_copies {
|
||||
vk::BufferImageCopy {0,
|
||||
color.info.pitch,
|
||||
color.info.extent.height,
|
||||
{vk::ImageAspectFlagBits::eColor, 0, 0, layers},
|
||||
narrow.info.pitch,
|
||||
narrow.info.extent.height,
|
||||
{narrow.info.IsDepth() ? vk::ImageAspectFlagBits::eDepth
|
||||
: vk::ImageAspectFlagBits::eColor,
|
||||
0, 0, layers},
|
||||
{},
|
||||
color.info.extent}};
|
||||
narrow.info.extent}};
|
||||
|
||||
auto depth_buffer = m_tiler.GetScratchBuffer(depth_size);
|
||||
auto color_buffer = m_tiler.GetScratchBuffer(color_size, depth_buffer.buffer);
|
||||
auto depth_buffer = m_tiler.GetScratchBuffer(depth_slice * layers);
|
||||
auto narrow_buffer = m_tiler.GetScratchBuffer(narrow_slice * layers, depth_buffer.buffer);
|
||||
const TileManager::D16Layout promote_layout {
|
||||
.width = depth.info.extent.width,
|
||||
.height = depth.info.extent.height,
|
||||
.layers = layers,
|
||||
.source_row_stride = static_cast<uint64_t>(color.info.pitch) * sizeof(uint16_t),
|
||||
.target_row_stride = static_cast<uint64_t>(depth.info.pitch) * transfer_bytes,
|
||||
.source_slice_stride = color_slice,
|
||||
.source_row_stride = static_cast<uint64_t>(narrow.info.pitch) * sizeof(uint16_t),
|
||||
.target_row_stride = static_cast<uint64_t>(depth.info.pitch) * sizeof(uint32_t),
|
||||
.source_slice_stride = narrow_slice,
|
||||
.target_slice_stride = depth_slice,
|
||||
};
|
||||
const bool d32 = DepthAspectTransferFormat(depth.backing.format) == vk::Format::eD32Sfloat;
|
||||
if (source_depth) {
|
||||
if (source_wide) {
|
||||
source.Download(depth_copies, depth_buffer.buffer, depth_buffer.offset, depth_buffer.size);
|
||||
m_tiler.ConvertD16(depth_buffer, color_buffer, TileManager::D16Direction::Demote, d32,
|
||||
m_tiler.ConvertD16(depth_buffer, narrow_buffer, TileManager::D16Direction::Demote, d32,
|
||||
{.width = promote_layout.width,
|
||||
.height = promote_layout.height,
|
||||
.layers = promote_layout.layers,
|
||||
@@ -550,11 +549,12 @@ bool TextureCache::CopyD16(Image& destination, Image& source) {
|
||||
.target_row_stride = promote_layout.source_row_stride,
|
||||
.source_slice_stride = promote_layout.target_slice_stride,
|
||||
.target_slice_stride = promote_layout.source_slice_stride});
|
||||
destination.Upload(color_copies, color_buffer.buffer, color_buffer.offset,
|
||||
color_buffer.size);
|
||||
destination.Upload(narrow_copies, narrow_buffer.buffer, narrow_buffer.offset,
|
||||
narrow_buffer.size);
|
||||
} else {
|
||||
source.Download(color_copies, color_buffer.buffer, color_buffer.offset, color_buffer.size);
|
||||
m_tiler.ConvertD16(color_buffer, depth_buffer, TileManager::D16Direction::Promote, d32,
|
||||
source.Download(narrow_copies, narrow_buffer.buffer, narrow_buffer.offset,
|
||||
narrow_buffer.size);
|
||||
m_tiler.ConvertD16(narrow_buffer, depth_buffer, TileManager::D16Direction::Promote, d32,
|
||||
promote_layout);
|
||||
destination.Upload(depth_copies, depth_buffer.buffer, depth_buffer.offset,
|
||||
depth_buffer.size);
|
||||
|
||||
@@ -9978,37 +9978,78 @@ public:
|
||||
d16_storage_desc.view_info.usage = vk::ImageUsageFlagBits::eStorage;
|
||||
const auto d16_storage_image =
|
||||
texture_cache.FindImage(d16_storage_desc, true);
|
||||
auto d16_storage_readback = CreateHostBuffer(
|
||||
name, sizeof(d16_fallback_values),
|
||||
vk::BufferUsageFlagBits::eTransferDst, std::vector<u32>(2, 0));
|
||||
auto &d16_storage_native = texture_cache.GetImage(d16_storage_image);
|
||||
d16_storage_native.Transit(vk::ImageLayout::eTransferSrcOptimal,
|
||||
vk::AccessFlagBits2::eTransferRead, {},
|
||||
scheduler.Current().Handle());
|
||||
vk::BufferImageCopy d16_storage_copy{};
|
||||
d16_storage_copy.bufferRowLength = 4;
|
||||
d16_storage_copy.imageSubresource = {vk::ImageAspectFlagBits::eColor, 0,
|
||||
0, 1};
|
||||
d16_storage_copy.imageExtent = {4, 1, 1};
|
||||
scheduler.Current().Handle().copyImageToBuffer(
|
||||
d16_storage_native.backing.image,
|
||||
vk::ImageLayout::eTransferSrcOptimal, d16_storage_readback.buffer, 1,
|
||||
&d16_storage_copy);
|
||||
HostReadBarrier(d16_storage_readback.buffer, d16_storage_readback.size,
|
||||
vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::AccessFlagBits::eTransferWrite);
|
||||
scheduler.Finish();
|
||||
const auto d16_storage_words = ReadBuffer(name, d16_storage_readback, 2);
|
||||
std::array<uint16_t, 4> d16_storage_values{};
|
||||
std::memcpy(d16_storage_values.data(), d16_storage_words.data(),
|
||||
sizeof(d16_storage_values));
|
||||
const auto read_texels = [&](ImageId id, vk::ImageAspectFlagBits aspect) {
|
||||
auto readback = CreateHostBuffer(name, 4 * sizeof(u32),
|
||||
vk::BufferUsageFlagBits::eTransferDst,
|
||||
std::vector<u32>(4, 0));
|
||||
auto &image = texture_cache.GetImage(id);
|
||||
image.Transit(vk::ImageLayout::eTransferSrcOptimal,
|
||||
vk::AccessFlagBits2::eTransferRead, {},
|
||||
scheduler.Current().Handle());
|
||||
const vk::BufferImageCopy copy{0, 4, 0, {aspect, 0, 0, 1}, {}, {4, 1, 1}};
|
||||
scheduler.Current().Handle().copyImageToBuffer(
|
||||
image.backing.image, vk::ImageLayout::eTransferSrcOptimal,
|
||||
readback.buffer, 1, ©);
|
||||
HostReadBarrier(readback.buffer, readback.size,
|
||||
vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::AccessFlagBits::eTransferWrite);
|
||||
scheduler.Finish();
|
||||
auto words = ReadBuffer(name, readback, 4);
|
||||
DestroyBuffer(&readback);
|
||||
return words;
|
||||
};
|
||||
const auto d16_storage_words =
|
||||
read_texels(d16_storage_image, vk::ImageAspectFlagBits::eColor);
|
||||
Require(
|
||||
name, "D16 fallback depth/storage copy",
|
||||
d16_storage_values == d16_fallback_values &&
|
||||
std::memcmp(d16_storage_words.data(), d16_fallback_values.data(),
|
||||
sizeof(d16_fallback_values)) == 0 &&
|
||||
d16_storage_image != d16_depth_image &&
|
||||
texture_cache.GetImage(d16_storage_image).IsGpuModified(),
|
||||
"D16 fallback reinterpreted four-byte host depth as two-byte color");
|
||||
DestroyBuffer(&d16_storage_readback);
|
||||
|
||||
// Dropping and re-adding the stencil plane keeps the D16 depth values.
|
||||
constexpr uint64_t d16_stenciled_offset = 0x33e000;
|
||||
constexpr std::array<uint16_t, 4> d16_stale_values{};
|
||||
std::memcpy(memory + d16_stenciled_offset, d16_fallback_values.data(),
|
||||
sizeof(d16_fallback_values));
|
||||
auto d16_stenciled_desc = d16_depth_desc;
|
||||
d16_stenciled_desc.info.data.address = base + d16_stenciled_offset;
|
||||
d16_stenciled_desc.info.stencil.address = base + 0x33f000;
|
||||
const auto d16_stenciled_image =
|
||||
texture_cache.FindImage(d16_stenciled_desc);
|
||||
(void)texture_cache.FindDepthTarget(d16_stenciled_image,
|
||||
d16_stenciled_desc);
|
||||
texture_cache.MarkGpuWritten(d16_stenciled_image);
|
||||
// Stale guest bytes: the values below can come only from image copies.
|
||||
Libs::LibKernel::Memory::WriteBacking(base + d16_stenciled_offset,
|
||||
d16_stale_values.data(),
|
||||
sizeof(d16_stale_values));
|
||||
auto d16_native_desc = d16_stenciled_desc;
|
||||
d16_native_desc.info.stencil = {};
|
||||
d16_native_desc.info.pixel_format = vk::Format::eD16Unorm;
|
||||
d16_native_desc.view_info.format = vk::Format::eD16Unorm;
|
||||
d16_native_desc.view_info.aspect = vk::ImageAspectFlagBits::eDepth;
|
||||
const auto d16_native_image = texture_cache.FindImage(d16_native_desc);
|
||||
const auto d16_native_words =
|
||||
read_texels(d16_native_image, vk::ImageAspectFlagBits::eDepth);
|
||||
Require(name, "D16 fallback depth/native depth copy",
|
||||
std::memcmp(d16_native_words.data(), d16_fallback_values.data(),
|
||||
sizeof(d16_fallback_values)) == 0 &&
|
||||
texture_cache.GetImage(d16_native_image).backing.format ==
|
||||
vk::Format::eD16Unorm,
|
||||
"D16 depth lost its values when its target dropped the stencil");
|
||||
const auto d16_restenciled_image =
|
||||
texture_cache.FindImage(d16_stenciled_desc);
|
||||
const auto d16_restenciled_words =
|
||||
read_texels(d16_restenciled_image, vk::ImageAspectFlagBits::eDepth);
|
||||
bool d16_promoted = d16_restenciled_image != d16_native_image;
|
||||
for (size_t i = 0; i < d16_fallback_values.size(); ++i) {
|
||||
d16_promoted &= (d16_restenciled_words[i] & 0x00ffffffu) ==
|
||||
EncodeD16AsD24(d16_fallback_values[i]);
|
||||
}
|
||||
Require(name, "D16 native depth/fallback depth copy", d16_promoted,
|
||||
"D16 depth lost its values when its target regained the stencil");
|
||||
|
||||
if (!texture_cache.GetImage(combined_destination_image).IsGpuModified()) {
|
||||
texture_cache.MarkGpuWritten(combined_destination_image);
|
||||
|
||||
Reference in New Issue
Block a user