diff options
| author | Jonas <104419015+jojo-chaechae@users.noreply.github.com> | 2026-11-03 04:18:21 +0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-11-03 04:18:21 +0600 |
| commit | 155bf34fc297b6b8e4c281ecf7ea5d9ce3140762 (patch) | |
| tree | ef69b034a8bd3bfc710c182c52e34e0acd4b3735 /src/video_core/engines | |
| parent | 05259375e0fb436c78882f8d9b95f9e2ce69af13 (diff) | |
| parent | 9f4f01f76e8556941c0c0c3f57edc1d600ed23ea (diff) | |
Merge pull request #337 from Sssnowyyy/nx2-review-fixes
nx2: fix pokopia regressions, textures that handle shader computes, and more
Diffstat (limited to 'src/video_core/engines')
| -rw-r--r-- | src/video_core/engines/draw_manager.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 5 | ||||
| -rw-r--r-- | src/video_core/engines/puller.cpp | 2 |
4 files changed, 22 insertions, 5 deletions
diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp index 038e5a2e69..974a9a6e9a 100644 --- a/src/video_core/engines/draw_manager.cpp +++ b/src/video_core/engines/draw_manager.cpp @@ -72,11 +72,19 @@ void Maxwell3D::DrawManager::Clear(Maxwell3D& maxwell3d, u32 layer_count) { } } -void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d) { +void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d, bool loop_continues) { if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) { + if (!loop_continues) { + draw_state.drawn_instances = 0; + } return; } - DrawEnd(maxwell3d, draw_state.instance_count + 1, true); + // The first draw of a batch also covers the loop's first instance; a batch that continues a + // loop split by a register write draws only the instances after the ones already drawn. + const bool continued = draw_state.drawn_instances != 0; + DrawEnd(maxwell3d, draw_state.instance_count + (continued ? 0 : 1), true); + draw_state.drawn_instances = + loop_continues ? draw_state.drawn_instances + draw_state.instance_count : 0; draw_state.instance_count = 0; } @@ -121,6 +129,7 @@ void Maxwell3D::DrawManager::DrawArrayInstanced(Maxwell3D& maxwell3d, Maxwell3D: draw_state.vertex_buffer.count = vertex_count; if (!subsequent) { draw_state.instance_count = 1; + draw_state.drawn_instances = 0; } draw_state.base_instance = draw_state.instance_count - 1; draw_state.draw_mode = DrawMode::Instance; @@ -220,6 +229,9 @@ void Maxwell3D::DrawManager::DrawEnd(Maxwell3D& maxwell3d, u32 instance_count, b [[fallthrough]]; case DrawMode::General: draw_state.base_instance = maxwell3d.regs.global_base_instance_index; + if (draw_state.draw_mode == DrawMode::Instance && draw_state.drawn_instances != 0) { + draw_state.base_instance += draw_state.drawn_instances + 1; + } draw_state.base_index = maxwell3d.regs.global_base_vertex_index; if (draw_state.draw_indexed) { draw_state.index_buffer = maxwell3d.regs.index_buffer; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 9731f54584..4ef7d42979 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -342,7 +342,7 @@ void Maxwell3D::ProcessDirtyRegisters(u32 method, u32 argument) { // the state they were begun with: NVN's draw macros reset the base instance (and its copy in // c[0][0x644]) right after the loop, before the macro returns. if (draw_manager.HasDeferredDraw() && !DrawManager::IsInstanceLoopMethod(method)) [[unlikely]] { - draw_manager.DrawDeferred(*this); + draw_manager.DrawDeferred(*this, true); } regs.reg_array[method] = argument; for (auto const& table : dirty.tables) @@ -537,7 +537,7 @@ void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* bas } // As in ProcessDirtyRegisters: the paths below write without it. if (draw_manager.HasDeferredDraw() && !DrawManager::IsInstanceLoopMethod(method)) [[unlikely]] { - draw_manager.DrawDeferred(*this); + draw_manager.DrawDeferred(*this, true); } switch (method) { case MAXWELL3D_REG_INDEX(const_buffer.buffer): diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index af0e37978e..c5d1eb3230 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -3069,6 +3069,8 @@ public: Maxwell3D::Regs::IndexBuffer index_buffer; u32 base_instance{}; u32 instance_count{}; + /// Deferred instances already drawn by flushes in the middle of the current loop. + u32 drawn_instances{}; std::vector<u8> inline_index_draw_indexes; }; struct DrawTextureState { @@ -3095,7 +3097,8 @@ public: }; void ProcessMethodCall(Maxwell3D& maxwell3d, u32 method, u32 argument); void Clear(Maxwell3D& maxwell3d, u32 layer_count); - void DrawDeferred(Maxwell3D& maxwell3d); + /// Draws the waiting instances. loop_continues is set when the loop goes on afterwards. + void DrawDeferred(Maxwell3D& maxwell3d, bool loop_continues = false); /// Instances after the first wait to be drawn together (DrawDeferred). [[nodiscard]] bool HasDeferredDraw() const noexcept { return draw_state.draw_mode == DrawMode::Instance && draw_state.instance_count != 0; diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index 0bb1809aa3..37ac3ec851 100644 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp @@ -116,6 +116,7 @@ bool Puller::ResumeAcquire(DmaPusher& dma_pusher) { return false; } pending_acquire.reset(); + dma_pusher.suspensions.fetch_add(1, std::memory_order_release); Nx2SemaphoreWaiters::Get().Remove(this); return true; } @@ -257,6 +258,7 @@ void Puller::ProcessSemaphoreTriggerMethod(DmaPusher& dma_pusher) { dma_pusher.rasterizer->ReleaseFences(); if (!waiters.Latched(this) && !acquire.Matches(ReadSemaphoreWord(dma_pusher, acquire.address))) { pending_acquire = acquire; + dma_pusher.suspensions.fetch_add(1, std::memory_order_release); VideoCommon::Nx2Profile::Add(VideoCommon::Nx2Profile::Counter::AcquireWaits, 1); } else { waiters.Remove(this); |
