mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-11 10:27:57 -05:00
Query Cachge: Fully rework Vulkan's query cache
This commit is contained in:
@ -20,8 +20,6 @@
|
||||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
using VideoCore::QueryType;
|
||||
|
||||
/// First register id that is actually a Macro call.
|
||||
constexpr u32 MacroRegistersStart = 0xE00;
|
||||
|
||||
@ -500,27 +498,21 @@ void Maxwell3D::StampQueryResult(u64 payload, bool long_query) {
|
||||
}
|
||||
|
||||
void Maxwell3D::ProcessQueryGet() {
|
||||
VideoCommon::QueryPropertiesFlags flags{};
|
||||
if (regs.report_semaphore.query.short_query == 0) {
|
||||
flags |= VideoCommon::QueryPropertiesFlags::HasTimeout;
|
||||
}
|
||||
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
|
||||
const VideoCommon::QueryType query_type =
|
||||
static_cast<VideoCommon::QueryType>(regs.report_semaphore.query.report.Value());
|
||||
const u32 payload = regs.report_semaphore.payload;
|
||||
const u32 subreport = regs.report_semaphore.query.sub_report;
|
||||
switch (regs.report_semaphore.query.operation) {
|
||||
case Regs::ReportSemaphore::Operation::Release:
|
||||
if (regs.report_semaphore.query.short_query != 0) {
|
||||
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
|
||||
const u32 payload = regs.report_semaphore.payload;
|
||||
std::function<void()> operation([this, sequence_address, payload] {
|
||||
memory_manager.Write<u32>(sequence_address, payload);
|
||||
});
|
||||
rasterizer->SignalFence(std::move(operation));
|
||||
} else {
|
||||
struct LongQueryResult {
|
||||
u64_le value;
|
||||
u64_le timestamp;
|
||||
};
|
||||
const GPUVAddr sequence_address{regs.report_semaphore.Address()};
|
||||
const u32 payload = regs.report_semaphore.payload;
|
||||
[this, sequence_address, payload] {
|
||||
memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
|
||||
memory_manager.Write<u64>(sequence_address, payload);
|
||||
}();
|
||||
flags |= VideoCommon::QueryPropertiesFlags::IsAFence;
|
||||
}
|
||||
rasterizer->Query(sequence_address, query_type, flags, payload, subreport);
|
||||
break;
|
||||
case Regs::ReportSemaphore::Operation::Acquire:
|
||||
// TODO(Blinkhawk): Under this operation, the GPU waits for the CPU to write a value that
|
||||
@ -528,11 +520,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE");
|
||||
break;
|
||||
case Regs::ReportSemaphore::Operation::ReportOnly:
|
||||
if (const std::optional<u64> result = GetQueryResult()) {
|
||||
// If the query returns an empty optional it means it's cached and deferred.
|
||||
// In this case we have a non-empty result, so we stamp it immediately.
|
||||
StampQueryResult(*result, regs.report_semaphore.query.short_query == 0);
|
||||
}
|
||||
rasterizer->Query(sequence_address, query_type, flags, payload, subreport);
|
||||
break;
|
||||
case Regs::ReportSemaphore::Operation::Trap:
|
||||
UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
|
||||
@ -544,6 +532,10 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
}
|
||||
|
||||
void Maxwell3D::ProcessQueryCondition() {
|
||||
if (rasterizer->AccelerateConditionalRendering()) {
|
||||
execute_on = true;
|
||||
return;
|
||||
}
|
||||
const GPUVAddr condition_address{regs.render_enable.Address()};
|
||||
switch (regs.render_enable_override) {
|
||||
case Regs::RenderEnable::Override::AlwaysRender:
|
||||
@ -553,10 +545,6 @@ void Maxwell3D::ProcessQueryCondition() {
|
||||
execute_on = false;
|
||||
break;
|
||||
case Regs::RenderEnable::Override::UseRenderEnable: {
|
||||
if (rasterizer->AccelerateConditionalRendering()) {
|
||||
execute_on = true;
|
||||
return;
|
||||
}
|
||||
switch (regs.render_enable.mode) {
|
||||
case Regs::RenderEnable::Mode::True: {
|
||||
execute_on = true;
|
||||
@ -606,7 +594,13 @@ void Maxwell3D::ProcessCounterReset() {
|
||||
#endif
|
||||
switch (regs.clear_report_value) {
|
||||
case Regs::ClearReport::ZPassPixelCount:
|
||||
rasterizer->ResetCounter(QueryType::SamplesPassed);
|
||||
rasterizer->ResetCounter(VideoCommon::QueryType::ZPassPixelCount64);
|
||||
break;
|
||||
case Regs::ClearReport::PrimitivesGenerated:
|
||||
rasterizer->ResetCounter(VideoCommon::QueryType::StreamingByteCount);
|
||||
break;
|
||||
case Regs::ClearReport::VtgPrimitivesOut:
|
||||
rasterizer->ResetCounter(VideoCommon::QueryType::StreamingByteCount);
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", regs.clear_report_value);
|
||||
@ -620,28 +614,6 @@ void Maxwell3D::ProcessSyncPoint() {
|
||||
rasterizer->SignalSyncPoint(sync_point);
|
||||
}
|
||||
|
||||
std::optional<u64> Maxwell3D::GetQueryResult() {
|
||||
switch (regs.report_semaphore.query.report) {
|
||||
case Regs::ReportSemaphore::Report::Payload:
|
||||
return regs.report_semaphore.payload;
|
||||
case Regs::ReportSemaphore::Report::ZPassPixelCount64:
|
||||
#if ANDROID
|
||||
if (!Settings::IsGPULevelHigh()) {
|
||||
// This is problematic on Android, disable on GPU Normal.
|
||||
return 120;
|
||||
}
|
||||
#endif
|
||||
// Deferred.
|
||||
rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed,
|
||||
system.GPU().GetTicks());
|
||||
return std::nullopt;
|
||||
default:
|
||||
LOG_DEBUG(HW_GPU, "Unimplemented query report type {}",
|
||||
regs.report_semaphore.query.report.Value());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Maxwell3D::ProcessCBBind(size_t stage_index) {
|
||||
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader
|
||||
// stage.
|
||||
|
@ -3182,9 +3182,6 @@ private:
|
||||
/// Handles writes to syncing register.
|
||||
void ProcessSyncPoint();
|
||||
|
||||
/// Returns a query's value or an empty object if the value will be deferred through a cache.
|
||||
std::optional<u64> GetQueryResult();
|
||||
|
||||
void RefreshParametersImpl();
|
||||
|
||||
bool IsMethodExecutable(u32 method);
|
||||
|
@ -362,21 +362,17 @@ void MaxwellDMA::ReleaseSemaphore() {
|
||||
const auto type = regs.launch_dma.semaphore_type;
|
||||
const GPUVAddr address = regs.semaphore.address;
|
||||
const u32 payload = regs.semaphore.payload;
|
||||
VideoCommon::QueryPropertiesFlags flags{VideoCommon::QueryPropertiesFlags::IsAFence};
|
||||
switch (type) {
|
||||
case LaunchDMA::SemaphoreType::NONE:
|
||||
break;
|
||||
case LaunchDMA::SemaphoreType::RELEASE_ONE_WORD_SEMAPHORE: {
|
||||
std::function<void()> operation(
|
||||
[this, address, payload] { memory_manager.Write<u32>(address, payload); });
|
||||
rasterizer->SignalFence(std::move(operation));
|
||||
rasterizer->Query(address, VideoCommon::QueryType::Payload, flags, payload, 0);
|
||||
break;
|
||||
}
|
||||
case LaunchDMA::SemaphoreType::RELEASE_FOUR_WORD_SEMAPHORE: {
|
||||
std::function<void()> operation([this, address, payload] {
|
||||
memory_manager.Write<u64>(address + sizeof(u64), system.GPU().GetTicks());
|
||||
memory_manager.Write<u64>(address, payload);
|
||||
});
|
||||
rasterizer->SignalFence(std::move(operation));
|
||||
rasterizer->Query(address, VideoCommon::QueryType::Payload,
|
||||
flags | VideoCommon::QueryPropertiesFlags::HasTimeout, payload, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -82,10 +82,7 @@ void Puller::ProcessSemaphoreTriggerMethod() {
|
||||
if (op == GpuSemaphoreOperation::WriteLong) {
|
||||
const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()};
|
||||
const u32 payload = regs.semaphore_sequence;
|
||||
[this, sequence_address, payload] {
|
||||
memory_manager.Write<u64>(sequence_address + sizeof(u64), gpu.GetTicks());
|
||||
memory_manager.Write<u64>(sequence_address, payload);
|
||||
}();
|
||||
rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, VideoCommon::QueryPropertiesFlags::HasTimeout, payload, 0);
|
||||
} else {
|
||||
do {
|
||||
const u32 word{memory_manager.Read<u32>(regs.semaphore_address.SemaphoreAddress())};
|
||||
@ -120,10 +117,7 @@ void Puller::ProcessSemaphoreTriggerMethod() {
|
||||
void Puller::ProcessSemaphoreRelease() {
|
||||
const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()};
|
||||
const u32 payload = regs.semaphore_release;
|
||||
std::function<void()> operation([this, sequence_address, payload] {
|
||||
memory_manager.Write<u32>(sequence_address, payload);
|
||||
});
|
||||
rasterizer->SignalFence(std::move(operation));
|
||||
rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, VideoCommon::QueryPropertiesFlags::IsAFence, payload, 0);
|
||||
}
|
||||
|
||||
void Puller::ProcessSemaphoreAcquire() {
|
||||
@ -132,7 +126,6 @@ void Puller::ProcessSemaphoreAcquire() {
|
||||
while (word != value) {
|
||||
regs.acquire_active = true;
|
||||
regs.acquire_value = value;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
rasterizer->ReleaseFences();
|
||||
word = memory_manager.Read<u32>(regs.semaphore_address.SemaphoreAddress());
|
||||
// TODO(kemathe73) figure out how to do the acquire_timeout
|
||||
|
Reference in New Issue
Block a user