diff options
| author | 2019-11-26 18:52:15 -0300 | |
|---|---|---|
| committer | 2020-02-14 17:33:13 -0300 | |
| commit | aae8c180cbbf91ba12f53c37e81a97d4b3cc4ccd (patch) | |
| tree | 560202675a073aa8e3863b4e17874fed27db8a6d /src/video_core/engines | |
| parent | gl_rasterizer: Sort method declarations (diff) | |
| download | yuzu-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.cpp | 41 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 4 |
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 | ||
| 667 | std::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 | |||
| 677 | void Maxwell3D::ProcessCBBind(std::size_t stage_index) { | 682 | void 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) \ |