mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 14:26:53 +01:00
graphics: trust image-local readback validity
This commit is contained in:
+4
-12
@@ -222,14 +222,6 @@ TextureCache::BindingType TextureCache::UploadBinding(const Image& image) {
|
|||||||
return image.usage.storage ? BindingType::Storage : BindingType::Texture;
|
return image.usage.storage ? BindingType::Storage : BindingType::Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::SafeToDownload(const Image& image) {
|
|
||||||
if (!image.SafeToDownload()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto range = image.info.data;
|
|
||||||
return !m_buffer_cache.HasGpuDirtyBytes(range.address, range.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageId TextureCache::InsertImage(const ImageInfo& info) {
|
ImageId TextureCache::InsertImage(const ImageInfo& info) {
|
||||||
const auto id = m_slot_images.insert(m_graphics, m_scheduler, info);
|
const auto id = m_slot_images.insert(m_graphics, m_scheduler, info);
|
||||||
if (!info.data.Empty()) {
|
if (!info.data.Empty()) {
|
||||||
@@ -1360,7 +1352,7 @@ ImageId TextureCache::FindImageFromRange(uint64_t address, uint64_t size, bool e
|
|||||||
if (ensure_valid && owner->depth_id) {
|
if (ensure_valid && owner->depth_id) {
|
||||||
owner = m_slot_images.try_get(owner->depth_id);
|
owner = m_slot_images.try_get(owner->depth_id);
|
||||||
}
|
}
|
||||||
if (owner == nullptr || (ensure_valid && !SafeToDownload(*owner))) {
|
if (owner == nullptr || (ensure_valid && !owner->SafeToDownload())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
matches.push_back(id);
|
matches.push_back(id);
|
||||||
@@ -1751,7 +1743,7 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uin
|
|||||||
std::scoped_lock lock {m_texture_cache.m_lock};
|
std::scoped_lock lock {m_texture_cache.m_lock};
|
||||||
auto& image = m_texture_cache.m_slot_images[selected];
|
auto& image = m_texture_cache.m_slot_images[selected];
|
||||||
// The GPU thread owns image retirement; CPU invalidation can dirty this image after lookup.
|
// The GPU thread owns image retirement; CPU invalidation can dirty this image after lookup.
|
||||||
if (!m_texture_cache.SafeToDownload(image)) {
|
if (!image.SafeToDownload()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!buffer.IsInBounds(image.info.data.address, 1)) {
|
if (!buffer.IsInBounds(image.info.data.address, 1)) {
|
||||||
@@ -1814,7 +1806,7 @@ bool TextureCache::DownloadImageMemory(ImageId id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto transfer = BuildDownload(image);
|
auto transfer = BuildDownload(image);
|
||||||
if (!transfer.valid || !SafeToDownload(image)) {
|
if (!transfer.valid || !image.SafeToDownload()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto range = image.info.data;
|
const auto range = image.info.data;
|
||||||
@@ -2001,7 +1993,7 @@ void TextureCache::RunGarbageCollector() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (owner->IsGpuModified()) {
|
if (owner->IsGpuModified()) {
|
||||||
const bool safe = SafeToDownload(*owner);
|
const bool safe = owner->SafeToDownload();
|
||||||
if (safe && owner->info.IsTiled()) {
|
if (safe && owner->info.IsTiled()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ private:
|
|||||||
[[nodiscard]] static bool SameBacking(const ImageInfo& cached, const ImageInfo& requested,
|
[[nodiscard]] static bool SameBacking(const ImageInfo& cached, const ImageInfo& requested,
|
||||||
bool exact_format);
|
bool exact_format);
|
||||||
[[nodiscard]] static BindingType UploadBinding(const Image& image);
|
[[nodiscard]] static BindingType UploadBinding(const Image& image);
|
||||||
[[nodiscard]] bool SafeToDownload(const Image& image);
|
|
||||||
|
|
||||||
// Caller holds m_lock; it also serializes the per-image query epoch.
|
// Caller holds m_lock; it also serializes the per-image query epoch.
|
||||||
[[nodiscard]] ImageIds FindImagesInRegion(uint64_t address, uint64_t size,
|
[[nodiscard]] ImageIds FindImagesInRegion(uint64_t address, uint64_t size,
|
||||||
|
|||||||
@@ -7288,12 +7288,16 @@ public:
|
|||||||
"failed to create the overlapping dirty Buffer owner");
|
"failed to create the overlapping dirty Buffer owner");
|
||||||
exact_buffer.first->Fill(exact_buffer.second, sizeof(uint32_t),
|
exact_buffer.first->Fill(exact_buffer.second, sizeof(uint32_t),
|
||||||
dirty_sibling_value);
|
dirty_sibling_value);
|
||||||
|
texture_cache.InvalidateMemoryFromGPU(base + exact_image_offset,
|
||||||
|
sizeof(uint32_t));
|
||||||
Libs::Graphics::Buffer exact_download(
|
Libs::Graphics::Buffer exact_download(
|
||||||
m_runtime_context, scheduler, MemoryUsage::DeviceLocal,
|
m_runtime_context, scheduler, MemoryUsage::DeviceLocal,
|
||||||
base + exact_image_offset, AllFlags, sizeof(uint32_t));
|
base + exact_image_offset, AllFlags, sizeof(uint32_t));
|
||||||
Require(name, "overlapping buffer ownership rejection",
|
Require(name, "overlapping buffer ownership rejection",
|
||||||
!texture_cache.FindImageFromRange(base + exact_image_offset,
|
!texture_cache.FindImageFromRange(base + exact_image_offset,
|
||||||
sizeof(uint32_t)) &&
|
sizeof(uint32_t)) &&
|
||||||
|
!TextureCacheTestAccess::TryDownload(texture_cache,
|
||||||
|
exact_image) &&
|
||||||
!BufferCacheTestAccess::SynchronizeBufferFromImage(
|
!BufferCacheTestAccess::SynchronizeBufferFromImage(
|
||||||
resources.GetBufferCache(), exact_download,
|
resources.GetBufferCache(), exact_download,
|
||||||
base + exact_image_offset, sizeof(uint32_t)),
|
base + exact_image_offset, sizeof(uint32_t)),
|
||||||
@@ -7350,8 +7354,9 @@ public:
|
|||||||
Require(
|
Require(
|
||||||
name, "CPU-dirty image range validity",
|
name, "CPU-dirty image range validity",
|
||||||
!texture_cache.FindImageFromRange(gc_image_desc_a.info.data.address,
|
!texture_cache.FindImageFromRange(gc_image_desc_a.info.data.address,
|
||||||
gc_image_desc_a.info.data.size),
|
gc_image_desc_a.info.data.size) &&
|
||||||
"FindImageFromRange accepted CPU-dirty native contents");
|
!TextureCacheTestAccess::TryDownload(texture_cache, gc_images[0]),
|
||||||
|
"CPU-dirty native contents remained eligible for image readback");
|
||||||
texture_cache.MarkGpuWritten(gc_images[0]);
|
texture_cache.MarkGpuWritten(gc_images[0]);
|
||||||
for (size_t index = 0; index < gc_image_offsets.size(); index++) {
|
for (size_t index = 0; index < gc_image_offsets.size(); index++) {
|
||||||
Libs::LibKernel::Memory::WriteBacking(base + gc_image_offsets[index],
|
Libs::LibKernel::Memory::WriteBacking(base + gc_image_offsets[index],
|
||||||
@@ -7440,11 +7445,33 @@ public:
|
|||||||
TextureCacheTestAccess::SetLinearReadback(texture_cache, true);
|
TextureCacheTestAccess::SetLinearReadback(texture_cache, true);
|
||||||
const auto submit_readback_image =
|
const auto submit_readback_image =
|
||||||
texture_cache.FindImage(submit_readback_desc);
|
texture_cache.FindImage(submit_readback_desc);
|
||||||
|
auto submit_buffer = resources.GetBufferCache().ObtainBuffer(
|
||||||
|
submit_readback_desc.info.data.address,
|
||||||
|
submit_readback_desc.info.data.size, true);
|
||||||
|
Require(name, "linear submit dirty buffer allocation",
|
||||||
|
submit_buffer.first != nullptr,
|
||||||
|
"failed to create the older GPU Buffer contents");
|
||||||
|
submit_buffer.first->Fill(submit_buffer.second, sizeof(uint32_t),
|
||||||
|
submit_readback_stale);
|
||||||
|
texture_cache.InvalidateMemoryFromGPU(
|
||||||
|
submit_readback_desc.info.data.address,
|
||||||
|
submit_readback_desc.info.data.size);
|
||||||
|
(void)texture_cache.FindTexture(submit_readback_image,
|
||||||
|
submit_readback_desc);
|
||||||
Require(name, "linear submit image clear",
|
Require(name, "linear submit image clear",
|
||||||
texture_cache.ClearImageFromBuffer(
|
texture_cache.ClearImageFromBuffer(
|
||||||
command, submit_readback_desc.info.data.address,
|
command, submit_readback_desc.info.data.address,
|
||||||
submit_readback_desc.info.data.size, submit_readback_value),
|
submit_readback_desc.info.data.size, submit_readback_value),
|
||||||
"failed to create GPU-current linear storage contents");
|
"failed to create GPU-current linear storage contents");
|
||||||
|
Require(name, "older buffer permits current image readback",
|
||||||
|
resources.GetBufferCache().HasGpuDirtyBytes(
|
||||||
|
submit_readback_desc.info.data.address,
|
||||||
|
submit_readback_desc.info.data.size) &&
|
||||||
|
texture_cache.FindImageFromRange(
|
||||||
|
submit_readback_desc.info.data.address,
|
||||||
|
submit_readback_desc.info.data.size) ==
|
||||||
|
submit_readback_image,
|
||||||
|
"historical GPU Buffer dirtiness rejected newer image contents");
|
||||||
TextureCacheTestAccess::TrackDownload(texture_cache,
|
TextureCacheTestAccess::TrackDownload(texture_cache,
|
||||||
submit_readback_image);
|
submit_readback_image);
|
||||||
Libs::LibKernel::Memory::WriteBacking(
|
Libs::LibKernel::Memory::WriteBacking(
|
||||||
@@ -35485,7 +35512,9 @@ int main(int argc, char **argv) {
|
|||||||
vulkan.CheckRenderExecutorColorStandardTileDiscovery();
|
vulkan.CheckRenderExecutorColorStandardTileDiscovery();
|
||||||
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
||||||
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
||||||
|
#endif
|
||||||
vulkan.CheckUnifiedTextureCacheFlow();
|
vulkan.CheckUnifiedTextureCacheFlow();
|
||||||
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
vulkan.CheckBgra16Readback();
|
vulkan.CheckBgra16Readback();
|
||||||
vulkan.CheckRasterization(false);
|
vulkan.CheckRasterization(false);
|
||||||
vulkan.CheckRasterization(false, true);
|
vulkan.CheckRasterization(false, true);
|
||||||
|
|||||||
Reference in New Issue
Block a user