diff --git a/README.md b/README.md index dd6590bbd..9b87c976b 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2616. +This is the source code for early-access 2617. ## Legal Notice diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h index b94d73c7a..b963e7b99 100755 --- a/src/common/atomic_ops.h +++ b/src/common/atomic_ops.h @@ -46,6 +46,13 @@ namespace Common { reinterpret_cast<__int64*>(expected.data())) != 0; } +[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) { + u128 result{}; + _InterlockedCompareExchange128(reinterpret_cast(pointer), result[1], + result[0], reinterpret_cast<__int64*>(result.data())); + return result; +} + #else [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) { @@ -72,6 +79,16 @@ namespace Common { return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a); } +[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) { + unsigned __int128 zeros_a = 0; + unsigned __int128 result_a = + __sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a); + + u128 result; + std::memcpy(result.data(), &result_a, sizeof(u128)); + return result; +} + #endif } // namespace Common diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 347e41efc..2a2664e5d 100755 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -56,7 +56,7 @@ u64 NativeClock::GetRTSC() { TimePoint new_time_point{}; TimePoint current_time_point{}; do { - current_time_point.pack = time_point.pack; + current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); _mm_mfence(); const u64 current_measure = __rdtsc(); u64 diff = current_measure - current_time_point.inner.last_measure; @@ -76,7 +76,7 @@ void NativeClock::Pause(bool is_paused) { TimePoint current_time_point{}; TimePoint new_time_point{}; do { - current_time_point.pack = time_point.pack; + current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); new_time_point.pack = current_time_point.pack; _mm_mfence(); new_time_point.inner.last_measure = __rdtsc(); diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 9547f277a..78d391cd9 100755 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -90,6 +90,10 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) { return; } if (!Settings::IsGPULevelExtreme()) { + // Push a command and block here before proceeding, addresses a synchronization + // bug causing an SVC break in Kirby and the Forgotten Land + // GPUTickCommand is essentially a no-op if we don't RequestFlush() + PushCommand(GPUTickCommand(), true); return; } auto& gpu = system.GPU(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4d632d211..e6f9ece8b 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -15,8 +15,9 @@ #include "common/logging/log.h" #include "common/math_util.h" #include "common/microprofile.h" +#include "common/scope_exit.h" #include "common/settings.h" -#include "core/memory.h" + #include "video_core/engines/kepler_compute.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/memory_manager.h" @@ -210,6 +211,7 @@ void RasterizerOpenGL::Clear() { void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { MICROPROFILE_SCOPE(OpenGL_Drawing); + SCOPE_EXIT({ gpu.TickWork(); }); query_cache.UpdateCounters(); GraphicsPipeline* const pipeline{shader_cache.CurrentGraphicsPipeline()}; @@ -265,8 +267,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { ++num_queued_commands; has_written_global_memory |= pipeline->WritesGlobalMemory(); - - gpu.TickWork(); } void RasterizerOpenGL::DispatchCompute() {