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);
|
EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0038e00);
|
||||||
|
|
||||||
const auto buffer_size = buffer[0];
|
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));
|
(static_cast<uint64_t>(buffer[2]) << 32u));
|
||||||
|
|
||||||
if (dst != nullptr && buffer_size != 0) {
|
// Mip statistics are not collected: each of up to 256 2-dword slots after the 16-dword header
|
||||||
memset(dst, 0, buffer_size);
|
// reports its id (dword 0 bits 24-31) and finest sampled mip 15 (dword 1 bits 24-27), i.e. no
|
||||||
// Hack?
|
// samples. A non-zero dword 0 then marks the report complete.
|
||||||
if (buffer_size >= sizeof(uint32_t)) {
|
if (dst != nullptr && buffer_size >= 64) {
|
||||||
auto* label = static_cast<uint32_t*>(dst);
|
const auto slots = std::min((buffer_size - 64) / 8, 256u);
|
||||||
*label = 1;
|
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;
|
return 4;
|
||||||
|
|||||||
@@ -52915,6 +52915,43 @@ void CheckPm4WaitResume(RenderContext &renderer) {
|
|||||||
std::printf("[host] %-32s ok\n", "Pm4WaitResume");
|
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) {
|
void CheckPm4MemSemaphore(RenderContext &renderer) {
|
||||||
constexpr const char *name = "Pm4MemSemaphore";
|
constexpr const char *name = "Pm4MemSemaphore";
|
||||||
Loader::SymbolDatabase symbols;
|
Loader::SymbolDatabase symbols;
|
||||||
@@ -54030,6 +54067,7 @@ int main(int argc, char **argv) {
|
|||||||
CheckPm4AcquireMemPackets(vulkan.RuntimeRenderer());
|
CheckPm4AcquireMemPackets(vulkan.RuntimeRenderer());
|
||||||
CheckPm4WaitPackets(vulkan.RuntimeRenderer());
|
CheckPm4WaitPackets(vulkan.RuntimeRenderer());
|
||||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||||
|
CheckPm4LodStats(vulkan.RuntimeRenderer());
|
||||||
CheckPm4MemSemaphore(vulkan.RuntimeRenderer());
|
CheckPm4MemSemaphore(vulkan.RuntimeRenderer());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -54341,6 +54379,7 @@ int main(int argc, char **argv) {
|
|||||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||||
CheckPm4IndirectControlFlow(vulkan.RuntimeRenderer());
|
CheckPm4IndirectControlFlow(vulkan.RuntimeRenderer());
|
||||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||||
|
CheckPm4LodStats(vulkan.RuntimeRenderer());
|
||||||
CheckPm4MemSemaphore(vulkan.RuntimeRenderer());
|
CheckPm4MemSemaphore(vulkan.RuntimeRenderer());
|
||||||
CheckPm4RewindResume(vulkan.RuntimeRenderer());
|
CheckPm4RewindResume(vulkan.RuntimeRenderer());
|
||||||
CheckEmbeddedFetchVertexOffset();
|
CheckEmbeddedFetchVertexOffset();
|
||||||
|
|||||||
Reference in new issue
Block a user