summaryrefslogtreecommitdiff
path: root/src/video_core/engines
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-11-26 18:52:15 -0300
committerGravatar ReinUsesLisp2020-02-14 17:33:13 -0300
commitaae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd (patch)
tree560202675a073aa8e3863b4e17874fed27db8a6d /src/video_core/engines
parentgl_rasterizer: Sort method declarations (diff)
downloadyuzu-aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd.tar.gz
yuzu-aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd.tar.xz
yuzu-aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd.zip
gl_query_cache: Implement host queries using a deferred cache
Instead of waiting immediately for executed commands, defer the query until the guest CPU reads it. This way we get closer to what the guest program is doing. To archive this we have to build a dependency queue, because host APIs (like OpenGL and Vulkan) use ranged queries instead of counters like NVN. Waiting for queries implicitly uses fences and this requires a command being queued, otherwise the driver will lock waiting until a timeout. To fix this when there are no commands queued, we explicitly call glFlush.
Diffstat (limited to 'src/video_core/engines')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp41
-rw-r--r--src/video_core/engines/maxwell_3d.h4
2 files changed, 27 insertions, 18 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index fe91ff6a0..9add2bc94 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -556,23 +556,13 @@ void Maxwell3D::ProcessQueryGet() {
556 // matches the current payload. 556 // matches the current payload.
557 UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE"); 557 UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE");
558 break; 558 break;
559 case Regs::QueryOperation::Counter: { 559 case Regs::QueryOperation::Counter:
560 u64 result; 560 if (const std::optional<u64> result = GetQueryResult()) {
561 switch (regs.query.query_get.select) { 561 // If the query returns an empty optional it means it's cached and deferred.
562 case Regs::QuerySelect::Zero: 562 // In this case we have a non-empty result, so we stamp it immediately.
563 result = 0; 563 StampQueryResult(*result, regs.query.query_get.short_query == 0);
564 break;
565 case Regs::QuerySelect::SamplesPassed:
566 result = rasterizer.Query(VideoCore::QueryType::SamplesPassed);
567 break;
568 default:
569 result = 1;
570 UNIMPLEMENTED_MSG("Unimplemented query select type {}",
571 static_cast<u32>(regs.query.query_get.select.Value()));
572 } 564 }
573 StampQueryResult(result, regs.query.query_get.short_query == 0);
574 break; 565 break;
575 }
576 case Regs::QueryOperation::Trap: 566 case Regs::QueryOperation::Trap:
577 UNIMPLEMENTED_MSG("Unimplemented query operation TRAP"); 567 UNIMPLEMENTED_MSG("Unimplemented query operation TRAP");
578 break; 568 break;
@@ -595,20 +585,20 @@ void Maxwell3D::ProcessQueryCondition() {
595 } 585 }
596 case Regs::ConditionMode::ResNonZero: { 586 case Regs::ConditionMode::ResNonZero: {
597 Regs::QueryCompare cmp; 587 Regs::QueryCompare cmp;
598 memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp)); 588 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
599 execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U; 589 execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
600 break; 590 break;
601 } 591 }
602 case Regs::ConditionMode::Equal: { 592 case Regs::ConditionMode::Equal: {
603 Regs::QueryCompare cmp; 593 Regs::QueryCompare cmp;
604 memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp)); 594 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
605 execute_on = 595 execute_on =
606 cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode; 596 cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode;
607 break; 597 break;
608 } 598 }
609 case Regs::ConditionMode::NotEqual: { 599 case Regs::ConditionMode::NotEqual: {
610 Regs::QueryCompare cmp; 600 Regs::QueryCompare cmp;
611 memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp)); 601 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
612 execute_on = 602 execute_on =
613 cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode; 603 cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
614 break; 604 break;
@@ -674,6 +664,21 @@ void Maxwell3D::DrawArrays() {
674 } 664 }
675} 665}
676 666
667std::optional<u64> Maxwell3D::GetQueryResult() {
668 switch (regs.query.query_get.select) {
669 case Regs::QuerySelect::Zero:
670 return 0;
671 case Regs::QuerySelect::SamplesPassed:
672 // Deferred.
673 rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed);
674 return {};
675 default:
676 UNIMPLEMENTED_MSG("Unimplemented query select type {}",
677 static_cast<u32>(regs.query.query_get.select.Value()));
678 return 1;
679 }
680}
681
677void Maxwell3D::ProcessCBBind(std::size_t stage_index) { 682void Maxwell3D::ProcessCBBind(std::size_t stage_index) {
678 // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. 683 // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage.
679 auto& shader = state.shader_stages[stage_index]; 684 auto& shader = state.shader_stages[stage_index];
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index d21f678ed..26939be3f 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <bitset> 8#include <bitset>
9#include <optional>
9#include <type_traits> 10#include <type_traits>
10#include <unordered_map> 11#include <unordered_map>
11#include <vector> 12#include <vector>
@@ -1462,6 +1463,9 @@ private:
1462 1463
1463 // Handles a instance drawcall from MME 1464 // Handles a instance drawcall from MME
1464 void StepInstance(MMEDrawMode expected_mode, u32 count); 1465 void StepInstance(MMEDrawMode expected_mode, u32 count);
1466
1467 /// Returns a query's value or an empty object if the value will be deferred through a cache.
1468 std::optional<u64> GetQueryResult();
1465}; 1469};
1466 1470
1467#define ASSERT_REG_POSITION(field_name, position) \ 1471#define ASSERT_REG_POSITION(field_name, position) \