mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 05:16:56 +01:00
graphics: count occlusion queries on the host GPU behind --occlusion-queries
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_OCCLUSIONQUERIES_H_
|
||||
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_OCCLUSIONQUERIES_H_
|
||||
|
||||
#include "common/common.h"
|
||||
#include "graphics/host_gpu/vulkanCommon.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
class CommandScheduler;
|
||||
struct GraphicContext;
|
||||
|
||||
// The guest's query results (16-byte aligned): a begin/end pair of running z-pass counters per DB,
|
||||
// 16 bytes apart; bit 63 marks a written counter. A query's samples are the sum of end - begin.
|
||||
constexpr uint32_t OCCLUSION_QUERY_DBS = 16;
|
||||
constexpr uint64_t OCCLUSION_QUERY_READY = 1ull << 63u;
|
||||
|
||||
// A dump of the running count, all of it in DB 0. A begin also clears its end counters.
|
||||
inline void WriteZPassCounters(volatile uint64_t* results, uint64_t samples, bool begin) {
|
||||
for (uint32_t db = 0; db < OCCLUSION_QUERY_DBS; db++) {
|
||||
results[db * 2] = OCCLUSION_QUERY_READY | (db == 0 ? samples : 0);
|
||||
if (begin) {
|
||||
results[db * 2 + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The guest's z-pass counters from host occlusion queries: a draw counts its samples while a guest
|
||||
// query is open, and the dumps' counters are written before the guest can see the GPU ran them.
|
||||
class OcclusionQueries {
|
||||
public:
|
||||
OcclusionQueries(GraphicContext& graphics, CommandScheduler& scheduler);
|
||||
~OcclusionQueries();
|
||||
KYTY_CLASS_NO_COPY(OcclusionQueries);
|
||||
|
||||
[[nodiscard]] bool Enabled() const { return m_pool != nullptr; }
|
||||
|
||||
// In the draw's rendering: the query that counts its samples, or -1.
|
||||
[[nodiscard]] int32_t Begin(vk::CommandBuffer command) {
|
||||
return m_open == 0 ? -1 : BeginQuery(command);
|
||||
}
|
||||
void End(vk::CommandBuffer command, int32_t query) const {
|
||||
if (query >= 0) {
|
||||
command.endQuery(m_pool, static_cast<uint32_t>(query));
|
||||
}
|
||||
}
|
||||
|
||||
// A PIXEL_PIPE_STAT_DUMP to address, after the draws recorded so far.
|
||||
void Dump(uint64_t address);
|
||||
// Waits for the GPU to run the dumps and writes their counters.
|
||||
void Publish() {
|
||||
if (!m_dumps.empty()) {
|
||||
PublishDumps();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct PendingDump {
|
||||
uint64_t address;
|
||||
uint64_t tick;
|
||||
uint64_t queries;
|
||||
uint64_t uncounted;
|
||||
};
|
||||
|
||||
int32_t BeginQuery(vk::CommandBuffer command);
|
||||
void PublishDumps();
|
||||
|
||||
CommandScheduler& m_scheduler;
|
||||
vk::Device m_device;
|
||||
vk::QueryPool m_pool;
|
||||
vk::QueryControlFlags m_control;
|
||||
std::vector<PendingDump> m_dumps;
|
||||
std::vector<uint64_t> m_results;
|
||||
uint32_t m_open = 0;
|
||||
uint64_t m_begun = 0;
|
||||
uint64_t m_read = 0;
|
||||
uint64_t m_samples = 0;
|
||||
uint64_t m_uncounted = 0;
|
||||
};
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_OCCLUSIONQUERIES_H_
|
||||
Reference in New Issue
Block a user