From 12f8a0c48815e01a06bc94a4496eabfde6f45b52 Mon Sep 17 00:00:00 2001 From: Robert Broglia Date: Sat, 13 Apr 2024 13:44:30 -0400 Subject: [PATCH] 1.5.81 release * Imagine: Rework RingBuffer indexing fixing freeSpace() check causing issues in Saturn.emu VDP2 code * Imagine: Add RingBufferRWFlags allowing blocking mode selection per read/write call * Imagine: Fix RingBuffer::reset() causing a crash in EmuAudio code due to the capacity not being reset after pointer reset * EmuFramework: Only send DocumentPickerEvent to top view when not showing emulation * Saturn.emu: Simplify VDP2 work queue and eliminate DrawCounter variable --- EmuFramework/metadata/conf.mk | 2 +- EmuFramework/src/EmuApp.cc | 2 +- Saturn.emu/src/ss/vdp2_render.cpp | 38 ++------- imagine/build.mk | 2 +- imagine/include/imagine/config/version.h | 2 +- .../imagine/util/container/RingBuffer.hh | 80 ++++++++++++------- imagine/include/imagine/vmem/memory.hh | 6 ++ 7 files changed, 68 insertions(+), 64 deletions(-) diff --git a/EmuFramework/metadata/conf.mk b/EmuFramework/metadata/conf.mk index 86a656c63..100cffa66 100644 --- a/EmuFramework/metadata/conf.mk +++ b/EmuFramework/metadata/conf.mk @@ -1,4 +1,4 @@ -metadata_version = 1.5.80 +metadata_version = 1.5.81 metadata_supportedMIMETypes = application/zip metadata_supportedFileExtensions = rar 7z android_metadata_versionCodeExtra = 16 diff --git a/EmuFramework/src/EmuApp.cc b/EmuFramework/src/EmuApp.cc index 986fc81ff..1774a3a5e 100644 --- a/EmuFramework/src/EmuApp.cc +++ b/EmuFramework/src/EmuApp.cc @@ -541,7 +541,7 @@ void EmuApp::mainInitCommon(IG::ApplicationInitParams initParams, IG::Applicatio [&](DocumentPickerEvent& e) { log.info("document picked with URI:{}", e.uri); - if(viewController().top().onDocumentPicked(e)) + if(!viewController().isShowingEmulation() && viewController().top().onDocumentPicked(e)) return; handleOpenFileCommand(e.uri); }, diff --git a/Saturn.emu/src/ss/vdp2_render.cpp b/Saturn.emu/src/ss/vdp2_render.cpp index c95069185..aacc0eb9c 100644 --- a/Saturn.emu/src/ss/vdp2_render.cpp +++ b/Saturn.emu/src/ss/vdp2_render.cpp @@ -3211,32 +3211,11 @@ struct WQ_Entry uint32 Arg32; }; -static IG::RingBuffer WQ; -static std::atomic_int_least32_t DrawCounter; - -template -static void atomicWait(const std::atomic &val, T oldVal) -{ - if(MDFN_UNLIKELY(val.load(std::memory_order_acquire) == oldVal)) - { - //fprintf(stderr, "waiting for change from:%d\n", oldVal); - val.wait(oldVal, std::memory_order_acquire); - } -} - -template -static void atomicWaitForValue(const std::atomic &val, T wantedVal) -{ - for(auto c = val.load(std::memory_order_acquire); c != wantedVal; c = val.load(std::memory_order_acquire)) - { - //fprintf(stderr, "waiting for value\n"); - val.wait(c, std::memory_order_acquire); - } -} +static IG::RingBuffer WQ; static INLINE void WWQ(uint16 command, uint32 arg32 = 0, uint16 arg16 = 0) { - WQ.push({command, arg16, arg32}); + WQ.push({command, arg16, arg32}, IG::RingBufferRWFlags{.blocking = true, .notifyOnBlock = true}); } static int RThreadEntry(void* data) @@ -3246,9 +3225,8 @@ static int RThreadEntry(void* data) while(MDFN_LIKELY(Running)) { - WQ_Entry entry = WQ.pop(); + WQ_Entry entry = WQ.pop(IG::RingBufferRWFlags{.blocking = true}); WQ_Entry* wqe = &entry; - WQ.notifyRead(); switch(wqe->Command) { @@ -3264,8 +3242,6 @@ static int RThreadEntry(void* data) //for(unsigned i = 0; i < 2; i++) DrawLine((uint16)wqe->Arg32, wqe->Arg32 >> 16, wqe->Arg16); // - DrawCounter.fetch_sub(1, std::memory_order_release); - DrawCounter.notify_all(); break; case COMMAND_RESET: @@ -3283,6 +3259,8 @@ static int RThreadEntry(void* data) // // // + + WQ.notifyRead(); } return 0; @@ -3302,7 +3280,7 @@ void VDP2REND_Init(const bool IsPAL, const uint64 affinity) UserLayerEnableMask = ~0U; Clock28M = false; // - DrawCounter.store(0, std::memory_order_release); + WQ.clear(); RThread = MThreading::Thread_Create(RThreadEntry, NULL, "MDFN VDP2 Render"); if(affinity) MThreading::Thread_SetAffinity(RThread, affinity); @@ -3401,7 +3379,8 @@ void VDP2REND_StartFrame(EmulateSpecStruct* espec_arg, const bool clock28m, cons void VDP2REND_EndFrame(void) { - atomicWaitForValue(DrawCounter, 0); + WQ.notifyWrite(); + WQ.waitForSize(0); if(NextOutLine < VisibleLines) { @@ -3443,7 +3422,6 @@ void VDP2REND_DrawLine(const int vdp2_line, const uint32 crt_line, const bool fi if(espec->InterlaceOn) out_line = (out_line << 1) | espec->InterlaceField; - auto wdcq = DrawCounter.fetch_add(1, std::memory_order_release); WWQ(COMMAND_DRAW_LINE, ((uint16)vdp2_line << 16) | out_line, field); // // diff --git a/imagine/build.mk b/imagine/build.mk index cdefa7ac1..9d8f2ef20 100644 --- a/imagine/build.mk +++ b/imagine/build.mk @@ -41,7 +41,7 @@ prefix ?= $(IMAGINE_SDK_PLATFORM_PATH) imaginePkgconfigTemplate := $(IMAGINE_PATH)/pkgconfig/imagine.pc pkgName := $(libName) pkgDescription := Game/Multimedia Engine -pkgVersion := 1.5.80 +pkgVersion := 1.5.81 LDLIBS := -l$(libName) $(LDLIBS) ifdef libNameExt pkgCFlags := -DIMAGINE_CONFIG_H=$(configFilename) diff --git a/imagine/include/imagine/config/version.h b/imagine/include/imagine/config/version.h index 4055e3fa0..a03126571 100755 --- a/imagine/include/imagine/config/version.h +++ b/imagine/include/imagine/config/version.h @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with Imagine. If not, see */ -#define IMAGINE_VERSION_BASE "1.5.80" +#define IMAGINE_VERSION_BASE "1.5.81" #ifdef NDEBUG #define IMAGINE_VERSION IMAGINE_VERSION_BASE diff --git a/imagine/include/imagine/util/container/RingBuffer.hh b/imagine/include/imagine/util/container/RingBuffer.hh index 95a4eb443..45064843d 100644 --- a/imagine/include/imagine/util/container/RingBuffer.hh +++ b/imagine/include/imagine/util/container/RingBuffer.hh @@ -36,6 +36,12 @@ struct RingBufferConf size_t fixedSize{}; }; +struct RingBufferRWFlags +{ + bool blocking:1{}; + bool notifyOnBlock:1{}; +}; + struct RingBufferIdxPair { size_t read{}, write{}; @@ -46,6 +52,7 @@ class RingBuffer { public: using IdxPair = RingBufferIdxPair; + using RWFlags = RingBufferRWFlags; static constexpr bool isFixedSize = conf.fixedSize; struct RWSpan : public std::span @@ -98,23 +105,30 @@ public: bool full() const { return size() == capacity(); } [[nodiscard]] - RWSpan beginRead(size_t s) + RWSpan beginRead(size_t s, RWFlags flags = {}) { IdxPair idxs{.read = readIdx.load(std::memory_order_relaxed), .write = writeIdx.load(std::memory_order_acquire)}; + if(flags.blocking && empty(idxs)) + { + if(flags.notifyOnBlock) + notifyWrite(); + writeIdx.wait(idxs.write, std::memory_order_acquire); + idxs.write = writeIdx.load(std::memory_order_acquire); + } s = std::min(s, size(idxs)); - std::span span{&buff[idxs.read], s}; + std::span span{&buff[wrapIdx(idxs.read)], s}; assertAddrRange(span); return {span, idxs}; } void endRead(RWSpan span) { - readIdx.store(wrapSize(span.idxs.read + span.size()), std::memory_order_release); + readIdx.store(span.idxs.read + span.size(), std::memory_order_release); } - size_t read(std::span buff) + size_t read(std::span buff, RWFlags flags = {}) { - auto span = beginRead(buff.size()); + auto span = beginRead(buff.size(), flags); copy_n(span.data(), span.size(), buff.data()); endRead(span); return span.size(); @@ -129,14 +143,12 @@ public: return std::optional{tmp}; } - T pop() + T pop(RWFlags flags = {}) { - IdxPair idxs = loadIdxs(); - if(empty(idxs)) - writeIdx.wait(idxs.write, std::memory_order_relaxed); T tmp; - read({&tmp, 1}); - return tmp; + if(read({&tmp, 1}, flags)) + return tmp; + return {}; } void notifyRead() @@ -145,39 +157,38 @@ public: } [[nodiscard]] - RWSpan beginWrite(size_t s) + RWSpan beginWrite(size_t s, RWFlags flags = {}) { IdxPair idxs{.read = readIdx.load(std::memory_order_acquire), .write = writeIdx.load(std::memory_order_relaxed)}; + if(flags.blocking && !freeSpace(idxs)) + { + if(flags.notifyOnBlock) + notifyRead(); + readIdx.wait(idxs.read, std::memory_order_acquire); + idxs.read = readIdx.load(std::memory_order_acquire); + } s = std::min(s, freeSpace(idxs)); - std::span span{&buff[idxs.write], s}; + std::span span{&buff[wrapIdx(idxs.write)], s}; assertAddrRange(span); return {span, idxs}; } void endWrite(RWSpan span) { - writeIdx.store(wrapSize(span.idxs.write + span.size()), std::memory_order_release); + writeIdx.store(span.idxs.write + span.size(), std::memory_order_release); } - size_t write(std::span buff) + size_t write(std::span buff, RWFlags flags = {}) { - auto span = beginWrite(buff.size()); + auto span = beginWrite(buff.size(), flags); copy_n(buff.data(), span.size(), span.data()); endWrite(span); return span.size(); } - bool tryPush(const T& val) + bool push(const T& val, RWFlags flags = {}) { - return write({&val, 1}); - } - - void push(const T& val) - { - IdxPair idxs = loadIdxs(); - if(!freeSpace(idxs)) - readIdx.wait(idxs.read, std::memory_order_relaxed); - write({&val, 1}); + return write({&val, 1}, flags); } void notifyWrite() @@ -192,7 +203,7 @@ public: return newCapacity; size_t oldSize = size(); auto newBuff = allocBuffer(newCapacity); - if(newCapacity > oldSize) // maintain buffer content if increasing size + if(oldSize && newCapacity > oldSize) // maintain buffer content if increasing size { copy_n(buff.get(), oldSize, newBuff.get()); } @@ -204,14 +215,18 @@ public: return newCapacity; } - void reset() requires(!isFixedSize) { buff.reset(); } + void reset() requires(!isFixedSize) + { + resetVPtr(buff); + clear(); + } void waitForSize(size_t s) { IdxPair idxs = loadIdxs(); while(size(idxs) != s) { - readIdx.wait(idxs.read, std::memory_order_relaxed); + readIdx.wait(idxs.read, std::memory_order_acquire); idxs = loadIdxs(); } } @@ -231,13 +246,18 @@ private: } size_t wrapSize(size_t s) const + { + return s & (capacity() | (capacity() - 1)); + } + + size_t wrapIdx(size_t s) const { return s & (capacity() - 1); } IdxPair loadIdxs() const { - return {.read = readIdx.load(std::memory_order_relaxed), .write = writeIdx.load(std::memory_order_relaxed)}; + return {.read = readIdx.load(std::memory_order_acquire), .write = writeIdx.load(std::memory_order_acquire)}; } size_t bufferCapacity() const requires(!isFixedSize) { return buff.get_deleter().size; } diff --git a/imagine/include/imagine/vmem/memory.hh b/imagine/include/imagine/vmem/memory.hh index 24201f1d5..a82c86727 100644 --- a/imagine/include/imagine/vmem/memory.hh +++ b/imagine/include/imagine/vmem/memory.hh @@ -107,4 +107,10 @@ inline UniqueVPtr makeUniqueMirroredVPtr(size_t size) return {buff.data(), VPtrDeleter{buff.size()}}; } +template +inline void resetVPtr(UniqueVPtr &ptr) +{ + ptr = {nullptr, VPtrDeleter{}}; +} + }