mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-02 04:38:28 -06:00
video_core: check if depth image is valid before using it (#4479)
* check if depth image is valid before using it * fix uid usage
This commit is contained in:
parent
f1873bb1d8
commit
2ff3487dbc
@ -741,6 +741,7 @@ set(COMMON src/common/logging/classes.h
|
||||
src/common/elf_info.h
|
||||
src/common/endian.h
|
||||
src/common/enum.h
|
||||
src/common/incremental_id.h
|
||||
src/common/io_file.cpp
|
||||
src/common/io_file.h
|
||||
src/common/lru_cache.h
|
||||
|
||||
22
src/common/incremental_id.h
Normal file
22
src/common/incremental_id.h
Normal file
@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
|
||||
namespace Common {
|
||||
template <typename CounterType>
|
||||
class IncrementalIdProvider {
|
||||
public:
|
||||
IncrementalIdProvider() : counter(0) {}
|
||||
~IncrementalIdProvider() = default;
|
||||
|
||||
CounterType Next() {
|
||||
return counter.fetch_add(1, std::memory_order_relaxed) + 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<CounterType> counter;
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
@ -702,10 +702,10 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
|
||||
|
||||
image_id = texture_cache.FindImage(desc);
|
||||
auto* image = &texture_cache.GetImage(image_id);
|
||||
if (image->depth_id) {
|
||||
if (auto depth_image_id = texture_cache.GetAssociatedDepth(*image)) {
|
||||
// If this image has an associated depth image, it's a stencil attachment.
|
||||
// Redirect the access to the actual depth-stencil buffer.
|
||||
image_id = image->depth_id;
|
||||
image_id = depth_image_id;
|
||||
image = &texture_cache.GetImage(image_id);
|
||||
}
|
||||
if (image->binding.is_bound) {
|
||||
|
||||
@ -15,6 +15,8 @@ namespace VideoCore {
|
||||
|
||||
using namespace Vulkan;
|
||||
|
||||
Common::IncrementalIdProvider<u64> Image::global_image_uid{};
|
||||
|
||||
static vk::ImageUsageFlags ImageUsageFlags(const Vulkan::Instance* instance,
|
||||
const ImageInfo& info) {
|
||||
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc |
|
||||
@ -119,6 +121,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||
if (info.pixel_format == vk::Format::eUndefined) {
|
||||
return;
|
||||
}
|
||||
image_uid = global_image_uid.Next();
|
||||
mip_hashes.resize(info.resources.levels);
|
||||
// Here we force `eExtendedUsage` as don't know all image usage cases beforehand. In normal case
|
||||
// the texture cache should re-create the resource with the usage requested
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/enum.h"
|
||||
#include "common/incremental_id.h"
|
||||
#include "common/types.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
#include "video_core/texture_cache/image_info.h"
|
||||
@ -111,8 +112,14 @@ struct Image {
|
||||
return True(flags & ImageFlagBits::GpuModified) && False(flags & (ImageFlagBits::Dirty));
|
||||
}
|
||||
|
||||
void AssociateDepth(ImageId image_id) {
|
||||
depth_id = image_id;
|
||||
void AssociateDepth(ImageId depth_image_id, u64 depth_image_uid) {
|
||||
depth_id = depth_image_id;
|
||||
depth_uid = depth_image_uid;
|
||||
}
|
||||
|
||||
void DisassociateDepth() {
|
||||
depth_id = {};
|
||||
depth_uid = {};
|
||||
}
|
||||
|
||||
ImageView& FindView(const ImageViewInfo& view_info, bool ensure_guest_samples = true);
|
||||
@ -149,6 +156,7 @@ public:
|
||||
VAddr track_addr = 0;
|
||||
VAddr track_addr_end = 0;
|
||||
ImageId depth_id{};
|
||||
u64 depth_uid{};
|
||||
|
||||
// Resource state tracking
|
||||
vk::ImageUsageFlags usage_flags;
|
||||
@ -169,6 +177,7 @@ public:
|
||||
std::deque<BackingImage> backing_images;
|
||||
BackingImage* backing{};
|
||||
boost::container::static_vector<u64, 16> mip_hashes{};
|
||||
u64 image_uid{};
|
||||
u64 lru_id{};
|
||||
u64 tick_accessed_last{};
|
||||
u64 hash{};
|
||||
@ -187,6 +196,9 @@ public:
|
||||
u32 needs_rebind : 1;
|
||||
u32 force_general : 1;
|
||||
} binding{};
|
||||
|
||||
private:
|
||||
static Common::IncrementalIdProvider<u64> global_image_uid;
|
||||
};
|
||||
|
||||
} // namespace VideoCore
|
||||
|
||||
@ -708,9 +708,9 @@ ImageView& TextureCache::FindDepthTarget(ImageId image_id, const ImageDesc& desc
|
||||
slot_images.insert(instance, scheduler, blit_helper, slot_image_views, info);
|
||||
RegisterImage(stencil_id);
|
||||
}
|
||||
Image& image = slot_images[stencil_id];
|
||||
TouchImage(image);
|
||||
image.AssociateDepth(image_id);
|
||||
Image& stencil_image = slot_images[stencil_id];
|
||||
TouchImage(stencil_image);
|
||||
stencil_image.AssociateDepth(image_id, image.image_uid);
|
||||
}
|
||||
|
||||
return image.FindView(desc.view_info, false);
|
||||
|
||||
@ -152,6 +152,23 @@ public:
|
||||
return slot_image_views[id];
|
||||
}
|
||||
|
||||
/// Get the associated depth stencil image if it is still valid.
|
||||
ImageId GetAssociatedDepth(Image& image) {
|
||||
if (!image.depth_id) {
|
||||
return {};
|
||||
}
|
||||
if (slot_images.is_allocated(image.depth_id)) {
|
||||
auto& depth_image = slot_images[image.depth_id];
|
||||
if (depth_image.image_uid == image.depth_uid &&
|
||||
depth_image.flags & ImageFlagBits::Registered) {
|
||||
return image.depth_id;
|
||||
}
|
||||
}
|
||||
// The linked depth image is no longer valid, disassociate it.
|
||||
image.DisassociateDepth();
|
||||
return {};
|
||||
}
|
||||
|
||||
/// Returns true if the specified address is a metadata surface.
|
||||
bool IsMeta(VAddr address) const {
|
||||
return surface_metas.contains(address);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user