mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 08:13:05 +00:00
Clear single-mip color targets reused from cached mip chains
This commit is contained in:
1 parent
190608ae20
commit
0ec3655f1c
2 files changed
+48
-14
No files matched your search
+1
-1
@@ -1121,7 +1121,7 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
|||||||
image.info.metadata = desc.info.metadata;
|
image.info.metadata = desc.info.metadata;
|
||||||
// Native color metadata must not retain a reused HTile/CMask/FMask clear flag.
|
// Native color metadata must not retain a reused HTile/CMask/FMask clear flag.
|
||||||
m_surface_metas.erase(range.address);
|
m_surface_metas.erase(range.address);
|
||||||
if (range.size == 0 || desc.info.resources.levels != 1 || image.info.resources.levels != 1) {
|
if (range.size == 0 || desc.info.resources.levels != 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9604,18 +9604,19 @@ public:
|
|||||||
constexpr uintptr_t base = 0x0000000204100000ull;
|
constexpr uintptr_t base = 0x0000000204100000ull;
|
||||||
constexpr uint64_t allocation_size = 0x200000;
|
constexpr uint64_t allocation_size = 0x200000;
|
||||||
constexpr uint64_t allocation_alignment = 0x10000;
|
constexpr uint64_t allocation_alignment = 0x10000;
|
||||||
constexpr uint64_t dcc_address = base + 0x100000;
|
|
||||||
struct FillCase {
|
struct FillCase {
|
||||||
uint32_t fill;
|
uint32_t fill;
|
||||||
std::array<uint32_t, 2> texel;
|
std::array<uint32_t, 2> texel;
|
||||||
bool reuse_unorm = false;
|
bool reuse_unorm = false;
|
||||||
bool cmask = false;
|
bool cmask = false;
|
||||||
|
bool reuse_mips = false;
|
||||||
};
|
};
|
||||||
constexpr std::array cases{
|
constexpr std::array cases{
|
||||||
FillCase{0x40404040u, {0, 0x3c000000u}},
|
FillCase{0x40404040u, {0, 0x3c000000u}},
|
||||||
FillCase{0x80808080u, {0x3c003c00u, 0x00003c00u}},
|
FillCase{0x80808080u, {0x3c003c00u, 0x00003c00u}},
|
||||||
FillCase{0x40404040u, {0, 0x3c000000u}, true},
|
FillCase{0x40404040u, {0, 0x3c000000u}, true},
|
||||||
FillCase{0, {0x804020ffu, 0}, false, true},
|
FillCase{0, {0x804020ffu, 0}, false, true},
|
||||||
|
FillCase{0x40404040u, {0, 0x3c000000u}, false, false, true},
|
||||||
};
|
};
|
||||||
EnsureRuntimeContext();
|
EnsureRuntimeContext();
|
||||||
// Astro's generic metadata fill, through S_ENDPGM; trailing debug data is omitted.
|
// Astro's generic metadata fill, through S_ENDPGM; trailing debug data is omitted.
|
||||||
@@ -9673,6 +9674,7 @@ public:
|
|||||||
std::memset(mapped, 0, allocation_size);
|
std::memset(mapped, 0, allocation_size);
|
||||||
|
|
||||||
for (const auto &fill_case : cases) {
|
for (const auto &fill_case : cases) {
|
||||||
|
const uint64_t dcc_address = base + (fill_case.reuse_mips ? 0x160000 : 0x100000);
|
||||||
const uint32_t selected_layer = fill_case.cmask ? 1 : 0;
|
const uint32_t selected_layer = fill_case.cmask ? 1 : 0;
|
||||||
const uint64_t metadata_size = fill_case.cmask ? 0x2000 : dcc_size.size;
|
const uint64_t metadata_size = fill_case.cmask ? 0x2000 : dcc_size.size;
|
||||||
const std::vector<u32> expected(
|
const std::vector<u32> expected(
|
||||||
@@ -9712,20 +9714,39 @@ public:
|
|||||||
auto &texture_cache = resources.GetTextureCache();
|
auto &texture_cache = resources.GetTextureCache();
|
||||||
auto &executor = context.GetRenderExecutor();
|
auto &executor = context.GetRenderExecutor();
|
||||||
resources.MapMemory(base, allocation_size);
|
resources.MapMemory(base, allocation_size);
|
||||||
ImageId unorm_id{};
|
ImageId preexisting_id{};
|
||||||
if (fill_case.reuse_unorm) {
|
if (fill_case.reuse_unorm || fill_case.reuse_mips) {
|
||||||
const auto float_info = registers.GetRenderTarget(0).info;
|
const auto float_info = registers.GetRenderTarget(0).info;
|
||||||
auto unorm_info = float_info;
|
const auto single_mip = registers.GetRenderTarget(0).attrib2;
|
||||||
unorm_info.dcc_compression_enable = false;
|
auto initial_info = float_info;
|
||||||
unorm_info.channel_type = Prospero::ChannelType::kUNorm;
|
initial_info.dcc_compression_enable = false;
|
||||||
registers.SetColorInfo(0, unorm_info);
|
initial_info.cmask_fast_clear_enable = false;
|
||||||
RenderColorInfo unorm{};
|
if (fill_case.reuse_unorm) {
|
||||||
|
initial_info.channel_type = Prospero::ChannelType::kUNorm;
|
||||||
|
}
|
||||||
|
auto initial_mips = single_mip;
|
||||||
|
initial_mips.num_mip_levels = fill_case.reuse_mips ? 1 : 0;
|
||||||
|
registers.SetColorInfo(0, initial_info);
|
||||||
|
registers.SetColorAttrib2(0, initial_mips);
|
||||||
|
RenderColorInfo preexisting{};
|
||||||
RenderExecutorTestAccess::ResolveRenderColorTarget(
|
RenderExecutorTestAccess::ResolveRenderColorTarget(
|
||||||
executor, scheduler.Current(), unorm, 0);
|
executor, scheduler.Current(), preexisting, 0);
|
||||||
unorm_id = unorm.image_id;
|
preexisting_id = preexisting.image_id;
|
||||||
(void)texture_cache.FindRenderTarget(unorm_id, unorm.desc);
|
(void)texture_cache.FindRenderTarget(preexisting_id, preexisting.desc);
|
||||||
|
if (fill_case.reuse_mips) {
|
||||||
|
Require(name, "mip chain excludes metadata",
|
||||||
|
preexisting.desc.info.data.address + preexisting.desc.info.data.size <=
|
||||||
|
dcc_address,
|
||||||
|
"the mip preservation fixture overlaps its color metadata");
|
||||||
|
vk::ClearValue clear{};
|
||||||
|
clear.color.float32 = std::array{1.0f, 0.0f, 1.0f, 0.0f};
|
||||||
|
TextureCacheTestAccess::ClearImage(
|
||||||
|
texture_cache, scheduler.Current(), preexisting_id,
|
||||||
|
{vk::ImageAspectFlagBits::eColor, 0, 2, 0, 1}, clear);
|
||||||
|
}
|
||||||
RenderExecutorTestAccess::ResetBindings(executor);
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
registers.SetColorInfo(0, float_info);
|
registers.SetColorInfo(0, float_info);
|
||||||
|
registers.SetColorAttrib2(0, single_mip);
|
||||||
}
|
}
|
||||||
const auto fill_metadata = [&](uint32_t count, bool raw = false) {
|
const auto fill_metadata = [&](uint32_t count, bool raw = false) {
|
||||||
const auto *shader = &native_fill;
|
const auto *shader = &native_fill;
|
||||||
@@ -9758,8 +9779,8 @@ public:
|
|||||||
executor, scheduler.Current(), &color, 1, no_depth);
|
executor, scheduler.Current(), &color, 1, no_depth);
|
||||||
if (fill_case.reuse_unorm) {
|
if (fill_case.reuse_unorm) {
|
||||||
Require(name, "FLOAT clear reuses UNORM image",
|
Require(name, "FLOAT clear reuses UNORM image",
|
||||||
color.image_id == unorm_id &&
|
color.image_id == preexisting_id &&
|
||||||
texture_cache.GetImage(unorm_id).backing.format ==
|
texture_cache.GetImage(preexisting_id).backing.format ==
|
||||||
vk::Format::eR16G16B16A16Unorm,
|
vk::Format::eR16G16B16A16Unorm,
|
||||||
"the aliased clear did not reuse its existing UNORM allocation");
|
"the aliased clear did not reuse its existing UNORM allocation");
|
||||||
}
|
}
|
||||||
@@ -9780,6 +9801,19 @@ public:
|
|||||||
ReadCachedTexel(name, context, color.image_id, {511, 255, 0},
|
ReadCachedTexel(name, context, color.image_id, {511, 255, 0},
|
||||||
{1, 1, 1}, selected_layer) == expected,
|
{1, 1, 1}, selected_layer) == expected,
|
||||||
"native metadata did not materialize the expected color");
|
"native metadata did not materialize the expected color");
|
||||||
|
if (fill_case.reuse_mips) {
|
||||||
|
const auto &image = texture_cache.GetImage(color.image_id);
|
||||||
|
Require(name, "single-mip clear reuses mip chain",
|
||||||
|
color.image_id == preexisting_id && image.info.resources.levels == 2 &&
|
||||||
|
color.desc.info.resources.levels == 1 &&
|
||||||
|
color.desc.view_info.base_level == 0 && color.desc.view_info.level_count == 1,
|
||||||
|
"the single-mip target did not retain its cached image and view scope");
|
||||||
|
Require(name, "single-mip clear preserves higher mip",
|
||||||
|
ReadCachedTexel(name, context, color.image_id, {255, 127, 0},
|
||||||
|
{1, 1, 1}, 0, 1) ==
|
||||||
|
std::vector<u32>{0x00003c00u, 0x00003c00u},
|
||||||
|
"clearing mip zero changed its higher mip");
|
||||||
|
}
|
||||||
const auto check_expanded_metadata = [&] {
|
const auto check_expanded_metadata = [&] {
|
||||||
context.GetBufferCache().ReadMemory(dcc_address, metadata_size, false);
|
context.GetBufferCache().ReadMemory(dcc_address, metadata_size, false);
|
||||||
std::vector<uint8_t> bytes(metadata_size);
|
std::vector<uint8_t> bytes(metadata_size);
|
||||||
|
|||||||
Reference in new issue
Block a user