From 25072b99c70f5ea46c8eb3be1edad170388ba47e Mon Sep 17 00:00:00 2001 From: gabest11 Date: Tue, 27 Dec 2011 09:15:35 +0000 Subject: [PATCH] GSdx: a few minor changes, please check if I wrapped the new pthread things correctly git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5019 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSLocalMemory.cpp | 2 - plugins/GSdx/GSLocalMemory.h | 2 - plugins/GSdx/GSRasterizer.cpp | 3 + plugins/GSdx/GSRasterizer.h | 7 + plugins/GSdx/GSRendererSW.cpp | 74 ++++++----- plugins/GSdx/GSRendererSW.h | 66 +++++++--- plugins/GSdx/GSState.cpp | 8 +- plugins/GSdx/GSThread.cpp | 38 ++++++ plugins/GSdx/GSThread.h | 226 +++++++++++++-------------------- plugins/GSdx/stdafx.h | 75 +++++++++-- 10 files changed, 298 insertions(+), 203 deletions(-) diff --git a/plugins/GSdx/GSLocalMemory.cpp b/plugins/GSdx/GSLocalMemory.cpp index cc5ebf095e..51140a3315 100644 --- a/plugins/GSdx/GSLocalMemory.cpp +++ b/plugins/GSdx/GSLocalMemory.cpp @@ -2002,8 +2002,6 @@ GSOffset::~GSOffset() list* GSOffset::GetPages(const GSVector4i& rect, GSVector4i* bbox) { - GSAutoLock lock(&m_lock); - GSVector2i bs = (bp & 31) == 0 ? GSLocalMemory::m_psm[psm].pgs : GSLocalMemory::m_psm[psm].bs; GSVector4i r = rect.ralign(bs); diff --git a/plugins/GSdx/GSLocalMemory.h b/plugins/GSdx/GSLocalMemory.h index 36605c12e6..d8fa7e7dc1 100644 --- a/plugins/GSdx/GSLocalMemory.h +++ b/plugins/GSdx/GSLocalMemory.h @@ -30,8 +30,6 @@ class GSOffset : public GSAlignedClass<32> { - GSCritSec m_lock; // GetPages could be called from multiple threads - hash_map*> m_cache; public: diff --git a/plugins/GSdx/GSRasterizer.cpp b/plugins/GSdx/GSRasterizer.cpp index bb68887d9c..00b25b02c9 100644 --- a/plugins/GSdx/GSRasterizer.cpp +++ b/plugins/GSdx/GSRasterizer.cpp @@ -163,6 +163,9 @@ void GSRasterizer::Draw(shared_ptr data) uint64 ticks = __rdtsc() - start; + _InterlockedExchangeAdd(&data->ticks, ticks); + _InterlockedExchangeAdd(&data->pixels, m_pixels); + m_ds->EndDraw(data->frame, ticks, m_pixels); } diff --git a/plugins/GSdx/GSRasterizer.h b/plugins/GSdx/GSRasterizer.h index e90b499ec6..ab81b38039 100644 --- a/plugins/GSdx/GSRasterizer.h +++ b/plugins/GSdx/GSRasterizer.h @@ -41,6 +41,11 @@ public: uint64 frame; void* param; + // drawing stats + + volatile long ticks; + volatile long pixels; + GSRasterizerData() : scissor(GSVector4i::zero()) , bbox(GSVector4i::zero()) @@ -51,6 +56,8 @@ public: , syncpoint(false) , frame(0) , param(NULL) + , ticks(0) + , pixels(0) { } diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index ce579526fb..86c72c5452 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -166,7 +166,19 @@ void GSRendererSW::Draw() { if(m_dump) m_dump.Object(m_vertices, m_count, m_vt.m_primclass); - shared_ptr data(new GSRasterizerData2(this)); + GSVector4i scissor = GSVector4i(m_context->scissor.in); + GSVector4i bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil())); + + scissor.z = std::min(scissor.z, (int)m_context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour + + GSVector4i r = bbox.rintersect(scissor); + + list* fb_pages = m_context->offset.fb->GetPages(r); + list* zb_pages = m_context->offset.zb->GetPages(r); + + GSRasterizerData2* data2 = new GSRasterizerData2(this, fb_pages, zb_pages); + + shared_ptr data(data2); GSScanlineGlobalData* gd = (GSScanlineGlobalData*)data->param; @@ -175,9 +187,8 @@ void GSRendererSW::Draw() return; } - data->scissor = GSVector4i(m_context->scissor.in); - data->scissor.z = std::min(data->scissor.z, (int)m_context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour - data->bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil())); + data->scissor = scissor; + data->bbox = bbox; data->primclass = m_vt.m_primclass; data->vertices = (GSVertexSW*)_aligned_malloc(sizeof(GSVertexSW) * m_count, 16); // TODO: detach m_vertices and reallocate later? memcpy(data->vertices, m_vertices, sizeof(GSVertexSW) * m_count); // TODO: m_vt.Update fetches all the vertices already, could also store them here @@ -185,11 +196,6 @@ void GSRendererSW::Draw() data->solidrect = gd->sel.IsSolidRect(); data->frame = m_perfmon.GetFrame(); - GSVector4i r = data->bbox.rintersect(data->scissor); - - list* fb_pages = m_context->offset.fb->GetPages(r); - list* zb_pages = m_context->offset.zb->GetPages(r); - // if(gd->sel.fwrite) @@ -202,7 +208,7 @@ void GSRendererSW::Draw() m_tc->InvalidatePages(zb_pages, m_context->offset.zb->psm); } - // + // set data->syncpoint if(m_fzb != m_context->offset.fzb) { @@ -220,7 +226,12 @@ void GSRendererSW::Draw() { for(list::iterator i = fb_pages->begin(); i != fb_pages->end(); i++) { - if(m_fzb_pages[*i] & 0xffff0000) data->syncpoint = true; // already used as a z-buffer + if(m_fzb_pages[*i] & 0xffff0000) // already used as a z-buffer + { + data->syncpoint = true; + + break; + } } } } @@ -231,20 +242,21 @@ void GSRendererSW::Draw() { for(list::iterator i = zb_pages->begin(); i != zb_pages->end(); i++) { - if(m_fzb_pages[*i] & 0x0000ffff) data->syncpoint = true; // already used as a frame buffer + if(m_fzb_pages[*i] & 0x0000ffff) // already used as a frame buffer + { + data->syncpoint = true; + + break; + } } } } - if(gd->sel.fwrite) - { - UseTargetPages(fb_pages, 0); - } + // - if(gd->sel.zwrite) - { - UseTargetPages(zb_pages, 1); - } + data2->UseTargetPages(); + + // if(s_dump) { @@ -304,8 +316,17 @@ void GSRendererSW::Draw() m_rl->Queue(data); } - // TODO: m_perfmon.Put(GSPerfMon::Prim, stats.prims); - // TODO: m_perfmon.Put(GSPerfMon::Fillrate, stats.pixels); + int prims = 0; + + switch(data->primclass) + { + case GS_POINT_CLASS: prims = data->count; break; + case GS_LINE_CLASS: prims = data->count / 2; break; + case GS_TRIANGLE_CLASS: prims = data->count / 3; break; + case GS_SPRITE_CLASS: prims = data->count / 2; break; + } + + m_perfmon.Put(GSPerfMon::Prim, prims); /* if(0)//stats.ticks > 5000000) @@ -329,15 +350,6 @@ void GSRendererSW::Sync(int reason) // NOTE: m_fzb_pages is refcounted, zeroing is done automatically - #ifdef _DEBUG - - for(size_t i = 0; i < countof(m_fzb_pages); i++) - { - ASSERT(m_fzb_pages[i] == 0); - } - - #endif - memset(m_tex_pages, 0, sizeof(m_tex_pages)); } diff --git a/plugins/GSdx/GSRendererSW.h b/plugins/GSdx/GSRendererSW.h index af249121bd..abb2267b21 100644 --- a/plugins/GSdx/GSRendererSW.h +++ b/plugins/GSdx/GSRendererSW.h @@ -30,14 +30,16 @@ class GSRendererSW : public GSRendererT class GSRasterizerData2 : public GSRasterizerData { GSRendererSW* m_parent; - GSOffset* m_fb; - GSOffset* m_zb; + const list* m_fb_pages; + const list* m_zb_pages; + bool m_using_pages; public: - GSRasterizerData2(GSRendererSW* parent) + GSRasterizerData2(GSRendererSW* parent, const list* fb_pages, const list* zb_pages) : m_parent(parent) - , m_fb(parent->m_context->offset.fb) - , m_zb(parent->m_context->offset.zb) + , m_fb_pages(fb_pages) + , m_zb_pages(zb_pages) + , m_using_pages(false) { GSScanlineGlobalData* gd = (GSScanlineGlobalData*)_aligned_malloc(sizeof(GSScanlineGlobalData), 32); @@ -51,24 +53,54 @@ class GSRendererSW : public GSRendererT virtual ~GSRasterizerData2() { + ReleaseTargetPages(); + GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param; - - GSVector4i r = bbox.rintersect(scissor); - - if(gd->sel.fwrite) - { - m_parent->ReleaseTargetPages(m_fb->GetPages(r), 0); - } - - if(gd->sel.zwrite) - { - m_parent->ReleaseTargetPages(m_zb->GetPages(r), 1); - } if(gd->clut) _aligned_free(gd->clut); if(gd->dimx) _aligned_free(gd->dimx); _aligned_free(gd); + + m_parent->m_perfmon.Put(GSPerfMon::Fillrate, pixels); + } + + void UseTargetPages() + { + if(m_using_pages) {ASSERT(0); return;} + + GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param; + + if(gd->sel.fwrite) + { + m_parent->UseTargetPages(m_fb_pages, 0); + } + + if(gd->sel.zwrite) + { + m_parent->UseTargetPages(m_zb_pages, 1); + } + + m_using_pages = true; + } + + void ReleaseTargetPages() + { + if(!m_using_pages) {ASSERT(0); return;} + + GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param; + + if(gd->sel.fwrite) + { + m_parent->ReleaseTargetPages(m_fb_pages, 0); + } + + if(gd->sel.zwrite) + { + m_parent->ReleaseTargetPages(m_zb_pages, 1); + } + + m_using_pages = false; } }; diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 72ec7fa6b3..3e96c58469 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -592,7 +592,11 @@ void GSState::ApplyTEX0(int i, GIFRegTEX0& TEX0) bool wt = m_mem.m_clut.WriteTest(TEX0, m_env.TEXCLUT); - if(wt || PRIM->CTXT == i && TEX0 != m_env.CTXT[i].TEX0) + // clut loading already covered with WriteTest, for drawing only have to check CPSM and CSA (MGS3 intro skybox would be drawn piece by piece without this) + + uint64 mask = 0x1f78001c3fffffffull; // TBP0 TBW PSM TW TCC TFX CPSM CSA + + if(wt || PRIM->CTXT == i && ((TEX0.u64 ^ m_env.CTXT[i].TEX0.u64) & mask)) { Flush(); } @@ -743,7 +747,9 @@ template void GSState::GIFRegHandlerTEX2(const GIFReg* RESTRICT r) // TFX, TCC, TH, TW, TBW, and TBP0 uint64 mask = 0xFFFFFFE003F00000ull; // TEX2 bits + GIFRegTEX0 TEX0; + TEX0.u64 = (m_env.CTXT[i].TEX0.u64 & ~mask) | (r->u64 & mask); ApplyTEX0(i, TEX0); diff --git a/plugins/GSdx/GSThread.cpp b/plugins/GSdx/GSThread.cpp index 2571538dae..54284285f0 100644 --- a/plugins/GSdx/GSThread.cpp +++ b/plugins/GSdx/GSThread.cpp @@ -22,6 +22,44 @@ #include "stdafx.h" #include "GSThread.h" +#ifdef _WINDOWS + +InitializeConditionVariablePtr pInitializeConditionVariable; +WakeConditionVariablePtr pWakeConditionVariable; +WakeAllConditionVariablePtr pWakeAllConditionVariable; +SleepConditionVariableSRWPtr pSleepConditionVariableSRW; +InitializeSRWLockPtr pInitializeSRWLock;; +AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive; +ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive; + +class InitCondVar +{ + HMODULE m_kernel32; + +public: + InitCondVar() + { + m_kernel32 = LoadLibrary("kernel32.dll"); // should not call LoadLibrary from DllMain, but kernel32.dll is the only one guaranteed to be loaded already + + pInitializeConditionVariable = (InitializeConditionVariablePtr)GetProcAddress(m_kernel32, "InitializeConditionVariable"); + pWakeConditionVariable = (WakeConditionVariablePtr)GetProcAddress(m_kernel32, "WakeConditionVariable"); + pWakeAllConditionVariable = (WakeAllConditionVariablePtr)GetProcAddress(m_kernel32, "WakeAllConditionVariable"); + pSleepConditionVariableSRW = (SleepConditionVariableSRWPtr)GetProcAddress(m_kernel32, "SleepConditionVariableSRW"); + pInitializeSRWLock = (InitializeSRWLockPtr)GetProcAddress(m_kernel32, "InitializeSRWLock"); + pAcquireSRWLockExclusive = (AcquireSRWLockExclusivePtr)GetProcAddress(m_kernel32, "AcquireSRWLockExclusive"); + pReleaseSRWLockExclusive = (ReleaseSRWLockExclusivePtr)GetProcAddress(m_kernel32, "ReleaseSRWLockExclusive"); + } + + virtual ~InitCondVar() + { + FreeLibrary(m_kernel32); + } +}; + +static InitCondVar s_icv; + +#endif + GSThread::GSThread() { #ifdef _WINDOWS diff --git a/plugins/GSdx/GSThread.h b/plugins/GSdx/GSThread.h index 6cd70a82bb..a2ed3b7de4 100644 --- a/plugins/GSdx/GSThread.h +++ b/plugins/GSdx/GSThread.h @@ -23,6 +23,22 @@ #ifdef _WINDOWS +typedef void (WINAPI * InitializeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable); +typedef void (WINAPI * WakeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable); +typedef void (WINAPI * WakeAllConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable); +typedef void (WINAPI * SleepConditionVariableSRWPtr)(CONDITION_VARIABLE* ConditionVariable, SRWLOCK* SRWLock, DWORD dwMilliseconds, ULONG Flags); +typedef void (WINAPI * InitializeSRWLockPtr)(SRWLOCK* SRWLock); +typedef void (WINAPI * AcquireSRWLockExclusivePtr)(SRWLOCK* SRWLock); +typedef void (WINAPI * ReleaseSRWLockExclusivePtr)(SRWLOCK* SRWLock); + +extern InitializeConditionVariablePtr pInitializeConditionVariable; +extern WakeConditionVariablePtr pWakeConditionVariable; +extern WakeAllConditionVariablePtr pWakeAllConditionVariable; +extern SleepConditionVariableSRWPtr pSleepConditionVariableSRW; +extern InitializeSRWLockPtr pInitializeSRWLock;; +extern AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive; +extern ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive; + class GSThread { DWORD m_ThreadId; @@ -68,6 +84,32 @@ public: bool Wait() {return WaitForSingleObject(m_hEvent, INFINITE) == WAIT_OBJECT_0;} }; +class GSCondVarLock +{ + SRWLOCK m_lock; + +public: + GSCondVarLock() {pInitializeSRWLock(&m_lock);} + + void Lock() {pAcquireSRWLockExclusive(&m_lock);} + void Unlock() {pReleaseSRWLockExclusive(&m_lock);} + + operator SRWLOCK* () {return &m_lock;} +}; + +class GSCondVar +{ + CONDITION_VARIABLE m_cv; + +public: + GSCondVar() {pInitializeConditionVariable(&m_cv);} + + void Set() {pWakeConditionVariable(&m_cv);} + void Wait(GSCondVarLock& lock) {pSleepConditionVariableSRW(&m_cv, lock, INFINITE, 0);} + + operator CONDITION_VARIABLE* () {return &m_cv;} +}; + #else #include @@ -128,6 +170,34 @@ public: bool Wait() {return sem_wait(&m_sem) == 0;} }; +class GSCondVarLock +{ + pthread_mutex_t m_lock; + +public: + GSCondVarLock() {pthread_mutex_init(&m_lock, NULL);} + virtual ~GSCondVarLock() {pthread_mutex_destroy(&m_lock);} + + void Lock() {pthread_mutex_lock(&m_lock);} + void Unlock() {pthread_mutex_unlock(&m_lock);} + + operator pthread_mutex_t* () {return &m_lock;} +}; + +class GSCondVar +{ + pthread_cond_t m_cv; + +public: + GSCondVar() {pthread_cond_init(&m_cv);} + virtual ~GSCondVar() {pthread_cond_destroy(&m_cv);} + + void Set() {pthread_cond_signal(&m_cv);} + void Wait(GSCondVarLock& lock) {pthread_cond_wait(&m_cv, lock);} + + operator pthread_cond_t* () {return &m_cv;} +}; + #endif class GSAutoLock @@ -167,42 +237,21 @@ protected: queue m_queue; volatile bool m_exit; struct {GSCritSec lock; GSEvent notempty; volatile long count;} m_ev; - #ifdef _WINDOWS - struct {SRWLOCK lock; CONDITION_VARIABLE notempty, empty; bool available;} m_cv; - HMODULE m_kernel32; - typedef void (WINAPI * InitializeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable); - typedef void (WINAPI * WakeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable); - typedef void (WINAPI * WakeAllConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable); - typedef void (WINAPI * SleepConditionVariableSRWPtr)(CONDITION_VARIABLE* ConditionVariable, SRWLOCK* SRWLock, DWORD dwMilliseconds, ULONG Flags); - typedef void (WINAPI * InitializeSRWLockPtr)(SRWLOCK* SRWLock); - typedef void (WINAPI * AcquireSRWLockExclusivePtr)(SRWLOCK* SRWLock); - typedef void (WINAPI * ReleaseSRWLockExclusivePtr)(SRWLOCK* SRWLock); - InitializeConditionVariablePtr pInitializeConditionVariable; - WakeConditionVariablePtr pWakeConditionVariable; - WakeAllConditionVariablePtr pWakeAllConditionVariable; - SleepConditionVariableSRWPtr pSleepConditionVariableSRW; - InitializeSRWLockPtr pInitializeSRWLock;; - AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive; - ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive; - #elif defined(_LINUX) - struct {pthread_mutex_t lock; pthread_cond_t notempty, empty; bool available;} m_cv; - #endif + struct {GSCondVar notempty, empty; GSCondVarLock lock; bool available;} m_cv; void ThreadProc() { - if(m_cv.available) { - #ifdef _WINDOWS - pAcquireSRWLockExclusive(&m_cv.lock); + m_cv.lock.Lock(); while(true) { while(m_queue.empty()) { - pSleepConditionVariableSRW(&m_cv.notempty, &m_cv.lock, INFINITE, 0); + m_cv.notempty.Wait(m_cv.lock); - if(m_exit) {pReleaseSRWLockExclusive(&m_cv.lock); return;} + if(m_exit) {m_cv.lock.Unlock(); return;} } { @@ -210,51 +259,20 @@ protected: T item = m_queue.front(); - pReleaseSRWLockExclusive(&m_cv.lock); + m_cv.lock.Unlock(); Process(item); - pAcquireSRWLockExclusive(&m_cv.lock); + m_cv.lock.Lock(); m_queue.pop(); } if(m_queue.empty()) { - pWakeConditionVariable(&m_cv.empty); + m_cv.empty.Set(); } } - #elif defined(_LINUX) - pthread_mutex_lock(&m_cv.lock); - - while(true) - { - while(m_queue.empty()) - { - pthread_cond_wait(&m_cv.notempty, &m_cv.lock); - - if(m_exit) {pthread_mutex_unlock(&m_cv.lock); return;} - } - - { - // NOTE: this is scoped because we must make sure the last item is no longer around when Wait detects an empty queue - T item = m_queue.front(); - - pthread_mutex_unlock(&m_cv.lock); - - Process(item); - - pthread_mutex_lock(&m_cv.lock); - - m_queue.pop(); - } - - if(m_queue.empty()) - { - pthread_cond_signal(&m_cv.empty); - } - } - #endif } else { @@ -302,33 +320,12 @@ public: #ifdef _WINDOWS - m_cv.available = false; - - m_kernel32 = LoadLibrary("kernel32.dll"); - - pInitializeConditionVariable = (InitializeConditionVariablePtr)GetProcAddress(m_kernel32, "InitializeConditionVariable"); - pWakeConditionVariable = (WakeConditionVariablePtr)GetProcAddress(m_kernel32, "WakeConditionVariable"); - pWakeAllConditionVariable = (WakeAllConditionVariablePtr)GetProcAddress(m_kernel32, "WakeAllConditionVariable"); - pSleepConditionVariableSRW = (SleepConditionVariableSRWPtr)GetProcAddress(m_kernel32, "SleepConditionVariableSRW"); - pInitializeSRWLock = (InitializeSRWLockPtr)GetProcAddress(m_kernel32, "InitializeSRWLock"); - pAcquireSRWLockExclusive = (AcquireSRWLockExclusivePtr)GetProcAddress(m_kernel32, "AcquireSRWLockExclusive"); - pReleaseSRWLockExclusive = (ReleaseSRWLockExclusivePtr)GetProcAddress(m_kernel32, "ReleaseSRWLockExclusive"); - - if(pInitializeConditionVariable != NULL) - { - pInitializeSRWLock(&m_cv.lock); - pInitializeConditionVariable(&m_cv.notempty); - pInitializeConditionVariable(&m_cv.empty); - - m_cv.available = true; - } + m_cv.available = pInitializeConditionVariable != NULL; #elif defined(_LINUX) - m_cv.available = true; - // FIXME attribute - pthread_cond_init(&m_cv.notempty, NULL); - pthread_cond_init(&m_cv.empty, NULL); - pthread_mutex_init(&m_cv.lock, NULL); + + m_cv.available = true; + #endif CreateThread(); @@ -338,32 +335,14 @@ public: { m_exit = true; - if(m_cv.available) { - #ifdef _WINDOWS - pWakeConditionVariable(&m_cv.notempty); - #elif defined(_LINUX) - pthread_cond_signal(&m_cv.notempty); - - pthread_mutex_destroy(&m_cv.lock); - pthread_cond_destroy(&m_cv.notempty); - pthread_cond_destroy(&m_cv.empty); - #endif + m_cv.notempty.Set(); } else { m_ev.notempty.Set(); } - - - #ifdef _WINDOWS - if(m_kernel32 != NULL) - { - FreeLibrary(m_kernel32); // lol, decrement the refcount anyway - } - #endif - } int GetCount() const @@ -373,31 +352,18 @@ public: virtual void Push(const T& item) { - if(m_cv.available) { - #ifdef _WINDOWS - pAcquireSRWLockExclusive(&m_cv.lock); - + m_cv.lock.Lock(); + m_queue.push(item); - pReleaseSRWLockExclusive(&m_cv.lock); + m_cv.lock.Unlock(); - pWakeConditionVariable(&m_cv.notempty); - #elif defined(_LINUX) - pthread_mutex_lock(&m_cv.lock); - - m_queue.push(item); - - pthread_mutex_unlock(&m_cv.lock); - - pthread_cond_signal(&m_cv.notempty); - #endif + m_cv.notempty.Set(); } else { - - GSAutoLock l(&m_ev.lock); m_queue.push(item); @@ -412,36 +378,22 @@ public: virtual void Wait() { - if(m_cv.available) { - #ifdef _WINDOWS - pAcquireSRWLockExclusive(&m_cv.lock); + m_cv.lock.Lock(); while(!m_queue.empty()) { - pSleepConditionVariableSRW(&m_cv.empty, &m_cv.lock, INFINITE, 0); + m_cv.empty.Wait(m_cv.lock); } - pReleaseSRWLockExclusive(&m_cv.lock); - #elif defined(_LINUX) - pthread_mutex_lock(&m_cv.lock); - - while(!m_queue.empty()) - { - pthread_cond_wait(&m_cv.empty, &m_cv.lock); - } - - pthread_mutex_unlock(&m_cv.lock); - #endif + m_cv.lock.Unlock(); } else { - // NOTE: it is the safest to have our own counter because m_queue.pop() might decrement its own before the last item runs out of its scope and gets destroyed (implementation dependent) while(m_ev.count > 0) _mm_pause(); - } m_count++; diff --git a/plugins/GSdx/stdafx.h b/plugins/GSdx/stdafx.h index c4ff5070ea..fdd228af1b 100644 --- a/plugins/GSdx/stdafx.h +++ b/plugins/GSdx/stdafx.h @@ -71,6 +71,17 @@ #endif +// put these into vc9/common7/ide/usertype.dat to have them highlighted + +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned long long uint64; +typedef signed long long int64; + // stdc #include @@ -115,6 +126,57 @@ using namespace std; using namespace stdext; + // hashing algoritms at: http://www.cris.com/~Ttwang/tech/inthash.htm + // default hash_compare does ldiv and other crazy stuff to reduce speed + + template<> class hash_compare + { + public: + enum {bucket_size = 1}; + + size_t operator()(uint32 key) const + { + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + + return (size_t)key; + } + + bool operator()(uint32 a, uint32 b) const + { + return a < b; + } + }; + + template<> class hash_compare + { + public: + enum {bucket_size = 1}; + + size_t operator()(uint64 key) const + { + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + + return (size_t)key; + } + + bool operator()(uint64 a, uint64 b) const + { + return a < b; + } + }; + #define vsnprintf _vsnprintf #define snprintf _snprintf @@ -171,19 +233,6 @@ struct aligned_free_object {template void operator()(T& p) {_aligned_fr struct aligned_free_first {template void operator()(T& p) {_aligned_free(p.first);}}; struct aligned_free_second {template void operator()(T& p) {_aligned_free(p.second);}}; -// syntactic sugar - -// put these into vc9/common7/ide/usertype.dat to have them highlighted - -typedef unsigned char uint8; -typedef signed char int8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef signed int int32; -typedef unsigned long long uint64; -typedef signed long long int64; - #define countof(a) (sizeof(a) / sizeof(a[0])) #define ALIGN_STACK(n) __aligned(int, n) __dummy;