diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index e09780d31e..8d4c3e0e79 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -1,4 +1,4 @@ - + @@ -34,12 +34,12 @@ true StaticLibrary - MultiByte + Unicode true StaticLibrary - MultiByte + Unicode false @@ -49,7 +49,7 @@ StaticLibrary false - MultiByte + Unicode false @@ -59,7 +59,7 @@ StaticLibrary false - MultiByte + Unicode diff --git a/Source/Core/Core/Src/DSPEmulator.h b/Source/Core/Core/Src/DSPEmulator.h index 30de180cf3..b5d04e3e2a 100644 --- a/Source/Core/Core/Src/DSPEmulator.h +++ b/Source/Core/Core/Src/DSPEmulator.h @@ -44,6 +44,7 @@ public: virtual void DSP_Update(int cycles) = 0; virtual void DSP_StopSoundStream() = 0; virtual void DSP_ClearAudioBuffer(bool mute) = 0; + virtual u32 DSP_UpdateRate() = 0; protected: SoundStream *soundStream; diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp index 3e73944e44..6d15c8226a 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp @@ -28,6 +28,7 @@ #include "../AudioInterface.h" #include "ConfigManager.h" #include "Core.h" +#include "HW/SystemTimers.h" DSPHLE::DSPHLE() { m_InitMixer = false; @@ -87,6 +88,16 @@ void DSPHLE::DSP_Update(int cycles) m_pUCode->Update(cycles / 6); } +u32 DSPHLE::DSP_UpdateRate() +{ + // AX HLE uses 3ms (Wii) or 5ms (GC) timing period + int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.bVBeam ? 2 : 1; + if (m_pUCode != NULL) + return (SystemTimers::GetTicksPerSecond() / 1000) * m_pUCode->GetUpdateMs() / fields; + else + return SystemTimers::GetTicksPerSecond() / 1000; +} + void DSPHLE::SendMailToDSP(u32 _uMail) { if (m_pUCode != NULL) { diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h index 6ad20115b4..50d65d5d52 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h @@ -46,6 +46,7 @@ public: virtual void DSP_Update(int cycles); virtual void DSP_StopSoundStream(); virtual void DSP_ClearAudioBuffer(bool mute); + virtual u32 DSP_UpdateRate(); CMailHandler& AccessMailHandler() { return m_MailHandler; } diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp index 18c7edfd8b..cbe558c878 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp @@ -738,6 +738,11 @@ void CUCode_AX::Update(int cycles) } } +u32 CUCode_AX::GetUpdateMs() +{ + return 5; +} + void CUCode_AX::DoAXState(PointerWrap& p) { p.Do(m_cmdlist); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h index f55d2a1858..8d1cb99c25 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h @@ -73,6 +73,7 @@ public: virtual void MixAdd(short* out_buffer, int nsamples); virtual void Update(int cycles); virtual void DoState(PointerWrap& p); + u32 GetUpdateMs(); // Needed because StdThread.h std::thread implem does not support member // pointers. TODO(delroth): obsolete. diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp index 41d782a01a..0c3714ffea 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp @@ -672,6 +672,11 @@ void CUCode_AXWii::OutputWMSamples(u32* addresses) } } +u32 CUCode_AXWii::GetUpdateMs() +{ + return 3; +} + void CUCode_AXWii::DoState(PointerWrap &p) { std::lock_guard lk(m_processing); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h index 6e4eb7ad4e..12cb47a868 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h @@ -25,6 +25,7 @@ class CUCode_AXWii : public CUCode_AX public: CUCode_AXWii(DSPHLE *dsp_hle, u32 _CRC); virtual ~CUCode_AXWii(); + u32 GetUpdateMs(); virtual void DoState(PointerWrap &p); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.cpp index c29cf9e536..63316caa21 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.cpp @@ -19,6 +19,7 @@ #include "UCodes.h" #include "UCode_CARD.h" #include "../../DSP.h" +#include "ConfigManager.h" CUCode_CARD::CUCode_CARD(DSPHLE *dsp_hle, u32 crc) @@ -44,6 +45,11 @@ void CUCode_CARD::Update(int cycles) } } +u32 CUCode_CARD::GetUpdateMs() +{ + return SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5; +} + void CUCode_CARD::HandleMail(u32 _uMail) { if (_uMail == 0xFF000000) // unlock card diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.h index a6f90124ad..163dcc3fb0 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_CARD.h @@ -25,6 +25,7 @@ class CUCode_CARD : public IUCode public: CUCode_CARD(DSPHLE *dsp_hle, u32 crc); virtual ~CUCode_CARD(); + u32 GetUpdateMs(); void HandleMail(u32 _uMail); void Update(int cycles); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.cpp index 00fef067ff..86d561d395 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.cpp @@ -19,6 +19,7 @@ #include "UCode_GBA.h" #include "../../DSP.h" +#include "ConfigManager.h" CUCode_GBA::CUCode_GBA(DSPHLE *dsp_hle, u32 crc) : IUCode(dsp_hle, crc) @@ -40,6 +41,11 @@ void CUCode_GBA::Update(int cycles) } } +u32 CUCode_GBA::GetUpdateMs() +{ + return SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5; +} + void CUCode_GBA::HandleMail(u32 _uMail) { static bool nextmail_is_mramaddr = false; diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.h index c61917339f..8ab66a22ec 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_GBA.h @@ -23,6 +23,7 @@ struct CUCode_GBA : public IUCode { CUCode_GBA(DSPHLE *dsp_hle, u32 crc); virtual ~CUCode_GBA(); + u32 GetUpdateMs(); void HandleMail(u32 _uMail); void Update(int cycles); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.cpp index ae7716012a..a874bc173d 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.cpp @@ -17,6 +17,7 @@ #include "UCodes.h" #include "UCode_InitAudioSystem.h" +#include "ConfigManager.h" CUCode_InitAudioSystem::CUCode_InitAudioSystem(DSPHLE *dsp_hle, u32 crc) : IUCode(dsp_hle, crc) @@ -42,6 +43,11 @@ void CUCode_InitAudioSystem::Update(int cycles) } } +u32 CUCode_InitAudioSystem::GetUpdateMs() +{ + return SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5; +} + void CUCode_InitAudioSystem::HandleMail(u32 _uMail) {} diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.h index 8dc237f1d0..a698df4e4c 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.h @@ -25,6 +25,7 @@ class CUCode_InitAudioSystem : public IUCode public: CUCode_InitAudioSystem(DSPHLE *dsp_hle, u32 crc); virtual ~CUCode_InitAudioSystem(); + u32 GetUpdateMs(); void HandleMail(u32 _uMail); void Update(int cycles); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.cpp index b94486fe9e..f4ab0ac366 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.cpp @@ -19,6 +19,7 @@ #include "UCode_ROM.h" #include "Hash.h" #include "../../Memmap.h" +#include "ConfigManager.h" CUCode_Rom::CUCode_Rom(DSPHLE *dsp_hle, u32 crc) : IUCode(dsp_hle, crc) @@ -117,6 +118,11 @@ void CUCode_Rom::BootUCode() m_DSPHLE->SetUCode(ector_crc); } +u32 CUCode_Rom::GetUpdateMs() +{ + return SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5; +} + void CUCode_Rom::DoState(PointerWrap &p) { p.Do(m_CurrentUCode); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.h index f1e7b8ec7a..5dc0ce73c1 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_ROM.h @@ -25,6 +25,7 @@ class CUCode_Rom : public IUCode public: CUCode_Rom(DSPHLE *dsp_hle, u32 _crc); virtual ~CUCode_Rom(); + u32 GetUpdateMs(); void HandleMail(u32 _uMail); void Update(int cycles); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp index 9d392cd6b0..681197703d 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp @@ -27,6 +27,7 @@ #include "WaveFile.h" #include "../../DSP.h" +#include "ConfigManager.h" CUCode_Zelda::CUCode_Zelda(DSPHLE *dsp_hle, u32 _CRC) @@ -565,6 +566,10 @@ void CUCode_Zelda::ExecuteList() } } +u32 CUCode_Zelda::GetUpdateMs() +{ + return SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5; +} void CUCode_Zelda::DoState(PointerWrap &p) { diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.h index 94a5bcea3f..19567fd302 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.h @@ -133,6 +133,7 @@ class CUCode_Zelda : public IUCode public: CUCode_Zelda(DSPHLE *dsp_hle, u32 _CRC); virtual ~CUCode_Zelda(); + u32 GetUpdateMs(); void HandleMail(u32 _uMail); void HandleMail_LightVersion(u32 _uMail); diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h index 225ac731c0..1b089228e0 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h @@ -92,6 +92,7 @@ public: // Cycles are out of the 81/121mhz the DSP runs at. virtual void Update(int cycles) = 0; virtual void MixAdd(short* buffer, int size) {} + virtual u32 GetUpdateMs() = 0; virtual void DoState(PointerWrap &p) { DoStateShared(p); } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index fecbf8d702..ded232a9b1 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -326,6 +326,11 @@ void DSPLLE::DSP_Update(int cycles) } } +u32 DSPLLE::DSP_UpdateRate() +{ + return 12600; // TO BE TWEAKED +} + void DSPLLE::DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) { if (!soundStream) diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h index 456d038c96..4043c95452 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h @@ -44,6 +44,7 @@ public: virtual void DSP_Update(int cycles); virtual void DSP_StopSoundStream(); virtual void DSP_ClearAudioBuffer(bool mute); + virtual u32 DSP_UpdateRate(); private: static void dsp_thread(DSPLLE* lpParameter); diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index fb8ddb0c26..134d286d78 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -119,9 +119,6 @@ int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default // These are badly educated guesses // Feel free to experiment. Set these in Init below. int - // These shouldn't be period controlled either, most likely. - DSP_PERIOD, - // This is a fixed value, don't change it AUDIO_DMA_PERIOD, @@ -149,8 +146,8 @@ void DSPCallback(u64 userdata, int cyclesLate) { //splits up the cycle budget in case lle is used //for hle, just gives all of the slice to hle - DSP::UpdateDSPSlice(DSP_PERIOD - cyclesLate); - CoreTiming::ScheduleEvent(DSP_PERIOD - cyclesLate, et_DSP); + DSP::UpdateDSPSlice(DSP::GetDSPEmulator()->DSP_UpdateRate() - cyclesLate); + CoreTiming::ScheduleEvent(DSP::GetDSPEmulator()->DSP_UpdateRate() - cyclesLate, et_DSP); } void AudioDMACallback(u64 userdata, int cyclesLate) @@ -256,17 +253,6 @@ void Init() IPC_HLE_PERIOD = GetTicksPerSecond() / (freq * fields); } - if (DSP::GetDSPEmulator()->IsLLE()) - { - DSP_PERIOD = 12600; // TO BE TWEAKED - } - else - { - // AX HLE uses 3ms (Wii) or 5ms (GC) timing period - int ms_to_process = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5; - DSP_PERIOD = (int)(GetTicksPerSecond() / 1000) * ms_to_process / fields; - } - // System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (AudioInterface::GetAIDSampleRate() * 4 / 32); @@ -292,7 +278,7 @@ void Init() et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI); - CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP); + CoreTiming::ScheduleEvent(0, et_DSP); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI); CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU) diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.cpp b/Source/Core/VideoCommon/Src/IndexGenerator.cpp index aa1a971687..28c62193c2 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.cpp +++ b/Source/Core/VideoCommon/Src/IndexGenerator.cpp @@ -18,17 +18,9 @@ #include #include "Common.h" +#include "VideoConfig.h" #include "IndexGenerator.h" -/* -* -QUAD simulator - -0 1 4 5 -3 2 7 6 -012023 147172 ... -*/ - //Init u16 *IndexGenerator::Tptr; u16 *IndexGenerator::BASETptr; @@ -41,6 +33,32 @@ u32 IndexGenerator::numL; u32 IndexGenerator::numP; u32 IndexGenerator::index; +static const u16 s_primitive_restart = -1; + +static void (*primitive_table[8])(u32); + +void IndexGenerator::Init() +{ + if(g_Config.backend_info.bSupportsPrimitiveRestart) + { + primitive_table[0] = IndexGenerator::AddQuads; + primitive_table[2] = IndexGenerator::AddList; + primitive_table[3] = IndexGenerator::AddStrip; + primitive_table[4] = IndexGenerator::AddFan; + } + else + { + primitive_table[0] = IndexGenerator::AddQuads; + primitive_table[2] = IndexGenerator::AddList; + primitive_table[3] = IndexGenerator::AddStrip; + primitive_table[4] = IndexGenerator::AddFan; + } + primitive_table[1] = NULL; + primitive_table[5] = &IndexGenerator::AddLineList; + primitive_table[6] = &IndexGenerator::AddLineStrip; + primitive_table[7] = &IndexGenerator::AddPoints; +} + void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) { Tptr = Triangleptr; @@ -57,82 +75,150 @@ void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr) void IndexGenerator::AddIndices(int primitive, u32 numVerts) { - //switch (primitive) - //{ - //case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVerts); break; - //case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVerts); break; - //case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVerts); break; - //case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVerts); break; - //case GX_DRAW_LINES: IndexGenerator::AddLineList(numVerts); break; - //case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVerts); break; - //case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVerts); break; - //} - - static void (*const primitive_table[])(u32) = - { - IndexGenerator::AddQuads, - NULL, - IndexGenerator::AddList, - IndexGenerator::AddStrip, - IndexGenerator::AddFan, - IndexGenerator::AddLineList, - IndexGenerator::AddLineStrip, - IndexGenerator::AddPoints, - }; - primitive_table[primitive](numVerts); index += numVerts; } // Triangles -__forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) +template __forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3) { *Tptr++ = index1; *Tptr++ = index2; *Tptr++ = index3; - + if(pr) + *Tptr++ = s_primitive_restart; + ++numT; } -void IndexGenerator::AddList(u32 const numVerts) +template void IndexGenerator::AddList(u32 const numVerts) { auto const numTris = numVerts / 3; for (u32 i = 0; i != numTris; ++i) { - WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2); + WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2); } + u32 remainingVerts = numVerts - numTris*3; + if(remainingVerts) + ERROR_LOG(VIDEO, "AddList: unknown count of vertices found"); } -void IndexGenerator::AddStrip(u32 const numVerts) +template void IndexGenerator::AddStrip(u32 const numVerts) { - bool wind = false; - for (u32 i = 2; i < numVerts; ++i) - { - WriteTriangle( - index + i - 2, - index + i - !wind, - index + i - wind); + if(pr) { + for (u32 i = 0; i < numVerts; ++i) + { + *Tptr++ = index + i; + } + *Tptr++ = s_primitive_restart; + numT += numVerts - 2; + + } else { + bool wind = false; + for (u32 i = 2; i < numVerts; ++i) + { + WriteTriangle( + index + i - 2, + index + i - !wind, + index + i - wind); - wind ^= true; + wind ^= true; + } } } -void IndexGenerator::AddFan(u32 numVerts) +/** + * FAN simulator: + * + * 2---3 + * / \ / \ + * 1---0---4 + * + * would generate this triangles: + * 012, 023, 034 + * + * rotated (for better striping): + * 120, 302, 034 + * + * as odd ones have to winded, following strip is fine: + * 12034 + * + * so we use 6 indices for 3 triangles + */ + +template void IndexGenerator::AddFan(u32 numVerts) { - for (u32 i = 2; i < numVerts; ++i) + u32 i = 2; + + if(pr) { + for(; i<=numVerts-3; i+=3) { + *Tptr++ = index + i - 1; + *Tptr++ = index + i + 0; + *Tptr++ = index; + *Tptr++ = index + i + 1; + *Tptr++ = index + i + 2; + *Tptr++ = s_primitive_restart; + numT += 3; + } + + for(; i<=numVerts-2; i+=2) { + *Tptr++ = index + i - 1; + *Tptr++ = index + i + 0; + *Tptr++ = index; + *Tptr++ = index + i + 1; + *Tptr++ = s_primitive_restart; + numT += 2; + } + } + + for (; i < numVerts; ++i) { - WriteTriangle(index, index + i - 1, index + i); + WriteTriangle(index, index + i - 1, index + i); } } -void IndexGenerator::AddQuads(u32 numVerts) +/* + * QUAD simulator + * + * 0---1 4---5 + * |\ | |\ | + * | \ | | \ | + * | \| | \| + * 3---2 7---6 + * + * 012,023, 456,467 ... + * or 120,302, 564,746 + * or as strip: 1203, 5647 + * + * Warning: + * A simple triangle has to be rendered for three vertices. + * ZWW do this for sun rays + */ +template void IndexGenerator::AddQuads(u32 numVerts) { auto const numQuads = numVerts / 4; for (u32 i = 0; i != numQuads; ++i) { - WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); - WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); + if(pr) { + *Tptr++ = index + i * 4 + 1; + *Tptr++ = index + i * 4 + 2; + *Tptr++ = index + i * 4 + 0; + *Tptr++ = index + i * 4 + 3; + *Tptr++ = s_primitive_restart; + numT += 2; + } else { + WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2); + WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3); + } } + // three vertices remaining, so render a triangle + u32 remainingVerts = numVerts - numQuads*4; + if(remainingVerts == 3) + { + WriteTriangle(index+numVerts-3, index+numVerts-2, index+numVerts-1); + } + else if(remainingVerts) + ERROR_LOG(VIDEO, "AddQuads: unknown count of vertices found"); } // Lines @@ -145,8 +231,14 @@ void IndexGenerator::AddLineList(u32 numVerts) *Lptr++ = index + i * 2 + 1; ++numL; } + u32 remainingVerts = numVerts - numLines*2; + if(remainingVerts) + ERROR_LOG(VIDEO, "AddLineList: unknown count of vertices found"); + } +// shouldn't be used as strips as LineLists are much more common +// so converting them to lists void IndexGenerator::AddLineStrip(u32 numVerts) { for (u32 i = 1; i < numVerts; ++i) @@ -170,6 +262,6 @@ void IndexGenerator::AddPoints(u32 numVerts) u32 IndexGenerator::GetRemainingIndices() { - u32 max_index = 65535; + u32 max_index = 65534; // -1 is reserved for primitive restart (ogl + dx11) return max_index - index; } diff --git a/Source/Core/VideoCommon/Src/IndexGenerator.h b/Source/Core/VideoCommon/Src/IndexGenerator.h index f14d3ae026..421c0aa4a8 100644 --- a/Source/Core/VideoCommon/Src/IndexGenerator.h +++ b/Source/Core/VideoCommon/Src/IndexGenerator.h @@ -26,6 +26,7 @@ class IndexGenerator { public: // Init + static void Init(); static void Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr); static void AddIndices(int primitive, u32 numVertices); @@ -54,10 +55,10 @@ public: */ private: // Triangles - static void AddList(u32 numVerts); - static void AddStrip(u32 numVerts); - static void AddFan(u32 numVerts); - static void AddQuads(u32 numVerts); + template static void AddList(u32 numVerts); + template static void AddStrip(u32 numVerts); + template static void AddFan(u32 numVerts); + template static void AddQuads(u32 numVerts); // Lines static void AddLineList(u32 numVerts); @@ -66,7 +67,7 @@ private: // Points static void AddPoints(u32 numVerts); - static void WriteTriangle(u32 index1, u32 index2, u32 index3); + template static void WriteTriangle(u32 index1, u32 index2, u32 index3); static u16 *Tptr; static u16 *BASETptr; diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index d1e8b14e8a..f27271efe6 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -659,6 +659,10 @@ void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2) m_VtxAttr.texCoord[7].Elements = vat.g2.Tex7CoordElements; m_VtxAttr.texCoord[7].Format = vat.g2.Tex7CoordFormat; m_VtxAttr.texCoord[7].Frac = vat.g2.Tex7Frac; + + if(!m_VtxAttr.ByteDequant) { + ERROR_LOG(VIDEO, "ByteDequant is set to zero"); + } }; void VertexLoader::AppendToString(std::string *dest) const diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index 3e2e88c55f..567621964f 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -74,28 +74,54 @@ bool VertexManager::IsFlushed() const u32 VertexManager::GetRemainingIndices(int primitive) { - switch (primitive) - { - case GX_DRAW_QUADS: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; - case GX_DRAW_TRIANGLES: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); - case GX_DRAW_TRIANGLE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; - case GX_DRAW_TRIANGLE_FAN: - return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + + if(g_Config.backend_info.bSupportsPrimitiveRestart) { + switch (primitive) + { + case GX_DRAW_QUADS: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 5 * 4; + case GX_DRAW_TRIANGLES: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 4 * 3; + case GX_DRAW_TRIANGLE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 1 - 1; + case GX_DRAW_TRIANGLE_FAN: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4 + 1; - case GX_DRAW_LINES: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); - case GX_DRAW_LINE_STRIP: - return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; + case GX_DRAW_LINES: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); + case GX_DRAW_LINE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; - case GX_DRAW_POINTS: - return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); + case GX_DRAW_POINTS: + return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); - default: - return 0; - } + default: + return 0; + } + } else { + switch (primitive) + { + case GX_DRAW_QUADS: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4; + case GX_DRAW_TRIANGLES: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()); + case GX_DRAW_TRIANGLE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + case GX_DRAW_TRIANGLE_FAN: + return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2; + + case GX_DRAW_LINES: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()); + case GX_DRAW_LINE_STRIP: + return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1; + + case GX_DRAW_POINTS: + return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen()); + + default: + return 0; + } + } } void VertexManager::AddVertices(int primitive, u32 numVertices) diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 1670e47222..f282a3edeb 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -165,6 +165,7 @@ struct VideoConfig bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL bool bSupportsFormatReinterpretation; bool bSupportsPixelLighting; + bool bSupportsPrimitiveRestart; bool bSupportsSeparateAlphaFunction; bool bSupportsGLSLUBO; // needed by pixelShaderGen, so must stay in videoCommon } backend_info; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index da8c98e19e..e573751698 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -154,7 +154,7 @@ void VertexManager::Draw(UINT stride) if (IndexGenerator::GetNumTriangles() > 0) { - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangle_draw_index, 0); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index a5d395b1ce..0fe58e4277 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -35,6 +35,7 @@ #include "Debugger/DebuggerPanel.h" #include "DLCache.h" #include "EmuWindow.h" +#include "IndexGenerator.h" #include "FileUtil.h" #include "Globals.h" #include "IniFile.h" @@ -96,6 +97,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsPixelLighting = true; + g_Config.backend_info.bSupportsPrimitiveRestart = true; IDXGIFactory* factory; IDXGIAdapter* ad; @@ -192,6 +194,7 @@ void VideoBackend::Video_Prepare() // VideoCommon BPInit(); Fifo_Init(); + IndexGenerator::Init(); VertexLoaderManager::Init(); OpcodeDecoder_Init(); VertexShaderManager::Init(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index f52ad1e40d..4d21506b9c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -51,6 +51,7 @@ #include "VideoState.h" #include "Render.h" #include "DLCache.h" +#include "IndexGenerator.h" #include "IniFile.h" #include "Core.h" #include "Host.h" @@ -102,6 +103,7 @@ void InitBackendInfo() g_Config.backend_info.bUseRGBATextures = false; g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = true; + g_Config.backend_info.bSupportsPrimitiveRestart = false; // TODO: figure out if it does g_Config.backend_info.bSupportsSeparateAlphaFunction = device_caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND; // Dual source blend disabled by default until a proper method to test for support is found g_Config.backend_info.bSupportsDualSourceBlend = false; @@ -183,6 +185,7 @@ void VideoBackend::Video_Prepare() // VideoCommon BPInit(); Fifo_Init(); + IndexGenerator::Init(); VertexLoaderManager::Init(); OpcodeDecoder_Init(); VertexShaderManager::Init(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 78e59644a4..d6c161614e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -338,6 +338,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; + g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1 || GLEW_NV_primitive_restart; g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; @@ -345,6 +346,7 @@ Renderer::Renderer() g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex; g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage; g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading; + g_ogl_config.bSupportOGL31 = GLEW_VERSION_3_1; g_ogl_config.gl_vendor = (const char*)glGetString(GL_VENDOR); g_ogl_config.gl_renderer = (const char*)glGetString(GL_RENDERER); @@ -397,9 +399,10 @@ Renderer::Renderer() g_ogl_config.gl_renderer, g_ogl_config.gl_version).c_str(), 5000); - WARN_LOG(VIDEO,"Missing OGL Extensions: %s%s%s%s%s%s%s%s", + WARN_LOG(VIDEO,"Missing OGL Extensions: %s%s%s%s%s%s%s%s%s", g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "" : "DualSourceBlend ", g_ActiveConfig.backend_info.bSupportsGLSLUBO ? "" : "UniformBuffer ", + g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? "" : "PrimitiveRestart ", g_ogl_config.bSupportsGLPinnedMemory ? "" : "PinnedMemory ", g_ogl_config.bSupportsGLSLCache ? "" : "ShaderCache ", g_ogl_config.bSupportsGLBaseVertex ? "" : "BaseVertex ", @@ -475,6 +478,20 @@ Renderer::Renderer() glScissor(0, 0, GetTargetWidth(), GetTargetHeight()); glBlendColor(0, 0, 0, 0.5f); glClearDepth(1.0f); + + if(g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) + { + if(g_ogl_config.bSupportOGL31) + { + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(65535); + } + else + { + glEnableClientState(GL_PRIMITIVE_RESTART_NV); + glPrimitiveRestartIndexNV(65535); + } + } UpdateActiveConfig(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h index 963c267b19..61e820dad4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h @@ -24,6 +24,7 @@ extern struct VideoConfig { bool bSupportCoverageMSAA; bool bSupportSampleShading; GLSL_VERSION eSupportedGLSLVersion; + bool bSupportOGL31; const char *gl_vendor; const char *gl_renderer; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 2d19b18020..04ba57eda1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -358,10 +358,10 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo (GLfloat)targetSource.left, (GLfloat)targetSource.bottom, -1.f, -1.f, (GLfloat)targetSource.left, (GLfloat)targetSource.top, - 1.f, -1.f, - (GLfloat)targetSource.right, (GLfloat)targetSource.top, 1.f, 1.f, - (GLfloat)targetSource.right, (GLfloat)targetSource.bottom + (GLfloat)targetSource.right, (GLfloat)targetSource.bottom, + 1.f, -1.f, + (GLfloat)targetSource.right, (GLfloat)targetSource.top }; glBindBuffer(GL_ARRAY_BUFFER, vbo_it->second.vbo); @@ -371,7 +371,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo } glBindVertexArray(vbo_it->second.vao); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index 1059e90b35..cd738c7026 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -250,10 +250,10 @@ void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc, (float)sourceRc.left, (float)sourceRc.top, -1.f, 1.f, (float)sourceRc.left, (float)sourceRc.bottom, - 1.f, 1.f, - (float)sourceRc.right, (float)sourceRc.bottom, 1.f, -1.f, - (float)sourceRc.right, (float)sourceRc.top + (float)sourceRc.right, (float)sourceRc.top, + 1.f, 1.f, + (float)sourceRc.right, (float)sourceRc.bottom }; glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO ); glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW); @@ -262,7 +262,7 @@ void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc, } glBindVertexArray( s_encode_VAO ); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); @@ -426,10 +426,10 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRender (float)srcFmtWidth, (float)srcHeight, 1.f, 1.f, (float)srcFmtWidth, 0.f, - -1.f, 1.f, - 0.f, 0.f, -1.f, -1.f, - 0.f, (float)srcHeight + 0.f, (float)srcHeight, + -1.f, 1.f, + 0.f, 0.f }; glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO ); @@ -440,7 +440,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRender } glBindVertexArray( s_decode_VAO ); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); GL_REPORT_ERRORD(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 5e8a10c8d9..333d0b5550 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -124,10 +124,12 @@ void VertexManager::Draw(u32 stride) u32 triangle_index_size = IndexGenerator::GetTriangleindexLen(); u32 line_index_size = IndexGenerator::GetLineindexLen(); u32 point_index_size = IndexGenerator::GetPointindexLen(); + GLenum triangle_mode = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart?GL_TRIANGLE_STRIP:GL_TRIANGLES; + if(g_ogl_config.bSupportsGLBaseVertex) { if (triangle_index_size > 0) { - glDrawElementsBaseVertex(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); + glDrawElementsBaseVertex(triangle_mode, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) @@ -143,7 +145,7 @@ void VertexManager::Draw(u32 stride) } else { if (triangle_index_size > 0) { - glDrawElements(GL_TRIANGLES, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); + glDrawElements(triangle_mode, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0]); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 8e293cb820..b1720789d1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -96,6 +96,7 @@ Make AA apply instantly during gameplay if possible #include "PerfQuery.h" #include "VideoState.h" +#include "IndexGenerator.h" #include "VideoBackend.h" #include "ConfigManager.h" @@ -199,6 +200,7 @@ void VideoBackend::Video_Prepare() g_perf_query = new PerfQuery; Fifo_Init(); // must be done before OpcodeDecoder_Init() OpcodeDecoder_Init(); + IndexGenerator::Init(); VertexShaderManager::Init(); PixelShaderManager::Init(); ProgramShaderCache::Init();