mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
Handle stencil storage/depth transitions
This commit is contained in:
@@ -326,6 +326,7 @@ inline constexpr std::array<VideoOutFormatPolicy, 6> VIDEO_OUT_FORMAT_POLICIES {
|
|||||||
enum class DepthOverlap : uint8_t {
|
enum class DepthOverlap : uint8_t {
|
||||||
None,
|
None,
|
||||||
RetireSampled,
|
RetireSampled,
|
||||||
|
RetireStorage,
|
||||||
ExpandTarget,
|
ExpandTarget,
|
||||||
DiscardTarget,
|
DiscardTarget,
|
||||||
Unsupported
|
Unsupported
|
||||||
@@ -815,6 +816,23 @@ ClassifyStorageBufferRebind(bool buffer_overlap, bool cached_gpu_modified,
|
|||||||
return DepthOverlap::Unsupported;
|
return DepthOverlap::Unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mirrors storage -> depth-target binding transition. An inaccessible stencil aspect
|
||||||
|
// does not require the otherwise necessary image content copy.
|
||||||
|
[[nodiscard]] inline DepthOverlap ClassifyStorageDepthOverlap(const ImageInfo& storage,
|
||||||
|
const DepthTargetInfo& depth) {
|
||||||
|
const bool overlaps_depth = ImageRangeOverlaps(storage.address, storage.size, depth.address,
|
||||||
|
depth.size);
|
||||||
|
const bool overlaps_stencil = depth.stencil_address != 0 &&
|
||||||
|
ImageRangeOverlaps(storage.address, storage.size,
|
||||||
|
depth.stencil_address, depth.stencil_size);
|
||||||
|
if (!overlaps_depth && !overlaps_stencil) {
|
||||||
|
return DepthOverlap::None;
|
||||||
|
}
|
||||||
|
return !overlaps_depth && overlaps_stencil && !depth.stencil_access
|
||||||
|
? DepthOverlap::RetireStorage
|
||||||
|
: DepthOverlap::Unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline RenderTargetOverlap
|
[[nodiscard]] inline RenderTargetOverlap
|
||||||
ClassifyRenderTargetOverlap(const ImageInfo& sampled, bool sampled_gpu_modified, bool same_context,
|
ClassifyRenderTargetOverlap(const ImageInfo& sampled, bool sampled_gpu_modified, bool same_context,
|
||||||
const RenderTargetInfo& target) {
|
const RenderTargetInfo& target) {
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ namespace Libs::Graphics {
|
|||||||
uint32_t width, uint32_t height,
|
uint32_t width, uint32_t height,
|
||||||
uint32_t depth) noexcept {
|
uint32_t depth) noexcept {
|
||||||
return (format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) &&
|
return (format == Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt) &&
|
||||||
type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) && width == 1 &&
|
type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) && width != 0 &&
|
||||||
height == 1 && depth == 1) ||
|
height != 0 && depth == 1) ||
|
||||||
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) &&
|
(format == Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt) &&
|
||||||
type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && width != 0 &&
|
type == Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) && width != 0 &&
|
||||||
height != 0 && depth == 1);
|
height != 0 && depth == 1);
|
||||||
|
|||||||
@@ -2533,6 +2533,7 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
|||||||
std::shared_ptr<CachedImage> sampled_depth_source;
|
std::shared_ptr<CachedImage> sampled_depth_source;
|
||||||
std::shared_ptr<CachedImage> native_depth_source;
|
std::shared_ptr<CachedImage> native_depth_source;
|
||||||
std::shared_ptr<CachedImage> discarded_depth_source;
|
std::shared_ptr<CachedImage> discarded_depth_source;
|
||||||
|
std::shared_ptr<CachedImage> retired_storage_source;
|
||||||
for (const auto& entry: m_images) {
|
for (const auto& entry: m_images) {
|
||||||
auto& cached = *entry;
|
auto& cached = *entry;
|
||||||
const bool overlaps =
|
const bool overlaps =
|
||||||
@@ -2554,6 +2555,9 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
|||||||
cached.buffer_modified, cached.ctx == ctx, info);
|
cached.buffer_modified, cached.ctx == ctx, info);
|
||||||
break;
|
break;
|
||||||
case CachedImage::Kind::StorageTexture:
|
case CachedImage::Kind::StorageTexture:
|
||||||
|
overlap = cached.ctx == ctx ? ClassifyStorageDepthOverlap(cached.info, info)
|
||||||
|
: DepthOverlap::Unsupported;
|
||||||
|
break;
|
||||||
case CachedImage::Kind::RenderTarget:
|
case CachedImage::Kind::RenderTarget:
|
||||||
case CachedImage::Kind::VideoOut: break;
|
case CachedImage::Kind::VideoOut: break;
|
||||||
}
|
}
|
||||||
@@ -2565,9 +2569,20 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
|||||||
sampled_depth_source = entry;
|
sampled_depth_source = entry;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DepthOverlap::RetireStorage:
|
||||||
|
supported = cached.kind == CachedImage::Kind::StorageTexture &&
|
||||||
|
cached.gpu_modified && !cached.buffer_modified &&
|
||||||
|
!cached.info.IsCpuDirty() &&
|
||||||
|
retired_storage_source == nullptr && native_depth_source == nullptr &&
|
||||||
|
discarded_depth_source == nullptr;
|
||||||
|
if (supported) {
|
||||||
|
retired_storage_source = entry;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DepthOverlap::ExpandTarget:
|
case DepthOverlap::ExpandTarget:
|
||||||
supported =
|
supported =
|
||||||
cached.kind == CachedImage::Kind::DepthTarget && native_depth_source == nullptr;
|
cached.kind == CachedImage::Kind::DepthTarget && native_depth_source == nullptr &&
|
||||||
|
retired_storage_source == nullptr;
|
||||||
if (supported) {
|
if (supported) {
|
||||||
native_depth_source = entry;
|
native_depth_source = entry;
|
||||||
}
|
}
|
||||||
@@ -2575,6 +2590,7 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
|||||||
case DepthOverlap::DiscardTarget:
|
case DepthOverlap::DiscardTarget:
|
||||||
supported = cached.kind == CachedImage::Kind::DepthTarget &&
|
supported = cached.kind == CachedImage::Kind::DepthTarget &&
|
||||||
discarded_depth_source == nullptr && native_depth_source == nullptr;
|
discarded_depth_source == nullptr && native_depth_source == nullptr;
|
||||||
|
supported = supported && retired_storage_source == nullptr;
|
||||||
if (supported) {
|
if (supported) {
|
||||||
discarded_depth_source = entry;
|
discarded_depth_source = entry;
|
||||||
}
|
}
|
||||||
@@ -2591,8 +2607,17 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
|||||||
retire.push_back(&cached);
|
retire.push_back(&cached);
|
||||||
}
|
}
|
||||||
RequireRetirementIsolation(retire, "depth target", info.address, info.size);
|
RequireRetirementIsolation(retire, "depth target", info.address, info.size);
|
||||||
RetireImages(retire, native_depth_source != nullptr ? native_depth_source.get()
|
if (retired_storage_source != nullptr) {
|
||||||
: discarded_depth_source.get());
|
m_memory_tracker.UnmarkRegionAsGpuModified(retired_storage_source->info.address,
|
||||||
|
retired_storage_source->info.size);
|
||||||
|
retired_storage_source->gpu_modified = false;
|
||||||
|
}
|
||||||
|
const auto* transition_source = native_depth_source != nullptr
|
||||||
|
? native_depth_source.get()
|
||||||
|
: (discarded_depth_source != nullptr
|
||||||
|
? discarded_depth_source.get()
|
||||||
|
: nullptr);
|
||||||
|
RetireImages(retire, transition_source);
|
||||||
const bool coherent_guest_stencil =
|
const bool coherent_guest_stencil =
|
||||||
has_stencil &&
|
has_stencil &&
|
||||||
IsCoherentGuestImageSource(stencil_source, info.stencil_address, info.stencil_size);
|
IsCoherentGuestImageSource(stencil_source, info.stencil_address, info.stencil_size);
|
||||||
@@ -2614,6 +2639,9 @@ DepthStencilVulkanImage* TextureCache::FindDepthTarget(CommandBuffer* command, G
|
|||||||
if (discarded_depth_source != nullptr) {
|
if (discarded_depth_source != nullptr) {
|
||||||
command->RetainResourceUntilFence(discarded_depth_source);
|
command->RetainResourceUntilFence(discarded_depth_source);
|
||||||
}
|
}
|
||||||
|
if (retired_storage_source != nullptr) {
|
||||||
|
command->RetainResourceUntilFence(retired_storage_source);
|
||||||
|
}
|
||||||
if (native_depth_source != nullptr) {
|
if (native_depth_source != nullptr) {
|
||||||
const auto& old = native_depth_source->depth;
|
const auto& old = native_depth_source->depth;
|
||||||
if (old.layers >= info.layers || native_depth_source->image->layers != old.layers) {
|
if (old.layers >= info.layers || native_depth_source->image->layers != old.layers) {
|
||||||
|
|||||||
@@ -9747,7 +9747,7 @@ ShaderTextureResource BasicUintVolumeStorageTextureDescriptor() {
|
|||||||
} else if (std::strcmp(kind, "depth-tile-extent") == 0) {
|
} else if (std::strcmp(kind, "depth-tile-extent") == 0) {
|
||||||
resource = Ppsa14053DepthTileStorageTextureResource();
|
resource = Ppsa14053DepthTileStorageTextureResource();
|
||||||
descriptor = Ppsa14053DepthTileStorageTextureDescriptor();
|
descriptor = Ppsa14053DepthTileStorageTextureDescriptor();
|
||||||
descriptor.fields[2] |= 1u;
|
descriptor.fields[4] |= 1u;
|
||||||
} else {
|
} else {
|
||||||
std::_Exit(0x7e);
|
std::_Exit(0x7e);
|
||||||
}
|
}
|
||||||
@@ -10874,6 +10874,34 @@ void CheckStorageTextureSampledReuse() {
|
|||||||
std::printf("[host] %-32s ok\n", "StorageTextureSampledReuse");
|
std::printf("[host] %-32s ok\n", "StorageTextureSampledReuse");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckStorageTextureDepthAlias() {
|
||||||
|
ImageInfo storage{};
|
||||||
|
storage.address = 0x201ae60000ull;
|
||||||
|
storage.size = 0x870000;
|
||||||
|
DepthTargetInfo depth{};
|
||||||
|
depth.address = 0x2046ca0000ull;
|
||||||
|
depth.size = 0x1fe0000;
|
||||||
|
depth.stencil_address = storage.address;
|
||||||
|
depth.stencil_size = storage.size;
|
||||||
|
Require("StorageTextureDepthAlias", "inactive stencil",
|
||||||
|
ClassifyStorageDepthOverlap(storage, depth) == DepthOverlap::RetireStorage,
|
||||||
|
"inactive stencil storage ownership was not retired");
|
||||||
|
depth.stencil_access = true;
|
||||||
|
Require("StorageTextureDepthAlias", "active stencil",
|
||||||
|
ClassifyStorageDepthOverlap(storage, depth) == DepthOverlap::Unsupported,
|
||||||
|
"active stencil storage contents were discarded");
|
||||||
|
depth.stencil_access = false;
|
||||||
|
storage.address = depth.address;
|
||||||
|
Require("StorageTextureDepthAlias", "depth aspect",
|
||||||
|
ClassifyStorageDepthOverlap(storage, depth) == DepthOverlap::Unsupported,
|
||||||
|
"depth-aspect storage contents were discarded");
|
||||||
|
storage.address = 0x2000000000ull;
|
||||||
|
Require("StorageTextureDepthAlias", "disjoint",
|
||||||
|
ClassifyStorageDepthOverlap(storage, depth) == DepthOverlap::None,
|
||||||
|
"disjoint storage image was classified as an alias");
|
||||||
|
std::printf("[host] %-32s ok\n", "StorageTextureDepthAlias");
|
||||||
|
}
|
||||||
|
|
||||||
[[noreturn]] void RunStorageTextureAccessDeathCase(const char *kind) {
|
[[noreturn]] void RunStorageTextureAccessDeathCase(const char *kind) {
|
||||||
constexpr uintptr_t base = 0x0000000200300000ull;
|
constexpr uintptr_t base = 0x0000000200300000ull;
|
||||||
constexpr uint64_t size = 0x10000;
|
constexpr uint64_t size = 0x10000;
|
||||||
@@ -12900,6 +12928,7 @@ int main(int argc, char **argv) {
|
|||||||
CheckStorageTextureVolumeUploadLayout();
|
CheckStorageTextureVolumeUploadLayout();
|
||||||
CheckStorageTextureGpuOwnedRebindState();
|
CheckStorageTextureGpuOwnedRebindState();
|
||||||
CheckStorageTextureSampledReuse();
|
CheckStorageTextureSampledReuse();
|
||||||
|
CheckStorageTextureDepthAlias();
|
||||||
CheckStorageTextureAccessPermissions();
|
CheckStorageTextureAccessPermissions();
|
||||||
CheckMetaOverlapDeaths();
|
CheckMetaOverlapDeaths();
|
||||||
CheckOverlappingMetadataViews();
|
CheckOverlappingMetadataViews();
|
||||||
|
|||||||
Reference in New Issue
Block a user