mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
texture cache: convert D16<->D24/D32 depth copies instead of crashing (#1873)
gpu: convert guest D16 depth between native D16 and stenciled four-byte host depth Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
+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);
|
||||
|
||||
Reference in New Issue
Block a user