mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-31 09:28:29 +00:00
graphics: report GET_LOD_STATS mip-statistics slots as unsampled
Co-authored-by: TheCruZ <thecruzwtf@gmail.com>
This commit is contained in:
1 parent
4919fdb6e6
commit
14837b0479
2 files changed
+49
-7
No files matched your search
@@ -1285,16 +1285,19 @@ KYTY_CP_OP_PARSER(CpOpGetLodStats) {
|
||||
EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0038e00);
|
||||
|
||||
const auto buffer_size = buffer[0];
|
||||
auto* dst = reinterpret_cast<void*>((buffer[1] & 0xffffffc0u) |
|
||||
auto* dst = reinterpret_cast<volatile uint32_t*>((buffer[1] & 0xffffffc0u) |
|
||||
(static_cast<uint64_t>(buffer[2]) << 32u));
|
||||
|
||||
if (dst != nullptr && buffer_size != 0) {
|
||||
memset(dst, 0, buffer_size);
|
||||
// Hack?
|
||||
if (buffer_size >= sizeof(uint32_t)) {
|
||||
auto* label = static_cast<uint32_t*>(dst);
|
||||
*label = 1;
|
||||
// Mip statistics are not collected: each of up to 256 2-dword slots after the 16-dword header
|
||||
// reports its id (dword 0 bits 24-31) and finest sampled mip 15 (dword 1 bits 24-27), i.e. no
|
||||
// samples. A non-zero dword 0 then marks the report complete.
|
||||
if (dst != nullptr && buffer_size >= 64) {
|
||||
const auto slots = std::min((buffer_size - 64) / 8, 256u);
|
||||
for (uint32_t slot = 0; slot < slots; slot++) {
|
||||
dst[16 + slot * 2] = slot << 24u;
|
||||
dst[16 + slot * 2 + 1] = 15u << 24u;
|
||||
}
|
||||
dst[0] = 1;
|
||||
}
|
||||
|
||||
return 4;
|
||||
|
||||
@@ -52915,6 +52915,43 @@ void CheckPm4WaitResume(RenderContext &renderer) {
|
||||
std::printf("[host] %-32s ok\n", "Pm4WaitResume");
|
||||
}
|
||||
|
||||
void CheckPm4LodStats(RenderContext &renderer) {
|
||||
constexpr const char *name = "Pm4LodStats";
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer, 0);
|
||||
|
||||
// A 16-dword header, 256 two-dword slots and a guard the CP must leave unwritten.
|
||||
constexpr uint32_t poison = 0xa5a5a5a5u;
|
||||
alignas(64) std::array<uint32_t, 16 + 256 * 2 + 4> report{};
|
||||
std::array<uint32_t, 5> packet{};
|
||||
const auto run = [&](uint32_t size) {
|
||||
report.fill(poison);
|
||||
report[0] = 0;
|
||||
CommandBufferLayout dcb{packet.data(), packet.data() + packet.size(), packet.data(),
|
||||
packet.data() + packet.size(), nullptr, nullptr, 0};
|
||||
Pm4Execution execution;
|
||||
return Gen5::AgcDcbGetLodStats(reinterpret_cast<Gen5::CommandBuffer *>(&dcb), 0,
|
||||
report.data(), size, 0, 0, 0, 0) == packet.data() &&
|
||||
processor.Process(execution, packet) == Pm4ProcessResult::Complete && report[0] != 0;
|
||||
};
|
||||
// Slots below the count report no samples (finest mip 15); everything after them is untouched.
|
||||
const auto empty_slots = [&](uint32_t slots) {
|
||||
for (uint32_t slot = 0; slot < slots; slot++) {
|
||||
if (report[16 + slot * 2] != slot << 24u || report[17 + slot * 2] != 15u << 24u) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return std::all_of(report.begin() + 16 + slots * 2, report.end(),
|
||||
[](uint32_t dw) { return dw == poison; });
|
||||
};
|
||||
|
||||
Require(name, "full report", run(64 + 256 * 8 + 16) && empty_slots(256),
|
||||
"report did not mark exactly 256 slots unsampled");
|
||||
Require(name, "partial report", run(64 + 2 * 8 + 4) && empty_slots(2),
|
||||
"report did not stop at the last whole slot in the buffer");
|
||||
std::printf("[host] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
void CheckPm4MemSemaphore(RenderContext &renderer) {
|
||||
constexpr const char *name = "Pm4MemSemaphore";
|
||||
Loader::SymbolDatabase symbols;
|
||||
@@ -54030,6 +54067,7 @@ int main(int argc, char **argv) {
|
||||
CheckPm4AcquireMemPackets(vulkan.RuntimeRenderer());
|
||||
CheckPm4WaitPackets(vulkan.RuntimeRenderer());
|
||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||
CheckPm4LodStats(vulkan.RuntimeRenderer());
|
||||
CheckPm4MemSemaphore(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
@@ -54341,6 +54379,7 @@ int main(int argc, char **argv) {
|
||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||
CheckPm4IndirectControlFlow(vulkan.RuntimeRenderer());
|
||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||
CheckPm4LodStats(vulkan.RuntimeRenderer());
|
||||
CheckPm4MemSemaphore(vulkan.RuntimeRenderer());
|
||||
CheckPm4RewindResume(vulkan.RuntimeRenderer());
|
||||
CheckEmbeddedFetchVertexOffset();
|
||||
|
||||
Reference in new issue
Block a user