mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-02 12:45:46 -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/elf_info.h
|
||||||
src/common/endian.h
|
src/common/endian.h
|
||||||
src/common/enum.h
|
src/common/enum.h
|
||||||
|
src/common/incremental_id.h
|
||||||
src/common/io_file.cpp
|
src/common/io_file.cpp
|
||||||
src/common/io_file.h
|
src/common/io_file.h
|
||||||
src/common/lru_cache.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);
|
image_id = texture_cache.FindImage(desc);
|
||||||
auto* image = &texture_cache.GetImage(image_id);
|
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.
|
// If this image has an associated depth image, it's a stencil attachment.
|
||||||
// Redirect the access to the actual depth-stencil buffer.
|
// 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);
|
image = &texture_cache.GetImage(image_id);
|
||||||
}
|
}
|
||||||
if (image->binding.is_bound) {
|
if (image->binding.is_bound) {
|
||||||
|
|||||||
@ -15,6 +15,8 @@ namespace VideoCore {
|
|||||||
|
|
||||||
using namespace Vulkan;
|
using namespace Vulkan;
|
||||||
|
|
||||||
|
Common::IncrementalIdProvider<u64> Image::global_image_uid{};
|
||||||
|
|
||||||
static vk::ImageUsageFlags ImageUsageFlags(const Vulkan::Instance* instance,
|
static vk::ImageUsageFlags ImageUsageFlags(const Vulkan::Instance* instance,
|
||||||
const ImageInfo& info) {
|
const ImageInfo& info) {
|
||||||
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eTransferSrc |
|
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) {
|
if (info.pixel_format == vk::Format::eUndefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
image_uid = global_image_uid.Next();
|
||||||
mip_hashes.resize(info.resources.levels);
|
mip_hashes.resize(info.resources.levels);
|
||||||
// Here we force `eExtendedUsage` as don't know all image usage cases beforehand. In normal case
|
// 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
|
// the texture cache should re-create the resource with the usage requested
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/enum.h"
|
#include "common/enum.h"
|
||||||
|
#include "common/incremental_id.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "video_core/renderer_vulkan/vk_common.h"
|
#include "video_core/renderer_vulkan/vk_common.h"
|
||||||
#include "video_core/texture_cache/image_info.h"
|
#include "video_core/texture_cache/image_info.h"
|
||||||
@ -111,8 +112,14 @@ struct Image {
|
|||||||
return True(flags & ImageFlagBits::GpuModified) && False(flags & (ImageFlagBits::Dirty));
|
return True(flags & ImageFlagBits::GpuModified) && False(flags & (ImageFlagBits::Dirty));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssociateDepth(ImageId image_id) {
|
void AssociateDepth(ImageId depth_image_id, u64 depth_image_uid) {
|
||||||
depth_id = image_id;
|
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);
|
ImageView& FindView(const ImageViewInfo& view_info, bool ensure_guest_samples = true);
|
||||||
@ -149,6 +156,7 @@ public:
|
|||||||
VAddr track_addr = 0;
|
VAddr track_addr = 0;
|
||||||
VAddr track_addr_end = 0;
|
VAddr track_addr_end = 0;
|
||||||
ImageId depth_id{};
|
ImageId depth_id{};
|
||||||
|
u64 depth_uid{};
|
||||||
|
|
||||||
// Resource state tracking
|
// Resource state tracking
|
||||||
vk::ImageUsageFlags usage_flags;
|
vk::ImageUsageFlags usage_flags;
|
||||||
@ -169,6 +177,7 @@ public:
|
|||||||
std::deque<BackingImage> backing_images;
|
std::deque<BackingImage> backing_images;
|
||||||
BackingImage* backing{};
|
BackingImage* backing{};
|
||||||
boost::container::static_vector<u64, 16> mip_hashes{};
|
boost::container::static_vector<u64, 16> mip_hashes{};
|
||||||
|
u64 image_uid{};
|
||||||
u64 lru_id{};
|
u64 lru_id{};
|
||||||
u64 tick_accessed_last{};
|
u64 tick_accessed_last{};
|
||||||
u64 hash{};
|
u64 hash{};
|
||||||
@ -187,6 +196,9 @@ public:
|
|||||||
u32 needs_rebind : 1;
|
u32 needs_rebind : 1;
|
||||||
u32 force_general : 1;
|
u32 force_general : 1;
|
||||||
} binding{};
|
} binding{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Common::IncrementalIdProvider<u64> global_image_uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // 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);
|
slot_images.insert(instance, scheduler, blit_helper, slot_image_views, info);
|
||||||
RegisterImage(stencil_id);
|
RegisterImage(stencil_id);
|
||||||
}
|
}
|
||||||
Image& image = slot_images[stencil_id];
|
Image& stencil_image = slot_images[stencil_id];
|
||||||
TouchImage(image);
|
TouchImage(stencil_image);
|
||||||
image.AssociateDepth(image_id);
|
stencil_image.AssociateDepth(image_id, image.image_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return image.FindView(desc.view_info, false);
|
return image.FindView(desc.view_info, false);
|
||||||
|
|||||||
@ -152,6 +152,23 @@ public:
|
|||||||
return slot_image_views[id];
|
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.
|
/// Returns true if the specified address is a metadata surface.
|
||||||
bool IsMeta(VAddr address) const {
|
bool IsMeta(VAddr address) const {
|
||||||
return surface_metas.contains(address);
|
return surface_metas.contains(address);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user