diff options
| author | Matthew Parlane <parlane@gmail.com> | 2013-01-01 23:28:46 +1300 |
|---|---|---|
| committer | Matthew Parlane <parlane@gmail.com> | 2013-01-01 23:28:46 +1300 |
| commit | e0c9a1fd09b9be953bf0ae41b9014485e750b07e (patch) | |
| tree | 059744e17a2a35ca58dd9b817cab620faee38611 /Source/Core/VideoCommon | |
| parent | fe1fdc5e7b957312c906324134e42ca3484fa2d5 (diff) | |
| parent | c728ef2cd30ef803210d5db0a1ecab6b198a2c65 (diff) | |
Merge branch 'master' into wii-network
Conflicts:
Source/Core/Common/Src/CommonPaths.h
Source/Core/Core/CMakeLists.txt
Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp
Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp
Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp
Diffstat (limited to 'Source/Core/VideoCommon')
42 files changed, 1059 insertions, 517 deletions
diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index d0e28f571c..6ed8e29c6b 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -6,6 +6,7 @@ set(SRCS Src/BPFunctions.cpp Src/DLCache.cpp Src/Debugger.cpp Src/Fifo.cpp + Src/FPSCounter.cpp Src/FramebufferManagerBase.cpp Src/HiresTextures.cpp Src/ImageWrite.cpp diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp index 4c31798d9f..c172903b5d 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.cpp +++ b/Source/Core/VideoCommon/Src/AVIDump.cpp @@ -252,7 +252,7 @@ bool AVIDump::CreateFile() File::CreateFullPath(s_FormatContext->filename); if (!(s_FormatContext->oformat = av_guess_format("avi", NULL, NULL)) || - !(s_Stream = av_new_stream(s_FormatContext, 0))) + !(s_Stream = avformat_new_stream(s_FormatContext, codec))) { CloseFile(); return false; @@ -269,7 +269,7 @@ bool AVIDump::CreateFile() s_Stream->codec->pix_fmt = g_Config.bUseFFV1 ? PIX_FMT_BGRA : PIX_FMT_YUV420P; if (!(codec = avcodec_find_encoder(s_Stream->codec->codec_id)) || - (avcodec_open(s_Stream->codec, codec) < 0)) + (avcodec_open2(s_Stream->codec, codec, NULL) < 0)) { CloseFile(); return false; diff --git a/Source/Core/VideoCommon/Src/BPFunctions.cpp b/Source/Core/VideoCommon/Src/BPFunctions.cpp index 4f7315e832..b9a76ba7b6 100644 --- a/Source/Core/VideoCommon/Src/BPFunctions.cpp +++ b/Source/Core/VideoCommon/Src/BPFunctions.cpp @@ -39,7 +39,7 @@ void FlushPipeline() VertexManager::Flush(); } -void SetGenerationMode(const BPCmd &bp) +void SetGenerationMode() { g_renderer->SetGenerationMode(); } @@ -62,32 +62,34 @@ void SetScissor() TargetRectangle trc = g_renderer->ConvertEFBRectangle(rc); g_renderer->SetScissorRect(trc); + + UpdateViewportWithCorrection(); } -void SetLineWidth(const BPCmd &bp) +void SetLineWidth() { g_renderer->SetLineWidth(); } -void SetDepthMode(const BPCmd &bp) +void SetDepthMode() { g_renderer->SetDepthMode(); } -void SetBlendMode(const BPCmd &bp) +void SetBlendMode() { g_renderer->SetBlendMode(false); } -void SetDitherMode(const BPCmd &bp) +void SetDitherMode() { g_renderer->SetDitherMode(); } -void SetLogicOpMode(const BPCmd &bp) +void SetLogicOpMode() { g_renderer->SetLogicOpMode(); } -void SetColorMask(const BPCmd &bp) +void SetColorMask() { g_renderer->SetColorMask(); } @@ -119,7 +121,7 @@ void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, - convert the RGBA8 color to RGBA6/RGB8/RGB565 and convert it to RGBA8 again - convert the Z24 depth value to Z16 and back to Z24 */ -void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) +void ClearScreen(const EFBRectangle &rc) { bool colorEnable = bpmem.blendmode.colorupdate; bool alphaEnable = bpmem.blendmode.alphaupdate; @@ -152,7 +154,7 @@ void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) } } -void OnPixelFormatChange(const BPCmd &bp) +void OnPixelFormatChange() { int convtype = -1; @@ -234,7 +236,7 @@ bool GetConfig(const int &type) case CONFIG_DISABLEFOG: return g_ActiveConfig.bDisableFog; case CONFIG_SHOWEFBREGIONS: - return false; + return g_ActiveConfig.bShowEFBCopyRegions; default: PanicAlert("GetConfig Error: Unknown Config Type!"); return false; diff --git a/Source/Core/VideoCommon/Src/BPFunctions.h b/Source/Core/VideoCommon/Src/BPFunctions.h index 2b86523687..e7a8b0aeb4 100644 --- a/Source/Core/VideoCommon/Src/BPFunctions.h +++ b/Source/Core/VideoCommon/Src/BPFunctions.h @@ -37,18 +37,18 @@ enum }; void FlushPipeline(); -void SetGenerationMode(const BPCmd &bp); +void SetGenerationMode(); void SetScissor(); -void SetLineWidth(const BPCmd &bp); -void SetDepthMode(const BPCmd &bp); -void SetBlendMode(const BPCmd &bp); -void SetDitherMode(const BPCmd &bp); -void SetLogicOpMode(const BPCmd &bp); -void SetColorMask(const BPCmd &bp); +void SetLineWidth(); +void SetDepthMode(); +void SetBlendMode(); +void SetDitherMode(); +void SetLogicOpMode(); +void SetColorMask(); void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); -void ClearScreen(const BPCmd &bp, const EFBRectangle &rc); -void OnPixelFormatChange(const BPCmd &bp); +void ClearScreen(const EFBRectangle &rc); +void OnPixelFormatChange(); u8 *GetPointer(const u32 &address); bool GetConfig(const int &type); void SetTextureMode(const BPCmd &bp); diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp index d5b762c1a4..c452b238b6 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.cpp +++ b/Source/Core/VideoCommon/Src/BPMemory.cpp @@ -43,31 +43,6 @@ void LoadBPReg(u32 value0) BPWritten(bp); } -// Called when loading a saved state. -// Needs more testing though. -void BPReload() -{ - for (int i = 0; i < 254; i++) - { - switch (i) - { - case BPMEM_BLENDMODE: - case BPMEM_SETDRAWDONE: - case BPMEM_TRIGGER_EFB_COPY: - case BPMEM_LOADTLUT1: - case BPMEM_PERF1: - case BPMEM_PE_TOKEN_ID: - case BPMEM_PE_TOKEN_INT_ID: - // Cases in which we DON'T want to reload the BP - continue; - default: - BPCmd bp = {i, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[i])}; - BPWritten(bp); - } - } -} - - void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size) { const char* no_yes[2] = { "No", "Yes" }; diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index d59523e117..0bde9cc613 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -34,9 +34,9 @@ using namespace BPFunctions; -u32 mapTexAddress; -bool mapTexFound; -int numWrites; +static u32 mapTexAddress; +static bool mapTexFound; +static int numWrites; extern volatile bool g_bSkipCurrentFrame; @@ -81,6 +81,9 @@ void BPWritten(const BPCmd& bp) just stuff geometry in them and don't put state changes there ---------------------------------------------------------------------------------------------------------------- */ + + // check for invalid state, else unneeded configuration are built + g_video_backend->CheckInvalidState(); // Debugging only, this lets you skip a bp update //static int times = 0; @@ -128,7 +131,27 @@ void BPWritten(const BPCmd& bp) FlushPipeline(); } } // END ZTP SPEEDUP HACK - else FlushPipeline(); + else + { + if (((s32*)&bpmem)[bp.address] == bp.newvalue) + { + if (!(bp.address == BPMEM_TRIGGER_EFB_COPY + || bp.address == BPMEM_CLEARBBOX1 + || bp.address == BPMEM_CLEARBBOX2 + || bp.address == BPMEM_SETDRAWDONE + || bp.address == BPMEM_PE_TOKEN_ID + || bp.address == BPMEM_PE_TOKEN_INT_ID + || bp.address == BPMEM_LOADTLUT0 + || bp.address == BPMEM_LOADTLUT1 + || bp.address == BPMEM_TEXINVALIDATE + || bp.address == BPMEM_PRELOAD_MODE)) + { + return; + } + } + + FlushPipeline(); + } ((u32*)&bpmem)[bp.address] = bp.newvalue; @@ -140,7 +163,7 @@ void BPWritten(const BPCmd& bp) bpmem.genMode.numtexgens, bpmem.genMode.numcolchans, bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode, bpmem.genMode.numindstages, bpmem.genMode.zfreeze); - SetGenerationMode(bp); + SetGenerationMode(); break; } case BPMEM_IND_MTXA: // Index Matrix Changed @@ -168,12 +191,12 @@ void BPWritten(const BPCmd& bp) SetScissor(); break; case BPMEM_LINEPTWIDTH: // Line Width - SetLineWidth(bp); + SetLineWidth(); break; case BPMEM_ZMODE: // Depth Control PRIM_LOG("zmode: test=%d, func=%d, upd=%d", bpmem.zmode.testenable, bpmem.zmode.func, bpmem.zmode.updateenable); - SetDepthMode(bp); + SetDepthMode(); break; case BPMEM_BLENDMODE: // Blending Control { @@ -184,16 +207,16 @@ void BPWritten(const BPCmd& bp) bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode); // Set LogicOp Blending Mode if (bp.changes & 2) - SetLogicOpMode(bp); + SetLogicOpMode(); // Set Dithering Mode if (bp.changes & 4) - SetDitherMode(bp); + SetDitherMode(); // Set Blending Mode if (bp.changes & 0xFE1) - SetBlendMode(bp); + SetBlendMode(); // Set Color Mask if (bp.changes & 0x18) - SetColorMask(bp); + SetColorMask(); } break; } @@ -286,7 +309,7 @@ void BPWritten(const BPCmd& bp) // Clear the rectangular region after copying it. if (PE_copy.clear) { - ClearScreen(bp, rc); + ClearScreen(rc); } break; @@ -311,8 +334,6 @@ void BPWritten(const BPCmd& bp) else PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5); - // TODO(ector) : kill all textures that use this palette - // Not sure if it's a good idea, though. For now, we hash texture palettes break; } case BPMEM_FOGRANGE: // Fog Settings Control @@ -429,13 +450,13 @@ void BPWritten(const BPCmd& bp) } } break; - case BPMEM_TEXINVALIDATE: // Used, if game has manual control the Texture Cache, which we don't allow - DEBUG_LOG(VIDEO, "BP Texture Invalid: %08x", bp.newvalue); + case BPMEM_TEXINVALIDATE: + // TODO: Needs some restructuring in TextureCacheBase. break; case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel - OnPixelFormatChange(bp); + OnPixelFormatChange(); break; case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel @@ -473,7 +494,7 @@ void BPWritten(const BPCmd& bp) break; case BPMEM_PRELOAD_MODE: // Set to 0 when GX_TexModeSync() is called. - // if this is different from 0, manual TMEM management is used. + // if this is different from 0, manual TMEM management is used (GX_PreloadEntireTexture). if (bp.newvalue != 0) { // NOTE(neobrain): Apparently tmemodd doesn't affect hardware behavior at all (libogc uses it just as a buffer and switches its contents with tmemeven whenever this is called) @@ -484,7 +505,6 @@ void BPWritten(const BPCmd& bp) // Check if the game has overflowed TMEM, and copy up to the limit. // Paper Mario does this when entering the Great Boogly Tree (Chap 2) - // TODO: Does this wrap? if ((tmem_addr + size) > TMEM_SIZE) size = TMEM_SIZE - tmem_addr; @@ -660,3 +680,35 @@ void BPWritten(const BPCmd& bp) } } +// Called when loading a saved state. +void BPReload() +{ + // restore anything that goes straight to the renderer. + // let's not risk actually replaying any writes. + // note that PixelShaderManager is already covered since it has its own DoState. + SetGenerationMode(); + SetScissor(); + SetLineWidth(); + SetDepthMode(); + SetLogicOpMode(); + SetDitherMode(); + SetBlendMode(); + SetColorMask(); + OnPixelFormatChange(); + { + BPCmd bp = {BPMEM_TX_SETMODE0, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0])}; + SetTextureMode(bp); + } + { + BPCmd bp = {BPMEM_TX_SETMODE0_4, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0_4])}; + SetTextureMode(bp); + } + { + BPCmd bp = {BPMEM_FIELDMASK, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMASK])}; + SetInterlacingMode(bp); + } + { + BPCmd bp = {BPMEM_FIELDMODE, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMODE])}; + SetInterlacingMode(bp); + } +} diff --git a/Source/Core/VideoCommon/Src/DLCache.cpp b/Source/Core/VideoCommon/Src/DLCache.cpp index 5499fa26f1..c828ea3a03 100644 --- a/Source/Core/VideoCommon/Src/DLCache.cpp +++ b/Source/Core/VideoCommon/Src/DLCache.cpp @@ -361,9 +361,9 @@ u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl) (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices); num_draw_call++; - const int tc[12] = { + const u32 tc[12] = { g_VtxDesc.Position, g_VtxDesc.Normal, g_VtxDesc.Color0, g_VtxDesc.Color1, g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, - g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const int)((g_VtxDesc.Hex >> 31) & 3) + g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3) }; for(int i = 0; i < 12; i++) { @@ -563,9 +563,9 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl) dl->InsertRegion(NewRegion); memcpy(NewRegion->start_address, StartAddress, Vdatasize); emitter.ABI_CallFunctionCCCP((void *)&VertexLoaderManager::RunCompiledVertices, cmd_byte & GX_VAT_MASK, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices, NewRegion->start_address); - const int tc[12] = { + const u32 tc[12] = { g_VtxDesc.Position, g_VtxDesc.Normal, g_VtxDesc.Color0, g_VtxDesc.Color1, g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, - g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const int)((g_VtxDesc.Hex >> 31) & 3) + g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord, g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3) }; for(int i = 0; i < 12; i++) { diff --git a/Source/Core/VideoCommon/Src/Debugger.h b/Source/Core/VideoCommon/Src/Debugger.h index bcce50f223..fde31e4268 100644 --- a/Source/Core/VideoCommon/Src/Debugger.h +++ b/Source/Core/VideoCommon/Src/Debugger.h @@ -72,21 +72,9 @@ void GFXDebuggerCheckAndPause(bool update); void GFXDebuggerToPause(bool update); void GFXDebuggerUpdateScreen(); -#undef ENABLE_GFX_DEBUGGER -#if defined(_DEBUG) || defined(DEBUGFAST) -#define ENABLE_GFX_DEBUGGER -#endif - -#ifdef ENABLE_GFX_DEBUGGER #define GFX_DEBUGGER_PAUSE_AT(event,update) {if (((GFXDebuggerToPauseAtNext & event) && --GFXDebuggerEventToPauseCount<=0) || GFXDebuggerPauseFlag) GFXDebuggerToPause(update);} #define GFX_DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc) {if (((GFXDebuggerToPauseAtNext & event) && --GFXDebuggerEventToPauseCount<=0) || GFXDebuggerPauseFlag) {{dumpfunc};GFXDebuggerToPause(update);}} #define GFX_DEBUGGER_LOG_AT(event,dumpfunc) {if (( GFXDebuggerToPauseAtNext & event ) ) {{dumpfunc};}} -#else -// Disable debugging calls in Release build -#define GFX_DEBUGGER_PAUSE_AT(event,update) -#define GFX_DEBUGGER_PAUSE_LOG_AT(event,update,dumpfunc) -#define GFX_DEBUGGER_LOG_AT(event,dumpfunc) -#endif // ENABLE_GFX_DEBUGGER #endif // _GFX_DEBUGGER_H_ diff --git a/Source/Core/VideoCommon/Src/EmuWindow.cpp b/Source/Core/VideoCommon/Src/EmuWindow.cpp index 30dca24cb1..cbb0bc31ac 100644 --- a/Source/Core/VideoCommon/Src/EmuWindow.cpp +++ b/Source/Core/VideoCommon/Src/EmuWindow.cpp @@ -251,7 +251,7 @@ void OSDMenu(WPARAM wParam) OSDChoice = 1; // Toggle native resolution g_Config.iEFBScale = g_Config.iEFBScale + 1; - if (g_Config.iEFBScale > 4) g_Config.iEFBScale = 0; + if (g_Config.iEFBScale > 7) g_Config.iEFBScale = 0; break; case '4': OSDChoice = 2; @@ -280,11 +280,6 @@ void OSDMenu(WPARAM wParam) OSDChoice = 4; g_Config.bDisableFog = !g_Config.bDisableFog; break; - case '7': - // TODO: Not implemented in the D3D backends, yet - OSDChoice = 5; - g_Config.bDisableLighting = !g_Config.bDisableLighting; - break; } } diff --git a/Source/Core/VideoCommon/Src/FPSCounter.cpp b/Source/Core/VideoCommon/Src/FPSCounter.cpp new file mode 100644 index 0000000000..ea3f624c73 --- /dev/null +++ b/Source/Core/VideoCommon/Src/FPSCounter.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "FPSCounter.h" +#include "FileUtil.h" +#include "Timer.h" +#include "VideoConfig.h" + +#define FPS_REFRESH_INTERVAL 1000 + +static unsigned int s_counter = 0; +static unsigned int s_fps = 0; +static unsigned int s_fps_last_counter = 0; +static unsigned long s_last_update_time = 0; +static File::IOFile s_bench_file; + +void InitFPSCounter() +{ + s_counter = s_fps_last_counter = 0; + s_fps = 0; + s_last_update_time = Common::Timer::GetTimeMs(); + + if (s_bench_file.IsOpen()) + s_bench_file.Close(); +} + +static void LogFPSToFile(unsigned long val) +{ + if (!s_bench_file.IsOpen()) + s_bench_file.Open(File::GetUserPath(D_LOGS_IDX) + "fps.txt", "w"); + + char buffer[256]; + snprintf(buffer, 256, "%ld\n", val); + s_bench_file.WriteArray(buffer, strlen(buffer)); +} + +int UpdateFPSCounter() +{ + if (Common::Timer::GetTimeMs() - s_last_update_time >= FPS_REFRESH_INTERVAL) + { + s_last_update_time = Common::Timer::GetTimeMs(); + s_fps = s_counter - s_fps_last_counter; + s_fps_last_counter = s_counter; + if (g_ActiveConfig.bLogFPSToFile) + LogFPSToFile(s_fps); + } + + s_counter++; + return s_fps; +}
\ No newline at end of file diff --git a/Source/Core/VideoCommon/Src/FPSCounter.h b/Source/Core/VideoCommon/Src/FPSCounter.h new file mode 100644 index 0000000000..314f4b0fc7 --- /dev/null +++ b/Source/Core/VideoCommon/Src/FPSCounter.h @@ -0,0 +1,28 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _FPS_COUNTER_H_ +#define _FPS_COUNTER_H_ + +// Initializes the FPS counter. +void InitFPSCounter(); + +// Called when a frame is rendered. Returns the value to be displayed on +// screen as the FPS counter (updated every second). +int UpdateFPSCounter(); + +#endif // _FPS_COUNTER_H_
\ No newline at end of file diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 2e60055c97..50aa21ebbf 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -16,7 +16,6 @@ // http://code.google.com/p/dolphin-emu/ #include "VideoConfig.h" -#include "Setup.h" #include "MemoryUtil.h" #include "Thread.h" #include "Atomic.h" @@ -26,6 +25,7 @@ #include "ChunkFile.h" #include "Fifo.h" #include "HW/Memmap.h" +#include "Core.h" volatile bool g_bSkipCurrentFrame = false; extern u8* g_pVideoData; @@ -34,22 +34,39 @@ namespace { static volatile bool GpuRunningState = false; static volatile bool EmuRunningState = false; -static u8 *videoBuffer; +static std::mutex m_csHWVidOccupied; // STATE_TO_SAVE +static u8 *videoBuffer; static int size = 0; } // namespace void Fifo_DoState(PointerWrap &p) { - p.DoArray(videoBuffer, FIFO_SIZE); p.Do(size); - int pos = (int)(g_pVideoData - videoBuffer); // get offset - p.Do(pos); // read or write offset (depends on the mode afaik) - g_pVideoData = &videoBuffer[pos]; // overwrite g_pVideoData -> expected no change when load ss and change when save ss + p.DoPointer(g_pVideoData, videoBuffer); + p.Do(g_bSkipCurrentFrame); +} +void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock) +{ + if (doLock) + { + EmulatorState(false); + if (!Core::IsGPUThread()) + m_csHWVidOccupied.lock(); + _dbg_assert_(COMMON, !CommandProcessor::fifo.isGpuReadingData); + } + else + { + if (unpauseOnUnlock) + EmulatorState(true); + if (!Core::IsGPUThread()) + m_csHWVidOccupied.unlock(); + } } + void Fifo_Init() { videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE); @@ -127,6 +144,7 @@ void ResetVideoBuffer() // Purpose: Keep the Core HW updated about the CPU-GPU distance void RunGpuLoop() { + std::lock_guard<std::mutex> lk(m_csHWVidOccupied); GpuRunningState = true; SCPFifoStruct &fifo = CommandProcessor::fifo; @@ -178,12 +196,13 @@ void RunGpuLoop() Common::YieldCPU(); else { - // While the emu is paused, we still handle async request such as Savestates then sleep. + // While the emu is paused, we still handle async requests then sleep. while (!EmuRunningState) { g_video_backend->PeekMessages(); - VideoFifo_CheckStateRequest(); + m_csHWVidOccupied.unlock(); Common::SleepCurrentThread(1); + m_csHWVidOccupied.lock(); } } } diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h index e73434a19f..75e7d782f5 100644 --- a/Source/Core/VideoCommon/Src/Fifo.h +++ b/Source/Core/VideoCommon/Src/Fifo.h @@ -30,7 +30,9 @@ extern volatile bool g_bSkipCurrentFrame; void Fifo_Init(); void Fifo_Shutdown(); + void Fifo_DoState(PointerWrap &f); +void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock); void ReadDataFromFifo(u8* _uData, u32 len); @@ -45,6 +47,5 @@ void Fifo_SetRendering(bool bEnabled); // Implemented by the Video Backend void VideoFifo_CheckAsyncRequest(); -void VideoFifo_CheckStateRequest(); #endif // _FIFO_H diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp index b234a7c865..c883714daf 100644 --- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.cpp @@ -10,6 +10,9 @@ XFBSourceBase *FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_XFB]; +unsigned int FramebufferManagerBase::s_last_xfb_width = 1; +unsigned int FramebufferManagerBase::s_last_xfb_height = 1; + FramebufferManagerBase::FramebufferManagerBase() { m_realXFBSource = NULL; @@ -226,3 +229,31 @@ void FramebufferManagerBase::ReplaceVirtualXFB() } } } + +int FramebufferManagerBase::ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width) +{ + if (g_ActiveConfig.RealXFBEnabled()) + return x; + + if (g_ActiveConfig.b3DVision) + { + // This works, yet the version in the else doesn't. No idea why. + return x * (int)backbuffer_width / (int)FramebufferManagerBase::LastXfbWidth(); + } + else + return x * (int)Renderer::GetTargetRectangle().GetWidth() / (int)FramebufferManagerBase::LastXfbWidth(); +} + +int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height) +{ + if (g_ActiveConfig.RealXFBEnabled()) + return y; + + if (g_ActiveConfig.b3DVision) + { + // This works, yet the version in the else doesn't. No idea why. + return y * (int)backbuffer_height / (int)FramebufferManagerBase::LastXfbHeight(); + } + else + return y * (int)Renderer::GetTargetRectangle().GetHeight() / (int)FramebufferManagerBase::LastXfbHeight(); +} diff --git a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h index 26d360647d..e529bb1a39 100644 --- a/Source/Core/VideoCommon/Src/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/Src/FramebufferManagerBase.h @@ -50,6 +50,14 @@ public: static void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma); static const XFBSourceBase* const* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32 &xfbCount); + static void SetLastXfbWidth(unsigned int width) { s_last_xfb_width = width; } + static void SetLastXfbHeight(unsigned int height) { s_last_xfb_height = height; } + static unsigned int LastXfbWidth() { return s_last_xfb_width; } + static unsigned int LastXfbHeight() { return s_last_xfb_height; } + + static int ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width); + static int ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height); + protected: struct VirtualXFB { @@ -85,6 +93,9 @@ private: static VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode static const XFBSourceBase* m_overlappingXFBArray[MAX_VIRTUAL_XFB]; + + static unsigned int s_last_xfb_width; + static unsigned int s_last_xfb_height; }; extern FramebufferManagerBase *g_framebuffer_manager; diff --git a/Source/Core/VideoCommon/Src/HiresTextures.cpp b/Source/Core/VideoCommon/Src/HiresTextures.cpp index 50e8a194af..5a3fb051c3 100644 --- a/Source/Core/VideoCommon/Src/HiresTextures.cpp +++ b/Source/Core/VideoCommon/Src/HiresTextures.cpp @@ -90,10 +90,15 @@ void Init(const char *gameCode) } } -PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, int texformat, u8 *data) +bool HiresTexExists(const char* filename) { - std::string key(fileName); + std::string key(filename); + return textureMap.find(key) != textureMap.end(); +} +PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, unsigned int *required_size, int texformat, unsigned int data_size, u8 *data) +{ + std::string key(fileName); if (textureMap.find(key) == textureMap.end()) return PC_TEX_FMT_NONE; @@ -102,23 +107,17 @@ PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned in int channels; u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA); - if (temp == NULL) { ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str()); - SOIL_free_image_data(temp); return PC_TEX_FMT_NONE; } - if (width > 2048 || height > 2048) - { - ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 2048 pixels tall and wide", textureMap[key].c_str(), width, height); - SOIL_free_image_data(temp); - return PC_TEX_FMT_NONE; - } + *pWidth = width; + *pHeight = height; int offset = 0; - PC_TexFormat returnTex; + PC_TexFormat returnTex = PC_TEX_FMT_NONE; switch (texformat) { @@ -126,24 +125,32 @@ PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned in case GX_TF_I8: case GX_TF_IA4: case GX_TF_IA8: + *required_size = width * height * 8; + if (data_size < *required_size) + goto cleanup; + for (int i = 0; i < width * height * 4; i += 4) { // Rather than use a luminosity function, just use the most intense color for luminance + // TODO(neobrain): Isn't this kind of.. stupid? data[offset++] = *std::max_element(temp+i, temp+i+3); data[offset++] = temp[i+3]; } returnTex = PC_TEX_FMT_IA8; break; default: + *required_size = width * height * 4; + if (data_size < *required_size) + goto cleanup; + memcpy(data, temp, width * height * 4); returnTex = PC_TEX_FMT_RGBA32; break; } - *pWidth = width; - *pHeight = height; - SOIL_free_image_data(temp); INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str()); +cleanup: + SOIL_free_image_data(temp); return returnTex; } diff --git a/Source/Core/VideoCommon/Src/HiresTextures.h b/Source/Core/VideoCommon/Src/HiresTextures.h index 409c2cc260..4b0db76fd9 100644 --- a/Source/Core/VideoCommon/Src/HiresTextures.h +++ b/Source/Core/VideoCommon/Src/HiresTextures.h @@ -25,7 +25,8 @@ namespace HiresTextures { void Init(const char *gameCode); -PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, int texformat, u8 *data); +bool HiresTexExists(const char *filename); +PC_TexFormat GetHiresTex(const char *fileName, unsigned int *pWidth, unsigned int *pHeight, unsigned int *required_size, int texformat, unsigned int data_size, u8 *data); }; diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index 0b1258a662..726ef71b38 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -169,8 +169,7 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 return 0; } -static volatile u32 s_doStateRequested = false; - + void VideoBackendHardware::InitializeShared() { VideoCommon_Init(); @@ -181,54 +180,50 @@ void VideoBackendHardware::InitializeShared() memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs)); memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs)); s_AccessEFBResult = 0; + m_invalid = false; } -static volatile struct -{ - unsigned char **ptr; - int mode; -} s_doStateArgs; - -// Depending on the threading mode (DC/SC) this can be called -// from either the GPU thread or the CPU thread -void VideoFifo_CheckStateRequest() +// Run from the CPU thread +void VideoBackendHardware::DoState(PointerWrap& p) { - if (Common::AtomicLoadAcquire(s_doStateRequested)) + VideoCommon_DoState(p); + p.DoMarker("VideoCommon"); + + p.Do(s_swapRequested); + p.Do(s_efbAccessRequested); + p.Do(s_beginFieldArgs); + p.Do(s_accessEFBArgs); + p.Do(s_AccessEFBResult); + p.DoMarker("VideoBackendHardware"); + + // Refresh state. + if (p.GetMode() == PointerWrap::MODE_READ) { + m_invalid = true; + RecomputeCachedArraybases(); + // Clear all caches that touch RAM - TextureCache::Invalidate(false); + // (? these don't appear to touch any emulation state that gets saved. moved to on load only.) VertexLoaderManager::MarkAllDirty(); - - PointerWrap p(s_doStateArgs.ptr, s_doStateArgs.mode); - VideoCommon_DoState(p); - - // Refresh state. - if (s_doStateArgs.mode == PointerWrap::MODE_READ) - { - BPReload(); - RecomputeCachedArraybases(); - } - - Common::AtomicStoreRelease(s_doStateRequested, false); } } -// Run from the CPU thread -void VideoBackendHardware::DoState(PointerWrap& p) -{ - s_doStateArgs.ptr = p.ptr; - s_doStateArgs.mode = p.mode; - Common::AtomicStoreRelease(s_doStateRequested, true); - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) +void VideoBackendHardware::CheckInvalidState() { + if (m_invalid) { - while (Common::AtomicLoadAcquire(s_doStateRequested) && !s_FifoShuttingDown) - //Common::SleepCurrentThread(1); - Common::YieldCPU(); + m_invalid = false; + + BPReload(); + TextureCache::Invalidate(); } - else - VideoFifo_CheckStateRequest(); } +void VideoBackendHardware::PauseAndLock(bool doLock, bool unpauseOnUnlock) +{ + Fifo_PauseAndLock(doLock, unpauseOnUnlock); +} + + void VideoBackendHardware::RunLoop(bool enable) { VideoCommon_RunLoop(enable); diff --git a/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp b/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp index f24bfc31b3..10cf5b84af 100644 --- a/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp +++ b/Source/Core/VideoCommon/Src/OnScreenDisplay.cpp @@ -19,6 +19,7 @@ #include "Common.h" +#include "ConfigManager.h" #include "OnScreenDisplay.h" #include "RenderBase.h" #include "Timer.h" @@ -47,6 +48,8 @@ void AddMessage(const char* pstr, u32 ms) void DrawMessages() { + if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bOnScreenDisplayMessages) return; + if (s_listMsgs.size() > 0) { int left = 25, top = 15; diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp index 18d6726ae3..4f7f86d655 100644 --- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp @@ -439,7 +439,8 @@ void OpcodeDecoder_Init() #if _M_SSE >= 0x301 if (cpu_info.bSSSE3) { - *DataReadU32xFuncs = *DataReadU32xFuncs_SSSE3; + for (int i = 0; i < 16; ++i) + DataReadU32xFuncs[i] = DataReadU32xFuncs_SSSE3[i]; } #endif diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 03a3a7547a..a488e52b42 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -367,8 +367,6 @@ void UpdateFinishInterrupt(bool active) { ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active); interruptSetFinish = active; - if (active) - State::ProcessRequestedStates(0); } // TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate). diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 7500997fef..cc48276253 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -129,15 +129,11 @@ void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 compo return; } + // numtexgens should be <= 8 for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i) - { - if (18+i < 32) - uid->values[0] |= xfregs.texMtxInfo[i].projection << (18+i); // 1 - else - uid->values[1] |= xfregs.texMtxInfo[i].projection << (i - 14); // 1 - } + uid->values[0] |= xfregs.texMtxInfo[i].projection << (18+i); // 1 - uid->values[1] = bpmem.genMode.numindstages << 2; // 3 + uid->values[1] = bpmem.genMode.numindstages; // 3 u32 indirectStagesUsed = 0; for (unsigned int i = 0; i < bpmem.genMode.numindstages; ++i) if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) @@ -145,20 +141,20 @@ void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 compo assert(indirectStagesUsed == (indirectStagesUsed & 0xF)); - uid->values[1] |= indirectStagesUsed << 5; // 4; + uid->values[1] |= indirectStagesUsed << 3; // 4; for (unsigned int i = 0; i < bpmem.genMode.numindstages; ++i) { if (indirectStagesUsed & (1 << i)) { - uid->values[1] |= (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) << (9 + 3*i); // 1 + uid->values[1] |= (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) << (7 + 3*i); // 1 if (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) - uid->values[1] |= bpmem.tevindref.getTexCoord(i) << (10 + 3*i); // 2 + uid->values[1] |= bpmem.tevindref.getTexCoord(i) << (8 + 3*i); // 2 } } u32* ptr = &uid->values[2]; - for (unsigned int i = 0; i < bpmem.genMode.numtevstages+1; ++i) + for (int i = 0; i < bpmem.genMode.numtevstages+1; ++i) { StageHash(i, ptr); ptr += 4; // max: ptr = &uid->values[66] @@ -487,6 +483,15 @@ static char swapModeTable[4][5]; static char text[16384]; static bool DepthTextureEnable; +struct RegisterState +{ + bool ColorNeedOverflowControl; + bool AlphaNeedOverflowControl; + bool AuxStored; +}; + +static RegisterState RegisterStates[4]; + static void BuildSwapModeTable() { static const char *swapColors = "rgba"; @@ -617,7 +622,6 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType } WRITE(p, " ) {\n"); - char* pmainstart = p; int Pretest = AlphaPreTest(); if(Pretest >= 0 && !DepthTextureEnable) { @@ -717,6 +721,16 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType } } + RegisterStates[0].AlphaNeedOverflowControl = false; + RegisterStates[0].ColorNeedOverflowControl = false; + RegisterStates[0].AuxStored = false; + for(int i = 1; i < 4; i++) + { + RegisterStates[i].AlphaNeedOverflowControl = true; + RegisterStates[i].ColorNeedOverflowControl = true; + RegisterStates[i].AuxStored = false; + } + for (int i = 0; i < numStages; i++) WriteStage(p, i, ApiType); //build the equation for this stage @@ -724,11 +738,22 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType { // The results of the last texenv stage are put onto the screen, // regardless of the used destination register - WRITE(p, "prev.rgb = %s;\n",tevCOutputTable[bpmem.combiners[numStages-1].colorC.dest]); - WRITE(p, "prev.a = %s;\n",tevAOutputTable[bpmem.combiners[numStages-1].alphaC.dest]); + if(bpmem.combiners[numStages - 1].colorC.dest != 0) + { + bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].AuxStored; + WRITE(p, "prev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]); + RegisterStates[0].ColorNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl; + } + if(bpmem.combiners[numStages - 1].alphaC.dest != 0) + { + bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AuxStored; + WRITE(p, "prev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]); + RegisterStates[0].AlphaNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl; + } } - // emulation of unsigned 8 overflow when casting - WRITE(p, "prev = frac(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + // emulation of unsigned 8 overflow when casting if needed + if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl) + WRITE(p, "prev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n"); if(Pretest == -1) { @@ -917,7 +942,6 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType) TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC; TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC; - // blah1 if(cc.a == TEVCOLORARG_RASA || cc.a == TEVCOLORARG_RASC || cc.b == TEVCOLORARG_RASA || cc.b == TEVCOLORARG_RASC || cc.c == TEVCOLORARG_RASA || cc.c == TEVCOLORARG_RASC @@ -950,7 +974,6 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType) WRITE(p, "textemp = float4(1.0f, 1.0f, 1.0f, 1.0f);\n"); - // blah2 if (cc.a == TEVCOLORARG_KONST || cc.b == TEVCOLORARG_KONST || cc.c == TEVCOLORARG_KONST || cc.d == TEVCOLORARG_KONST || ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST || ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST) { @@ -971,30 +994,78 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType) || cc.b == TEVCOLORARG_CPREV || cc.b == TEVCOLORARG_APREV || cc.c == TEVCOLORARG_CPREV || cc.c == TEVCOLORARG_APREV || ac.a == TEVALPHAARG_APREV || ac.b == TEVALPHAARG_APREV || ac.c == TEVALPHAARG_APREV) - WRITE(p, "cprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n"); - + { + if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl) + { + WRITE(p, "cprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + RegisterStates[0].AlphaNeedOverflowControl = false; + RegisterStates[0].ColorNeedOverflowControl = false; + } + else + { + WRITE(p, "cprev = prev;\n"); + } + RegisterStates[0].AuxStored = true; + } if(cc.a == TEVCOLORARG_C0 || cc.a == TEVCOLORARG_A0 || cc.b == TEVCOLORARG_C0 || cc.b == TEVCOLORARG_A0 || cc.c == TEVCOLORARG_C0 || cc.c == TEVCOLORARG_A0 || ac.a == TEVALPHAARG_A0 || ac.b == TEVALPHAARG_A0 || ac.c == TEVALPHAARG_A0) - WRITE(p, "cc0 = frac(c0 * (255.0f/256.0f)) * (256.0f/255.0f);\n"); - + { + if(RegisterStates[1].AlphaNeedOverflowControl || RegisterStates[1].ColorNeedOverflowControl) + { + WRITE(p, "cc0 = frac(c0 * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + RegisterStates[1].AlphaNeedOverflowControl = false; + RegisterStates[1].ColorNeedOverflowControl = false; + } + else + { + WRITE(p, "cc0 = c0;\n"); + } + RegisterStates[1].AuxStored = true; + } if(cc.a == TEVCOLORARG_C1 || cc.a == TEVCOLORARG_A1 || cc.b == TEVCOLORARG_C1 || cc.b == TEVCOLORARG_A1 || cc.c == TEVCOLORARG_C1 || cc.c == TEVCOLORARG_A1 || ac.a == TEVALPHAARG_A1 || ac.b == TEVALPHAARG_A1 || ac.c == TEVALPHAARG_A1) - WRITE(p, "cc1 = frac(c1 * (255.0f/256.0f)) * (256.0f/255.0f);\n"); - + { + if(RegisterStates[2].AlphaNeedOverflowControl || RegisterStates[2].ColorNeedOverflowControl) + { + WRITE(p, "cc1 = frac(c1 * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + RegisterStates[2].AlphaNeedOverflowControl = false; + RegisterStates[2].ColorNeedOverflowControl = false; + } + else + { + WRITE(p, "cc1 = c1;\n"); + } + RegisterStates[2].AuxStored = true; + } if(cc.a == TEVCOLORARG_C2 || cc.a == TEVCOLORARG_A2 || cc.b == TEVCOLORARG_C2 || cc.b == TEVCOLORARG_A2 || cc.c == TEVCOLORARG_C2 || cc.c == TEVCOLORARG_A2 || ac.a == TEVALPHAARG_A2 || ac.b == TEVALPHAARG_A2 || ac.c == TEVALPHAARG_A2) + { + if(RegisterStates[3].AlphaNeedOverflowControl || RegisterStates[3].ColorNeedOverflowControl) + { WRITE(p, "cc2 = frac(c2 * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + RegisterStates[3].AlphaNeedOverflowControl = false; + RegisterStates[3].ColorNeedOverflowControl = false; + } + else + { + WRITE(p, "cc2 = c2;\n"); + } + RegisterStates[3].AuxStored = true; + } + RegisterStates[cc.dest].ColorNeedOverflowControl = (cc.clamp == 0); + RegisterStates[cc.dest].AuxStored = false; + // combine the color channel WRITE(p, "// color combine\n"); if (cc.clamp) WRITE(p, "%s = saturate(", tevCOutputTable[cc.dest]); @@ -1042,8 +1113,11 @@ static void WriteStage(char *&p, int n, API_TYPE ApiType) WRITE(p, ")"); WRITE(p,";\n"); - WRITE(p, "// alpha combine\n"); + RegisterStates[ac.dest].AlphaNeedOverflowControl = (ac.clamp == 0); + RegisterStates[ac.dest].AuxStored = false; + // combine the alpha channel + WRITE(p, "// alpha combine\n"); if (ac.clamp) WRITE(p, "%s = saturate(", tevAOutputTable[ac.dest]); else diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp index 2521f80500..258ec04413 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp @@ -302,7 +302,7 @@ void PixelShaderManager::SetConstants() float GC_ALIGNED16(material[4]); float NormalizationCoef = 1 / 255.0f; - for (int i = 0; i < 4; ++i) + for (int i = 0; i < 2; ++i) { if (nMaterialsChanged & (1 << i)) { @@ -316,6 +316,21 @@ void PixelShaderManager::SetConstants() SetPSConstant4fv(C_PMATERIALS + i, material); } } + + for (int i = 0; i < 2; ++i) + { + if (nMaterialsChanged & (1 << (i + 2))) + { + u32 data = *(xfregs.matColor + i); + + material[0] = ((data >> 24) & 0xFF) * NormalizationCoef; + material[1] = ((data >> 16) & 0xFF) * NormalizationCoef; + material[2] = ((data >> 8) & 0xFF) * NormalizationCoef; + material[3] = ( data & 0xFF) * NormalizationCoef; + + SetPSConstant4fv(C_PMATERIALS + i + 2, material); + } + } nMaterialsChanged = 0; } @@ -465,3 +480,16 @@ void PixelShaderManager::SetMaterialColorChanged(int index) { nMaterialsChanged |= (1 << index); } + +void PixelShaderManager::DoState(PointerWrap &p) +{ + p.Do(lastRGBAfull); + p.Do(lastAlpha); + p.Do(lastTexDims); + p.Do(lastZBias); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + Dirty(); + } +} diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.h b/Source/Core/VideoCommon/Src/PixelShaderManager.h index 2d1c01cad6..a336287a6f 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.h +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.h @@ -22,6 +22,8 @@ #include "XFMemory.h" #include "PixelShaderGen.h" +class PointerWrap; + // The non-API dependent parts. class PixelShaderManager { @@ -30,6 +32,7 @@ public: static void Init(); static void Dirty(); static void Shutdown(); + static void DoState(PointerWrap &p); static void SetConstants(); // sets pixel shader constants diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index ef0fff57f7..577570c568 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -67,12 +67,7 @@ int Renderer::s_target_height; int Renderer::s_backbuffer_width; int Renderer::s_backbuffer_height; -// ratio of backbuffer size and render area size -float Renderer::xScale; -float Renderer::yScale; - -unsigned int Renderer::s_XFB_width; -unsigned int Renderer::s_XFB_height; +TargetRectangle Renderer::target_rc; int Renderer::s_LastEFBScale; @@ -81,10 +76,17 @@ bool Renderer::XFBWrited; bool Renderer::s_EnableDLCachingAfterRecording; unsigned int Renderer::prev_efb_format = (unsigned int)-1; +unsigned int Renderer::efb_scale_numeratorX = 1; +unsigned int Renderer::efb_scale_numeratorY = 1; +unsigned int Renderer::efb_scale_denominatorX = 1; +unsigned int Renderer::efb_scale_denominatorY = 1; +unsigned int Renderer::ssaa_multiplier = 1; + Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false) { UpdateActiveConfig(); + TextureCache::OnConfigChanged(g_ActiveConfig); #if defined _WIN32 || defined HAVE_LIBAV bAVIDumping = false; @@ -96,6 +98,8 @@ Renderer::~Renderer() // invalidate previous efb format prev_efb_format = (unsigned int)-1; + efb_scale_numeratorX = efb_scale_numeratorY = efb_scale_denominatorX = efb_scale_denominatorY = ssaa_multiplier = 1; + #if defined _WIN32 || defined HAVE_LIBAV if (g_ActiveConfig.bDumpFrames && bLastFrameDumped && bAVIDumping) AVIDump::Stop(); @@ -119,69 +123,117 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight); XFBWrited = true; - // XXX: Without the VI, how would we know what kind of field this is? So - // just use progressive. if (g_ActiveConfig.bUseXFB) { FramebufferManagerBase::CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc,Gamma); } else { + // XXX: Without the VI, how would we know what kind of field this is? So + // just use progressive. g_renderer->Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight,sourceRc,Gamma); Common::AtomicStoreRelease(s_swapRequested, false); } - - if (TextureCache::DeferredInvalidate) +} + +int Renderer::EFBToScaledX(int x) +{ + switch (g_ActiveConfig.iEFBScale) { - TextureCache::Invalidate(false); - } + case 0: // fractional + return (int)ssaa_multiplier * FramebufferManagerBase::ScaleToVirtualXfbWidth(x, s_backbuffer_width); + + default: + return x * (int)ssaa_multiplier * (int)efb_scale_numeratorX / (int)efb_scale_denominatorX; + }; } -void Renderer::CalculateTargetScale(int x, int y, int &scaledX, int &scaledY) +int Renderer::EFBToScaledY(int y) { switch (g_ActiveConfig.iEFBScale) { + case 0: // fractional + return (int)ssaa_multiplier * FramebufferManagerBase::ScaleToVirtualXfbHeight(y, s_backbuffer_height); + + default: + return y * (int)ssaa_multiplier * (int)efb_scale_numeratorY / (int)efb_scale_denominatorY; + }; +} + +void Renderer::CalculateTargetScale(int x, int y, int &scaledX, int &scaledY) +{ + if (g_ActiveConfig.iEFBScale == 0 || g_ActiveConfig.iEFBScale == 1) + { + scaledX = x; + scaledY = y; + } + else + { + scaledX = x * (int)efb_scale_numeratorX / (int)efb_scale_denominatorX; + scaledY = y * (int)efb_scale_numeratorY / (int)efb_scale_denominatorY; + } +} + +// return true if target size changed +bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int framebuffer_height, int multiplier) +{ + int newEFBWidth, newEFBHeight; + + // TODO: Ugly. Clean up + switch (s_LastEFBScale) + { + case 2: // 1x + efb_scale_numeratorX = efb_scale_numeratorY = 1; + efb_scale_denominatorX = efb_scale_denominatorY = 1; + break; + case 3: // 1.5x - scaledX = (x / 2) * 3; - scaledY = (y / 2) * 3; + efb_scale_numeratorX = efb_scale_numeratorY = 3; + efb_scale_denominatorX = efb_scale_denominatorY = 2; break; + case 4: // 2x - scaledX = x * 2; - scaledY = y * 2; + efb_scale_numeratorX = efb_scale_numeratorY = 2; + efb_scale_denominatorX = efb_scale_denominatorY = 1; break; + case 5: // 2.5x - scaledX = (x / 2) * 5; - scaledY = (y / 2) * 5; + efb_scale_numeratorX = efb_scale_numeratorY = 5; + efb_scale_denominatorX = efb_scale_denominatorY = 2; break; + case 6: // 3x - scaledX = x * 3; - scaledY = y * 3; + efb_scale_numeratorX = efb_scale_numeratorY = 3; + efb_scale_denominatorX = efb_scale_denominatorY = 1; break; + case 7: // 4x - scaledX = x * 4; - scaledY = y * 4; + efb_scale_numeratorX = efb_scale_numeratorY = 4; + efb_scale_denominatorX = efb_scale_denominatorY = 1; break; - default: - scaledX = x; - scaledY = y; + + default: // fractional & integral handled later break; - }; -} + } -// return true if target size changed -bool Renderer::CalculateTargetSize(int multiplier) -{ - int newEFBWidth, newEFBHeight; switch (s_LastEFBScale) { case 0: // fractional - newEFBWidth = (int)(EFB_WIDTH * xScale); - newEFBHeight = (int)(EFB_HEIGHT * yScale); - break; case 1: // integral - newEFBWidth = EFB_WIDTH * (int)ceilf(xScale); - newEFBHeight = EFB_HEIGHT * (int)ceilf(yScale); + newEFBWidth = FramebufferManagerBase::ScaleToVirtualXfbWidth(EFB_WIDTH, framebuffer_width); + newEFBHeight = FramebufferManagerBase::ScaleToVirtualXfbHeight(EFB_HEIGHT, framebuffer_height); + + if (s_LastEFBScale == 1) + { + newEFBWidth = ((newEFBWidth-1) / EFB_WIDTH + 1) * EFB_WIDTH; + newEFBHeight = ((newEFBHeight-1) / EFB_HEIGHT + 1) * EFB_HEIGHT; + } + efb_scale_numeratorX = newEFBWidth; + efb_scale_denominatorX = EFB_WIDTH; + efb_scale_numeratorY = newEFBHeight; + efb_scale_denominatorY = EFB_HEIGHT; break; + default: CalculateTargetScale(EFB_WIDTH, EFB_HEIGHT, newEFBWidth, newEFBHeight); break; @@ -189,6 +241,7 @@ bool Renderer::CalculateTargetSize(int multiplier) newEFBWidth *= multiplier; newEFBHeight *= multiplier; + ssaa_multiplier = multiplier; if (newEFBWidth != s_target_width || newEFBHeight != s_target_height) { @@ -276,7 +329,6 @@ void Renderer::DrawDebugText() std::string("4: Aspect Ratio: ") + ar_text + (g_ActiveConfig.bCrop ? " (crop)" : ""), std::string("5: Copy EFB: ") + efbcopy_text, std::string("6: Fog: ") + (g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled"), - std::string("7: Material Lighting: ") + (g_ActiveConfig.bDisableLighting ? "Disabled" : "Enabled"), }; enum { lines_count = sizeof(lines)/sizeof(*lines) }; @@ -315,27 +367,125 @@ void Renderer::DrawDebugText() } } -void Renderer::CalculateXYScale(const TargetRectangle& dst_rect) +// TODO: remove +extern bool g_aspect_wide; + +void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height) { - if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB) + float FloatGLWidth = (float)backbuffer_width; + float FloatGLHeight = (float)backbuffer_height; + float FloatXOffset = 0; + float FloatYOffset = 0; + + // The rendering window size + const float WinWidth = FloatGLWidth; + const float WinHeight = FloatGLHeight; + + // Handle aspect ratio. + // Default to auto. + bool use16_9 = g_aspect_wide; + + // Update aspect ratio hack values + // Won't take effect until next frame + // Don't know if there is a better place for this code so there isn't a 1 frame delay + if ( g_ActiveConfig.bWidescreenHack ) { - xScale = 1.0f; - yScale = 1.0f; + float source_aspect = use16_9 ? (16.0f / 9.0f) : (4.0f / 3.0f); + float target_aspect; + + switch ( g_ActiveConfig.iAspectRatio ) + { + case ASPECT_FORCE_16_9 : + target_aspect = 16.0f / 9.0f; + break; + case ASPECT_FORCE_4_3 : + target_aspect = 4.0f / 3.0f; + break; + case ASPECT_STRETCH : + target_aspect = WinWidth / WinHeight; + break; + default : + // ASPECT_AUTO == no hacking + target_aspect = source_aspect; + break; + } + + float adjust = source_aspect / target_aspect; + if ( adjust > 1 ) + { + // Vert+ + g_Config.fAspectRatioHackW = 1; + g_Config.fAspectRatioHackH = 1/adjust; + } + else + { + // Hor+ + g_Config.fAspectRatioHackW = adjust; + g_Config.fAspectRatioHackH = 1; + } } else { - if (g_ActiveConfig.b3DVision) + // Hack is disabled + g_Config.fAspectRatioHackW = 1; + g_Config.fAspectRatioHackH = 1; + } + + // Check for force-settings and override. + if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) + use16_9 = true; + else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) + use16_9 = false; + + if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) + { + // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio + float Ratio = (WinWidth / WinHeight) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); + // Check if height or width is the limiting factor. If ratio > 1 the picture is too wide and have to limit the width. + if (Ratio > 1.0f) { - // This works, yet the version in the else doesn't. No idea why. - xScale = (float)(s_backbuffer_width-1) / (float)(s_XFB_width-1); - yScale = (float)(s_backbuffer_height-1) / (float)(s_XFB_height-1); + // Scale down and center in the X direction. + FloatGLWidth /= Ratio; + FloatXOffset = (WinWidth - FloatGLWidth) / 2.0f; } + // The window is too high, we have to limit the height else { - xScale = (float)(dst_rect.right - dst_rect.left - 1) / (float)(s_XFB_width-1); - yScale = (float)(dst_rect.bottom - dst_rect.top - 1) / (float)(s_XFB_height-1); + // Scale down and center in the Y direction. + FloatGLHeight *= Ratio; + FloatYOffset = FloatYOffset + (WinHeight - FloatGLHeight) / 2.0f; } } + + // ----------------------------------------------------------------------- + // Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10. + // Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset + // ------------------ + if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH && g_ActiveConfig.bCrop) + { + float Ratio = !use16_9 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f))); + // The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted) + float IncreasedWidth = (Ratio - 1.0f) * FloatGLWidth; + float IncreasedHeight = (Ratio - 1.0f) * FloatGLHeight; + // The new width and height + FloatGLWidth = FloatGLWidth * Ratio; + FloatGLHeight = FloatGLHeight * Ratio; + // Adjust the X and Y offset + FloatXOffset = FloatXOffset - (IncreasedWidth * 0.5f); + FloatYOffset = FloatYOffset - (IncreasedHeight * 0.5f); + } + + int XOffset = (int)(FloatXOffset + 0.5f); + int YOffset = (int)(FloatYOffset + 0.5f); + int iWhidth = (int)ceil(FloatGLWidth); + int iHeight = (int)ceil(FloatGLHeight); + iWhidth -= iWhidth % 4; // ensure divisibility by 4 to make it compatible with all the video encoders + iHeight -= iHeight % 4; + + target_rc.left = XOffset; + target_rc.top = YOffset; + target_rc.right = XOffset + iWhidth; + target_rc.bottom = YOffset + iHeight; } void Renderer::SetWindowSize(int width, int height) @@ -390,5 +540,6 @@ void Renderer::RecordVideoMemory() void UpdateViewport(Matrix44& vpCorrection) { - g_renderer->UpdateViewport(vpCorrection); + if (xfregs.viewport.wd != 0 && xfregs.viewport.ht != 0) + g_renderer->UpdateViewport(vpCorrection); } diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index e8d4c55a20..4da80c9752 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -74,10 +74,6 @@ public: static int GetBackbufferWidth() { return s_backbuffer_width; } static int GetBackbufferHeight() { return s_backbuffer_height; } - // XFB scale - TODO: Remove this and add two XFBToScaled functions instead - static float GetXFBScaleX() { return xScale; } - static float GetXFBScaleY() { return yScale; } - static void SetWindowSize(int width, int height); // EFB coordinate conversion functions @@ -85,9 +81,13 @@ public: // Use this to convert a whole native EFB rect to backbuffer coordinates virtual TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) = 0; + static const TargetRectangle& GetTargetRectangle() { return target_rc; } + static void UpdateDrawRectangle(int backbuffer_width, int backbuffer_height); + + // Use this to upscale native EFB coordinates to IDEAL internal resolution - static unsigned int EFBToScaledX(int x) { return x * GetTargetWidth() / EFB_WIDTH; } - static unsigned int EFBToScaledY(int y) { return y * GetTargetHeight() / EFB_HEIGHT; } + static int EFBToScaledX(int x); + static int EFBToScaledY(int y); // Floating point versions of the above - only use them if really necessary static float EFBToScaledXf(float x) { return x * ((float)GetTargetWidth() / (float)EFB_WIDTH); } @@ -133,8 +133,7 @@ public: protected: static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY); - static bool CalculateTargetSize(int multiplier = 1); - static void CalculateXYScale(const TargetRectangle& dst_rect); + static bool CalculateTargetSize(unsigned int framebuffer_width, unsigned int framebuffer_height, int multiplier = 1); static void CheckFifoRecording(); static void RecordVideoMemory(); @@ -159,12 +158,7 @@ protected: static int s_backbuffer_width; static int s_backbuffer_height; - // ratio of backbuffer size and render area size - TODO: Remove these! - static float xScale; - static float yScale; - - static unsigned int s_XFB_width; - static unsigned int s_XFB_height; + static TargetRectangle target_rc; // can probably eliminate this static var static int s_LastEFBScale; @@ -176,6 +170,11 @@ protected: private: static unsigned int prev_efb_format; + static unsigned int efb_scale_numeratorX; + static unsigned int efb_scale_numeratorY; + static unsigned int efb_scale_denominatorX; + static unsigned int efb_scale_denominatorY; + static unsigned int ssaa_multiplier; }; extern Renderer *g_renderer; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 00ff9610be..9fc18ef1bd 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -33,16 +33,18 @@ extern int frameCount; enum { - TEMP_SIZE = (2048 * 2048 * 4), TEXTURE_KILL_THRESHOLD = 200, }; TextureCache *g_texture_cache; GC_ALIGNED16(u8 *TextureCache::temp) = NULL; +unsigned int TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; -bool TextureCache::DeferredInvalidate; + +TextureCache::BackupConfig TextureCache::backup_config; + TextureCache::TCacheEntryBase::~TCacheEntryBase() { @@ -50,42 +52,29 @@ TextureCache::TCacheEntryBase::~TCacheEntryBase() TextureCache::TextureCache() { + temp_size = 2048 * 2048 * 4; if (!temp) - temp = (u8*)AllocateAlignedMemory(TEMP_SIZE,16); + temp = (u8*)AllocateAlignedMemory(temp_size, 16); TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); } -void TextureCache::Invalidate(bool shutdown) +void TextureCache::Invalidate() { TexCache::iterator iter = textures.begin(), tcend = textures.end(); for (; iter != tcend; ++iter) - { - if (shutdown) - iter->second->addr = 0; delete iter->second; - } textures.clear(); - if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) - HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); - SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); - - DeferredInvalidate = false; -} - -void TextureCache::InvalidateDefer() -{ - DeferredInvalidate = true; } TextureCache::~TextureCache() { - Invalidate(true); + Invalidate(); if (temp) { FreeAlignedMemory(temp); @@ -93,6 +82,48 @@ TextureCache::~TextureCache() } } +void TextureCache::OnConfigChanged(VideoConfig& config) +{ + if (!g_texture_cache) + goto skip_checks; + + // TODO: Invalidating texcache is really stupid in some of these cases + if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples || + config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay || + config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center || + config.bHiresTextures != backup_config.s_hires_textures) + { + g_texture_cache->Invalidate(); + + if(g_ActiveConfig.bHiresTextures) + HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + + SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); + TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); + } + + // TODO: Probably shouldn't clear all render targets here, just mark them dirty or something. + if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed? + config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture || + config.bCopyEFBScaled != backup_config.s_copy_efb_scaled || + config.bEFBCopyEnable != backup_config.s_copy_efb || + config.iEFBScale != backup_config.s_efb_scale) + { + g_texture_cache->ClearRenderTargets(); + } + +skip_checks: + backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples; + backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture; + backup_config.s_copy_efb_scaled = config.bCopyEFBScaled; + backup_config.s_copy_efb = config.bEFBCopyEnable; + backup_config.s_efb_scale = config.iEFBScale; + backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable; + backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; + backup_config.s_hires_textures = config.bHiresTextures; + backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable; +} + void TextureCache::Cleanup() { TexCache::iterator iter = textures.begin(); @@ -174,8 +205,93 @@ void TextureCache::ClearRenderTargets() tcend = textures.end(); for (; iter!=tcend; ++iter) - if (iter->second->type != TCET_EC_DYNAMIC) - iter->second->type = TCET_NORMAL; + if (iter->second->type == TCET_EC_VRAM) + { + delete iter->second; + textures.erase(iter++); + } +} + +bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels) +{ + // Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black + char texBasePathTemp[MAX_PATH]; + char texPathTemp[MAX_PATH]; + + sprintf(texBasePathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); + + for (unsigned int level = 1; level < levels; ++level) + { + sprintf(texPathTemp, "%s_mip%i", texBasePathTemp, level); + if (!HiresTextures::HiresTexExists(texPathTemp)) + { + if (level > 1) + WARN_LOG(VIDEO, "Couldn't find custom texture LOD with index %i (filename: %s), disabling custom LODs for this texture", level, texPathTemp); + + return false; + } + } + return true; +} + +PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height) +{ + char texPathTemp[MAX_PATH]; + unsigned int newWidth = 0; + unsigned int newHeight = 0; + + if (level == 0) + sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); + else + sprintf(texPathTemp, "%s_%08x_%i_mip%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat, level); + + unsigned int required_size = 0; + PC_TexFormat ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, &required_size, texformat, temp_size, temp); + if (ret == PC_TEX_FMT_NONE && temp_size < required_size) + { + // Allocate more memory and try again + // TODO: Should probably check if newWidth and newHeight are texture dimensions which are actually supported by the current video backend + temp_size = required_size; + FreeAlignedMemory(temp); + temp = (u8*)AllocateAlignedMemory(temp_size, 16); + ret = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, &required_size, texformat, temp_size, temp); + } + + if (ret != PC_TEX_FMT_NONE) + { + width = newWidth; + height = newHeight; + } + return ret; +} + +void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) +{ + char szTemp[MAX_PATH]; + std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; + + // make sure that the directory exists + if (false == File::Exists(szDir) || false == File::IsDirectory(szDir)) + File::CreateDir(szDir.c_str()); + + // For compatibility with old texture packs, don't print the LOD index for level 0. + // TODO: TLUT format should actually be stored in filename? :/ + if (level == 0) + { + sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); + } + else + { + sprintf(szTemp, "%s/%s_%08x_%i_mip%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level); + } + + if (false == File::Exists(szTemp)) + entry->Save(szTemp, level); } TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, @@ -194,6 +310,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, const unsigned int nativeW = width; const unsigned int nativeH = height; + bool using_custom_texture = false; + bool using_custom_lods = false; + u32 texID = address; u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) u64 tlut_hash = TEXHASH_INVALID; @@ -240,8 +359,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // 2. a) For EFB copies, only the hash and the texture address need to match if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr) { - if (entry->type != TCET_EC_VRAM) - entry->type = TCET_NORMAL; + entry->type = TCET_EC_VRAM; // TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat()) goto return_entry; @@ -259,7 +377,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... - if ((entry->type == TCET_NORMAL && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps == maxlevel) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) { // reuse the texture @@ -272,38 +390,39 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } + if (g_ActiveConfig.bHiresTextures) { - // Load Custom textures - char texPathTemp[MAX_PATH]; - - unsigned int newWidth = width; - unsigned int newHeight = height; - - sprintf(texPathTemp, "%s_%08x_%i", SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); - pcfmt = HiresTextures::GetHiresTex(texPathTemp, &newWidth, &newHeight, texformat, temp); - + pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height); if (pcfmt != PC_TEX_FMT_NONE) { - expandedWidth = width = newWidth; - expandedHeight = height = newHeight; + if (expandedWidth != width || expandedHeight != height) + { + expandedWidth = width; + expandedHeight = height; + + // If we thought we could reuse the texture before, make sure to delete it now! + delete entry; + entry = NULL; + } + using_custom_texture = true; } } - // TODO: RGBA8 textures are stored non-continuously in tmem, that might cause problems when preloading is enabled - if (pcfmt == PC_TEX_FMT_NONE) + // TODO: RGBA8 textures are stored non-continuously in tmem, that might cause problems here when preloading is enabled + if (!using_custom_texture) pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + // TODO: Cleanup. Plus, we still autogenerate mipmaps in certain cases (we shouldn't do that) bool isPow2; unsigned int texLevels; - UseNativeMips = UseNativeMips && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions isPow2 = !((width & (width - 1)) || (height & (height - 1))); - texLevels = (isPow2 && UseNativeMips && maxlevel) ? - GetPow2(std::max(width, height)) : !isPow2; - - if ((texLevels > (maxlevel + 1)) && maxlevel) - texLevels = maxlevel + 1; + texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2; + texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels; + using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels); + UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions + texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2; // create the entry/texture if (NULL == entry) { @@ -329,8 +448,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // load texture entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); + if (g_ActiveConfig.bDumpTextures && !using_custom_texture) + DumpTexture(entry, 0); + // load mips - TODO: Loading mipmaps from tmem is untested! - if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE) + if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips) { const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat); @@ -361,31 +483,33 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); entry->Load(currentWidth, currentHeight, expandedWidth, level, false); + if (g_ActiveConfig.bDumpTextures) + DumpTexture(entry, level); + *ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1); mipWidth >>= 1; mipHeight >>= 1; ++level; } } - - // TODO: won't this cause loaded hires textures to be dumped as well? - // dump texture to file - if (g_ActiveConfig.bDumpTextures) + else if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && using_custom_lods) { - char szTemp[MAX_PATH]; - std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; + unsigned int level = 1; + unsigned int mipWidth = (width + 1) >> 1; + unsigned int mipHeight = (height + 1) >> 1; - // make sure that the directory exists - if (false == File::Exists(szDir) || false == File::IsDirectory(szDir)) - File::CreateDir(szDir.c_str()); + while ((mipHeight || mipWidth) && (level < texLevels)) + { + unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1; + unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1; - sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32) (tex_hash & 0x00000000FFFFFFFFLL), texformat); + LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight); + entry->Load(currentWidth, currentHeight, currentWidth, level, false); - if (false == File::Exists(szTemp)) - entry->Save(szTemp); + mipWidth >>= 1; + mipHeight >>= 1; + ++level; + } } INCSTAT(stats.numTexturesCreated); @@ -649,16 +773,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if ((entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h) - || (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h)) + if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h) { - if (entry->type == TCET_EC_DYNAMIC) - { - scaled_tex_w = tex_w; - scaled_tex_h = tex_h; - } + scaled_tex_w = tex_w; + scaled_tex_h = tex_h; } - else + else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) { // remove it and recreate it as a render target delete entry; @@ -672,7 +792,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat, 0); + entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 2924c5871f..4ef3b8a985 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -27,6 +27,8 @@ #include "CommonTypes.h" +struct VideoConfig; + class TextureCache { public: @@ -84,7 +86,7 @@ public: virtual ~TCacheEntryBase(); virtual void Bind(unsigned int stage) = 0; - virtual bool Save(const char filename[]) = 0; + virtual bool Save(const char filename[], unsigned int level) = 0; virtual void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0; @@ -100,10 +102,10 @@ public: virtual ~TextureCache(); // needs virtual for DX11 dtor + static void OnConfigChanged(VideoConfig& config); static void Cleanup(); - static void Invalidate(bool shutdown); - static void InvalidateDefer(); + static void Invalidate(); static void InvalidateRange(u32 start_address, u32 size); static void MakeRangeDynamic(u32 start_address, u32 size); static void ClearRenderTargets(); // currently only used by OGL @@ -118,17 +120,34 @@ public: static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); - static bool DeferredInvalidate; - protected: TextureCache(); static GC_ALIGNED16(u8 *temp); + static unsigned int temp_size; private: + static bool CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels); + static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height); + static void DumpTexture(TCacheEntryBase* entry, unsigned int level); + + typedef std::map<u32, TCacheEntryBase*> TexCache; static TexCache textures; + + // Backup configuration values + static struct BackupConfig { + int s_colorsamples; + bool s_copy_efb_to_texture; + bool s_copy_efb_scaled; + bool s_copy_efb; + int s_efb_scale; + bool s_texfmt_overlay; + bool s_texfmt_overlay_center; + bool s_hires_textures; + bool s_copy_cache_enable; + } backup_config; }; extern TextureCache *g_texture_cache; diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index fb34ce1bc1..5bffab8ee7 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -224,14 +224,14 @@ void VertexLoader::CompileVertexTranslator() #endif // Colors - const int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; + const u32 col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; // TextureCoord // Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually. // If we didn't do this, the vertex format would be read as one bit offset from where it should be, making // 01 become 00, and 10/11 become 01 - const int tc[8] = { + const u32 tc[8] = { m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, - m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (const int)((m_VtxDesc.Hex >> 31) & 3) + m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (const u32)((m_VtxDesc.Hex >> 31) & 3) }; // Reset pipeline @@ -770,7 +770,7 @@ void VertexLoader::AppendToString(std::string *dest) const dest->append(StringFromFormat("Nrm: %i %s-%s ", m_VtxAttr.NormalElements, posMode[m_VtxDesc.Normal], posFormats[m_VtxAttr.NormalFormat])); } - int color_mode[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; + u32 color_mode[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1}; for (int i = 0; i < 2; i++) { if (color_mode[i]) @@ -778,7 +778,7 @@ void VertexLoader::AppendToString(std::string *dest) const dest->append(StringFromFormat("C%i: %i %s-%s ", i, m_VtxAttr.color[i].Elements, posMode[color_mode[i]], colorFormat[m_VtxAttr.color[i].Comp])); } } - int tex_mode[8] = { + u32 tex_mode[8] = { m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord, m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, m_VtxDesc.Tex7Coord }; diff --git a/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp b/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp index 316941a639..153e69a8c3 100644 --- a/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoaderManager.cpp @@ -19,9 +19,12 @@ #ifdef _MSC_VER #include <hash_map> using stdext::hash_map; -#else +#elif defined __APPLE__ #include <ext/hash_map> using __gnu_cxx::hash_map; +#else +#include <unordered_map> +using std::unordered_map; #endif #include <map> #include <vector> @@ -45,7 +48,12 @@ namespace stdext { } } #else -namespace __gnu_cxx { +#ifdef __APPLE__ +namespace __gnu_cxx +#else +namespace std +#endif +{ template<> struct hash<VertexLoaderUID> { size_t operator()(const VertexLoaderUID& uid) const { return uid.GetHash(); @@ -54,10 +62,15 @@ namespace __gnu_cxx { } #endif +#if defined _MSC_VER || defined __APPLE__ +typedef hash_map<VertexLoaderUID, VertexLoader*> VertexLoaderMap; +#else +typedef unordered_map<VertexLoaderUID, VertexLoader*> VertexLoaderMap; +#endif + namespace VertexLoaderManager { -typedef hash_map<VertexLoaderUID, VertexLoader*> VertexLoaderMap; static VertexLoaderMap g_VertexLoaderMap; // TODO - change into array of pointers. Keep a map of all seen so far. diff --git a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp index b16e7e6ee9..9cfa5efc31 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader_Color.cpp @@ -149,7 +149,7 @@ void LOADERDECL Color_ReadIndex8_24b_888() void LOADERDECL Color_ReadIndex8_32b_888x() { u8 Index = DataReadU8(); - const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR]+colIndex); + const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]); _SetCol(_Read24(iAddress)); } void LOADERDECL Color_ReadIndex8_16b_4444() diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp index 004b0f3cca..5be72e4fcf 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.cpp @@ -9,6 +9,7 @@ #include "NativeVertexFormat.h" #include "TextureCacheBase.h" #include "RenderBase.h" +#include "BPStructs.h" #include "VertexManagerBase.h" #include "VideoConfig.h" @@ -159,16 +160,9 @@ void VertexManager::AddVertices(int primitive, int numVertices) void VertexManager::Flush() { - // Disable Lighting - // TODO - Is this a good spot for this code? - if (g_ActiveConfig.bDisableLighting) - { - for (u32 i = 0; i < xfregs.numChan.numColorChans; i++) - { - xfregs.alpha[i].enablelighting = false; - xfregs.color[i].enablelighting = false; - } - } + // loading a state will invalidate BP, so check for it + g_video_backend->CheckInvalidState(); + g_vertex_manager->vFlush(); } @@ -236,22 +230,13 @@ void VertexManager::Flush() tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips, + (tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8), (tex.texMode1[i&3].max_lod >> 4)); if (tentry) { // 0s are probably for no manual wrapping needed. PixelShaderManager::SetTexDims(i, tentry->nativeW, tentry->nativeH, 0, 0); - - // TODO: - //if (g_ActiveConfig.iLog & CONF_SAVETEXTURES) - //{ - // // save the textures - // char strfile[255]; - // sprintf(strfile, "%stex%.3d_%d.tga", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_Config.iSaveTargetId, i); - // SaveTexture(strfile, GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); - //} } else ERROR_LOG(VIDEO, "error loading texture"); @@ -317,3 +302,20 @@ shader_fail: ResetBuffer(); } #endif + +void VertexManager::DoState(PointerWrap& p) +{ + g_vertex_manager->vDoState(p); +} + +void VertexManager::DoStateShared(PointerWrap& p) +{ + p.DoPointer(s_pCurBufferPointer, LocalVBuffer); + p.DoArray(LocalVBuffer, MAXVBUFFERSIZE); + p.DoArray(TIBuffer, MAXIBUFFERSIZE); + p.DoArray(LIBuffer, MAXIBUFFERSIZE); + p.DoArray(PIBuffer, MAXIBUFFERSIZE); + + if (p.GetMode() == PointerWrap::MODE_READ) + Flushed = false; +} diff --git a/Source/Core/VideoCommon/Src/VertexManagerBase.h b/Source/Core/VideoCommon/Src/VertexManagerBase.h index 12dc02ae4b..f3a4aa72e3 100644 --- a/Source/Core/VideoCommon/Src/VertexManagerBase.h +++ b/Source/Core/VideoCommon/Src/VertexManagerBase.h @@ -3,6 +3,7 @@ #define _VERTEXMANAGERBASE_H class NativeVertexFormat; +class PointerWrap; class VertexManager { @@ -20,7 +21,7 @@ public: // values from DX11 backend MAXVBUFFERSIZE = 0x50000, - MAXIBUFFERSIZE = 0x10000, + MAXIBUFFERSIZE = 0xFFFF, }; VertexManager(); @@ -44,6 +45,9 @@ public: static u16* GetPointIndexBuffer() { return PIBuffer; } static u8* GetVertexBuffer() { return LocalVBuffer; } + static void DoState(PointerWrap& p); + virtual void CreateDeviceObjects(){}; + virtual void DestroyDeviceObjects(){}; protected: // TODO: make private after Flush() is merged static void ResetBuffer(); @@ -55,6 +59,9 @@ protected: static bool Flushed; + virtual void vDoState(PointerWrap& p) { DoStateShared(p); } + void DoStateShared(PointerWrap& p); + private: static void AddIndices(int primitive, int numVertices); //virtual void Draw(u32 stride, bool alphapass) = 0; diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp index b6afbc61c6..d960710ada 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp @@ -51,6 +51,11 @@ static float s_fViewRotation[2]; void UpdateViewport(Matrix44& vpCorrection); +void UpdateViewportWithCorrection() +{ + UpdateViewport(s_viewportCorrection); +} + inline void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { g_renderer->SetVSConstant4f(const_number, f1, f2, f3, f4); @@ -202,6 +207,7 @@ void VertexShaderManager::SetConstants() int endn = (nPostTransformMatricesChanged[1] + 3 ) / 4; const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES + startn * 4]; SetMultiVSConstant4fv(C_POSTTRANSFORMMATRICES + startn, endn - startn, pstart); + nPostTransformMatricesChanged[0] = nPostTransformMatricesChanged[1] = -1; } if (nLightsChanged[0] >= 0) @@ -245,7 +251,7 @@ void VertexShaderManager::SetConstants() float GC_ALIGNED16(material[4]); float NormalizationCoef = 1 / 255.0f; - for (int i = 0; i < 4; ++i) + for (int i = 0; i < 2; ++i) { if (nMaterialsChanged & (1 << i)) { @@ -259,6 +265,21 @@ void VertexShaderManager::SetConstants() SetVSConstant4fv(C_MATERIALS + i, material); } } + + for (int i = 0; i < 2; ++i) + { + if (nMaterialsChanged & (1 << (i + 2))) + { + u32 data = *(xfregs.matColor + i); + + material[0] = ((data >> 24) & 0xFF) * NormalizationCoef; + material[1] = ((data >> 16) & 0xFF) * NormalizationCoef; + material[2] = ((data >> 8) & 0xFF) * NormalizationCoef; + material[3] = ( data & 0xFF) * NormalizationCoef; + + SetVSConstant4fv(C_MATERIALS + i + 2, material); + } + } nMaterialsChanged = 0; } @@ -616,3 +637,18 @@ void VertexShaderManager::ResetView() bProjectionChanged = true; } + +void VertexShaderManager::DoState(PointerWrap &p) +{ + p.Do(g_fProjectionMatrix); + p.Do(s_viewportCorrection); + p.Do(s_viewRotationMatrix); + p.Do(s_viewInvRotationMatrix); + p.Do(s_fViewTranslationVector); + p.Do(s_fViewRotation); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + Dirty(); + } +} diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.h b/Source/Core/VideoCommon/Src/VertexShaderManager.h index ddbde1c0dd..86f77ee3da 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderManager.h +++ b/Source/Core/VideoCommon/Src/VertexShaderManager.h @@ -20,6 +20,8 @@ #include "VertexShaderGen.h" +class PointerWrap; + struct ProjectionHack { float sign; @@ -31,6 +33,8 @@ struct ProjectionHack void UpdateProjectionHack(int iParams[], std::string sParams[]); +void UpdateViewportWithCorrection(); + // The non-API dependent parts. class VertexShaderManager { @@ -38,7 +42,8 @@ public: static void Init(); static void Dirty(); static void Shutdown(); - + static void DoState(PointerWrap &p); +; // constant management static void SetConstants(); diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h index 9f6dd59cd3..1eeed20b82 100644 --- a/Source/Core/VideoCommon/Src/VideoCommon.h +++ b/Source/Core/VideoCommon/Src/VideoCommon.h @@ -44,17 +44,14 @@ enum EFB_HEIGHT = 528, }; -enum -{ - // XFB width is decided by EFB copy operation. The VI can do horizontal - // scaling (TODO: emulate). - MAX_XFB_WIDTH = EFB_WIDTH, - - // Although EFB height is 528, 574-line XFB's can be created either with - // vertical scaling by the EFB copy operation or copying to multiple XFB's - // that are next to each other in memory (TODO: handle that situation). - MAX_XFB_HEIGHT = 574 -}; +// XFB width is decided by EFB copy operation. The VI can do horizontal +// scaling (TODO: emulate). +const u32 MAX_XFB_WIDTH = EFB_WIDTH; + +// Although EFB height is 528, 574-line XFB's can be created either with +// vertical scaling by the EFB copy operation or copying to multiple XFB's +// that are next to each other in memory (TODO: handle that situation). +const u32 MAX_XFB_HEIGHT = 574; // Logging // ---------- @@ -88,9 +85,9 @@ struct TargetRectangle : public MathUtil::Rectangle<int> }; #ifdef _WIN32 -#define PRIM_LOG(...) {DEBUG_LOG(VIDEO, __VA_ARGS__)} +#define PRIM_LOG(...) DEBUG_LOG(VIDEO, __VA_ARGS__) #else -#define PRIM_LOG(...) {DEBUG_LOG(VIDEO, ##__VA_ARGS__)} +#define PRIM_LOG(...) DEBUG_LOG(VIDEO, ##__VA_ARGS__) #endif diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index 5bb6e4dd99..c702b577e2 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -57,9 +57,9 @@ void VideoConfig::Load(const char *ini_file) iniFile.Get("Settings", "Crop", &bCrop, false); iniFile.Get("Settings", "UseXFB", &bUseXFB, 0); iniFile.Get("Settings", "UseRealXFB", &bUseRealXFB, 0); - iniFile.Get("Settings", "UseNativeMips", &bUseNativeMips, false); iniFile.Get("Settings", "SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples,128); iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings + iniFile.Get("Settings", "LogFPSToFile", &bLogFPSToFile, false); iniFile.Get("Settings", "ShowInputDisplay", &bShowInputDisplay, false); iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false); iniFile.Get("Settings", "OverlayProjStats", &bOverlayProjStats, false); @@ -85,8 +85,6 @@ void VideoConfig::Load(const char *ini_file) iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0); iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0); iniFile.Get("Settings", "WireFrame", &bWireFrame, 0); - iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0); - iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0); iniFile.Get("Settings", "DisableFog", &bDisableFog, 0); iniFile.Get("Settings", "EnableOpenCL", &bEnableOpenCL, false); @@ -129,7 +127,6 @@ void VideoConfig::GameIniLoad(const char *ini_file) iniFile.GetIfExists("Video_Settings", "Crop", &bCrop); iniFile.GetIfExists("Video_Settings", "UseXFB", &bUseXFB); iniFile.GetIfExists("Video_Settings", "UseRealXFB", &bUseRealXFB); - iniFile.GetIfExists("Video_Settings", "UseNativeMips", &bUseNativeMips); iniFile.GetIfExists("Video_Settings", "SafeTextureCacheColorSamples", &iSafeTextureCache_ColorSamples); iniFile.GetIfExists("Video_Settings", "DLOptimize", &iCompileDLsLevel); iniFile.GetIfExists("Video_Settings", "HiresTextures", &bHiresTextures); @@ -141,8 +138,6 @@ void VideoConfig::GameIniLoad(const char *ini_file) iniFile.GetIfExists("Video_Settings", "MSAA", &iMultisampleMode); iniFile.GetIfExists("Video_Settings", "EFBScale", &iEFBScale); // integral iniFile.GetIfExists("Video_Settings", "DstAlphaPass", &bDstAlphaPass); - iniFile.GetIfExists("Video_Settings", "DisableLighting", &bDisableLighting); - iniFile.GetIfExists("Video_Settings", "DisableTexturing", &bDisableTexturing); iniFile.GetIfExists("Video_Settings", "DisableFog", &bDisableFog); iniFile.GetIfExists("Video_Settings", "EnableOpenCL", &bEnableOpenCL); iniFile.GetIfExists("Video_Settings", "OMPDecoder", &bOMPDecoder); @@ -190,9 +185,9 @@ void VideoConfig::Save(const char *ini_file) iniFile.Set("Settings", "wideScreenHack", bWidescreenHack); iniFile.Set("Settings", "UseXFB", bUseXFB); iniFile.Set("Settings", "UseRealXFB", bUseRealXFB); - iniFile.Set("Settings", "UseNativeMips", bUseNativeMips); iniFile.Set("Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples); iniFile.Set("Settings", "ShowFPS", bShowFPS); + iniFile.Set("Settings", "LogFPSToFile", bLogFPSToFile); iniFile.Set("Settings", "ShowInputDisplay", bShowInputDisplay); iniFile.Set("Settings", "OverlayStats", bOverlayStats); iniFile.Set("Settings", "OverlayProjStats", bOverlayProjStats); @@ -217,8 +212,6 @@ void VideoConfig::Save(const char *ini_file) iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter); iniFile.Set("Settings", "Wireframe", bWireFrame); - iniFile.Set("Settings", "DisableLighting", bDisableLighting); - iniFile.Set("Settings", "DisableTexturing", bDisableTexturing); iniFile.Set("Settings", "DstAlphaPass", bDstAlphaPass); iniFile.Set("Settings", "DisableFog", bDisableFog); @@ -269,7 +262,6 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini) SET_IF_DIFFERS("Video_Settings", "Crop", bCrop); SET_IF_DIFFERS("Video_Settings", "UseXFB", bUseXFB); SET_IF_DIFFERS("Video_Settings", "UseRealXFB", bUseRealXFB); - SET_IF_DIFFERS("Video_Settings", "UseNativeMips", bUseNativeMips); SET_IF_DIFFERS("Video_Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples); SET_IF_DIFFERS("Video_Settings", "DLOptimize", iCompileDLsLevel); SET_IF_DIFFERS("Video_Settings", "HiresTextures", bHiresTextures); @@ -281,8 +273,6 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini) SET_IF_DIFFERS("Video_Settings", "MSAA", iMultisampleMode); SET_IF_DIFFERS("Video_Settings", "EFBScale", iEFBScale); // integral SET_IF_DIFFERS("Video_Settings", "DstAlphaPass", bDstAlphaPass); - SET_IF_DIFFERS("Video_Settings", "DisableLighting", bDisableLighting); - SET_IF_DIFFERS("Video_Settings", "DisableTexturing", bDisableTexturing); SET_IF_DIFFERS("Video_Settings", "DisableFog", bDisableFog); SET_IF_DIFFERS("Video_Settings", "EnableOpenCL", bEnableOpenCL); SET_IF_DIFFERS("Video_Settings", "OMPDecoder", bOMPDecoder); @@ -302,125 +292,3 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini) iniFile.Save(game_ini); } - - -// TODO: remove -extern bool g_aspect_wide; - -// TODO: Figure out a better place for this function. -void ComputeDrawRectangle(int backbuffer_width, int backbuffer_height, bool flip, TargetRectangle *rc) -{ - float FloatGLWidth = (float)backbuffer_width; - float FloatGLHeight = (float)backbuffer_height; - float FloatXOffset = 0; - float FloatYOffset = 0; - - // The rendering window size - const float WinWidth = FloatGLWidth; - const float WinHeight = FloatGLHeight; - - // Handle aspect ratio. - // Default to auto. - bool use16_9 = g_aspect_wide; - - // Update aspect ratio hack values - // Won't take effect until next frame - // Don't know if there is a better place for this code so there isn't a 1 frame delay - if ( g_ActiveConfig.bWidescreenHack ) - { - float source_aspect = use16_9 ? (16.0f / 9.0f) : (4.0f / 3.0f); - float target_aspect; - - switch ( g_ActiveConfig.iAspectRatio ) - { - case ASPECT_FORCE_16_9 : - target_aspect = 16.0f / 9.0f; - break; - case ASPECT_FORCE_4_3 : - target_aspect = 4.0f / 3.0f; - break; - case ASPECT_STRETCH : - target_aspect = WinWidth / WinHeight; - break; - default : - // ASPECT_AUTO == no hacking - target_aspect = source_aspect; - break; - } - - float adjust = source_aspect / target_aspect; - if ( adjust > 1 ) - { - // Vert+ - g_Config.fAspectRatioHackW = 1; - g_Config.fAspectRatioHackH = 1/adjust; - } - else - { - // Hor+ - g_Config.fAspectRatioHackW = adjust; - g_Config.fAspectRatioHackH = 1; - } - } - else - { - // Hack is disabled - g_Config.fAspectRatioHackW = 1; - g_Config.fAspectRatioHackH = 1; - } - - // Check for force-settings and override. - if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) - use16_9 = true; - else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) - use16_9 = false; - - if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) - { - // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio - float Ratio = (WinWidth / WinHeight) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); - // Check if height or width is the limiting factor. If ratio > 1 the picture is too wide and have to limit the width. - if (Ratio > 1.0f) - { - // Scale down and center in the X direction. - FloatGLWidth /= Ratio; - FloatXOffset = (WinWidth - FloatGLWidth) / 2.0f; - } - // The window is too high, we have to limit the height - else - { - // Scale down and center in the Y direction. - FloatGLHeight *= Ratio; - FloatYOffset = FloatYOffset + (WinHeight - FloatGLHeight) / 2.0f; - } - } - - // ----------------------------------------------------------------------- - // Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10. - // Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset - // ------------------ - if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH && g_ActiveConfig.bCrop) - { - float Ratio = !use16_9 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f))); - // The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted) - float IncreasedWidth = (Ratio - 1.0f) * FloatGLWidth; - float IncreasedHeight = (Ratio - 1.0f) * FloatGLHeight; - // The new width and height - FloatGLWidth = FloatGLWidth * Ratio; - FloatGLHeight = FloatGLHeight * Ratio; - // Adjust the X and Y offset - FloatXOffset = FloatXOffset - (IncreasedWidth * 0.5f); - FloatYOffset = FloatYOffset - (IncreasedHeight * 0.5f); - } - - int XOffset = (int)(FloatXOffset + 0.5f); - int YOffset = (int)(FloatYOffset + 0.5f); - int iWhidth = (int)ceil(FloatGLWidth); - int iHeight = (int)ceil(FloatGLHeight); - iWhidth -= iWhidth % 4; // ensure divisibility by 4 to make it compatible with all the video encoders - iHeight -= iHeight % 4; - rc->left = XOffset; - rc->top = flip ? (int)(YOffset + iHeight) : YOffset; - rc->right = XOffset + iWhidth; - rc->bottom = flip ? YOffset : (int)(YOffset + iHeight); -} diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 7c846676bb..fe883e0dbe 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -34,7 +34,6 @@ // Log in two categories, and save three other options in the same byte #define CONF_LOG 1 #define CONF_PRIMLOG 2 -#define CONF_SAVETEXTURES 4 #define CONF_SAVETARGETS 8 #define CONF_SAVESHADERS 16 @@ -78,7 +77,6 @@ struct VideoConfig bool bCrop; // Aspect ratio controls. bool bUseXFB; bool bUseRealXFB; - bool bUseNativeMips; // OpenCL/OpenMP bool bEnableOpenCL; @@ -99,11 +97,10 @@ struct VideoConfig bool bTexFmtOverlayEnable; bool bTexFmtOverlayCenter; bool bShowEFBCopyRegions; + bool bLogFPSToFile; // Render bool bWireFrame; - bool bDisableLighting; - bool bDisableTexturing; bool bDstAlphaPass; bool bDisableFog; @@ -139,8 +136,8 @@ struct VideoConfig bool bEnablePerPixelDepth; int iLog; // CONF_ bits - int iSaveTargetId; - + int iSaveTargetId; // TODO: Should be dropped + //currently unused: int iCompileDLsLevel; @@ -166,6 +163,12 @@ struct VideoConfig bool bSupportsFormatReinterpretation; bool bSupportsPixelLighting; } backend_info; + + // Utility + bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; } + bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; } + bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; } + bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; } }; extern VideoConfig g_Config; @@ -174,6 +177,4 @@ extern VideoConfig g_ActiveConfig; // Called every frame. void UpdateActiveConfig(); -void ComputeDrawRectangle(int backbuffer_width, int backbuffer_height, bool flip, TargetRectangle *rc); - #endif // _VIDEO_CONFIG_H_ diff --git a/Source/Core/VideoCommon/Src/VideoState.cpp b/Source/Core/VideoCommon/Src/VideoState.cpp index b1c1ed0889..ad5384cda9 100644 --- a/Source/Core/VideoCommon/Src/VideoState.cpp +++ b/Source/Core/VideoCommon/Src/VideoState.cpp @@ -24,36 +24,60 @@ #include "Fifo.h" #include "CommandProcessor.h" #include "PixelEngine.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" +#include "VertexManagerBase.h" static void DoState(PointerWrap &p) { // BP Memory p.Do(bpmem); - // CP Memory + p.DoMarker("BP Memory"); + + // CP Memory p.DoArray(arraybases, 16); p.DoArray(arraystrides, 16); p.Do(MatrixIndexA); p.Do(MatrixIndexB); p.Do(g_VtxDesc.Hex); p.DoArray(g_VtxAttr, 8); + p.DoMarker("CP Memory"); // XF Memory p.Do(xfregs); p.DoArray(xfmem, XFMEM_SIZE); - // Texture decoder + p.DoMarker("XF Memory"); + + // Texture decoder p.DoArray(texMem, TMEM_SIZE); + p.DoMarker("texMem"); // FIFO Fifo_DoState(p); + p.DoMarker("Fifo"); CommandProcessor::DoState(p); - PixelEngine::DoState(p); + p.DoMarker("CommandProcessor"); + + PixelEngine::DoState(p); + p.DoMarker("PixelEngine"); + + // the old way of replaying current bpmem as writes to push side effects to pixel shader manager doesn't really work. + PixelShaderManager::DoState(p); + p.DoMarker("PixelShaderManager"); + + VertexShaderManager::DoState(p); + p.DoMarker("VertexShaderManager"); + + VertexManager::DoState(p); + p.DoMarker("VertexManager"); + + // TODO: search for more data that should be saved and add it here } void VideoCommon_DoState(PointerWrap &p) { DoState(p); - //TODO: search for more data that should be saved and add it here } void VideoCommon_RunLoop(bool enable) diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp index ec3975cb07..9f395bfecf 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.cpp +++ b/Source/Core/VideoCommon/Src/XFStructs.cpp @@ -143,7 +143,7 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData) case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens if (xfregs.numTexGen.numTexGens != (newValue & 15)) - VertexManager::Flush(); + VertexManager::Flush(); break; case XFMEM_SETTEXMTXINFO: @@ -257,13 +257,26 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) // TODO - verify that it is correct. Seems to work, though. void LoadIndexedXF(u32 val, int refarray) { - int index = val >> 16; - int address = val & 0xFFF; // check mask - int size = ((val >> 12) & 0xF) + 1; - //load stuff from array to address in xf mem - - XFMemWritten(size, address); - - for (int i = 0; i < size; i++) - xfmem[address + i] = Memory::Read_U32(arraybases[refarray] + arraystrides[refarray] * index + i * 4); + int index = val >> 16; + int address = val & 0xFFF; // check mask + int size = ((val >> 12) & 0xF) + 1; + //load stuff from array to address in xf mem + + u32* currData = (u32*)(xfmem + address); + u32* newData = (u32*)Memory::GetPointer(arraybases[refarray] + arraystrides[refarray] * index); + bool changed = false; + for (int i = 0; i < size; ++i) + { + if (currData[i] != Common::swap32(newData[i])) + { + changed = true; + XFMemWritten(size, address); + break; + } + } + if (changed) + { + for (int i = 0; i < size; ++i) + currData[i] = Common::swap32(newData[i]); + } } diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index f53c18cb37..bf9122e6b5 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -111,7 +111,8 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - </ClCompile> + <OpenMPSupport>false</OpenMPSupport> + </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> </Link> @@ -129,7 +130,7 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <OpenMPSupport>true</OpenMPSupport> + <OpenMPSupport>false</OpenMPSupport> </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> @@ -141,7 +142,8 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'"> <ClCompile> <AdditionalIncludeDirectories>..\Common\Src;..\Core\Src;..\..\..\Externals\SOIL;..\..\..\Externals\CLRun\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - </ClCompile> + <OpenMPSupport>false</OpenMPSupport> + </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> @@ -183,6 +185,7 @@ <ClCompile Include="Src\DLCache.cpp" /> <ClCompile Include="Src\EmuWindow.cpp" /> <ClCompile Include="Src\Fifo.cpp" /> + <ClCompile Include="Src\FPSCounter.cpp" /> <ClCompile Include="Src\FramebufferManagerBase.cpp" /> <ClCompile Include="Src\HiresTextures.cpp" /> <ClCompile Include="Src\ImageWrite.cpp" /> @@ -228,6 +231,7 @@ <ClInclude Include="Src\DLCache.h" /> <ClInclude Include="Src\EmuWindow.h" /> <ClInclude Include="Src\Fifo.h" /> + <ClInclude Include="Src\FPSCounter.h" /> <ClInclude Include="Src\FramebufferManagerBase.h" /> <ClInclude Include="Src\HiresTextures.h" /> <ClInclude Include="Src\ImageWrite.h" /> diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index c933fbc939..e7019f17ed 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -119,6 +119,9 @@ <ClCompile Include="Src\LightingShaderGen.cpp"> <Filter>Shader Generators</Filter> </ClCompile> + <ClCompile Include="Src\FPSCounter.cpp"> + <Filter>Util</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="Src\CommandProcessor.h" /> @@ -246,6 +249,9 @@ <ClInclude Include="Src\LightingShaderGen.h"> <Filter>Shader Generators</Filter> </ClInclude> + <ClInclude Include="Src\FPSCounter.h"> + <Filter>Util</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="CMakeLists.txt" /> |
