diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2012-03-22 15:21:52 +0100 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2012-03-22 15:21:52 +0100 |
| commit | 0ffc12bbfd6ac44b3030ec30f400a58e951087b7 (patch) | |
| tree | 53a6fac9ec79bcd71fe2046d8fb579478da12fd2 /Source/Plugins | |
| parent | 006923e871e496a7c6c0fe9ba76da4ee939ce14e (diff) | |
| parent | d95e31af3f779bfa3141047e8b6275e1fd2e4bbb (diff) | |
Merge branch 'master' into zcomploc-support
Conflicts:
Source/Core/VideoCommon/Src/PixelShaderGen.cpp
Diffstat (limited to 'Source/Plugins')
47 files changed, 679 insertions, 729 deletions
diff --git a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj index f1f4d40457..2903bd0550 100644 --- a/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj +++ b/Source/Plugins/Plugin_VideoDX11/Plugin_VideoDX11.vcxproj @@ -46,7 +46,7 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> + <WholeProgramOptimization>false</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -57,7 +57,6 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp index 81a4cf96a6..8ee8081b2c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DUtil.cpp @@ -595,7 +595,7 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, // only upload the data to VRAM if it changed if (stsq_observer || - memcmp(rDest, &tex_sub_quad_data.rdest, sizeof(rDest)) != 0 || + memcmp(rDest, &tex_sub_quad_data.rdest, sizeof(*rDest)) != 0 || tex_sub_quad_data.u1 != u1 || tex_sub_quad_data.v1 != v1 || tex_sub_quad_data.u2 != u2 || tex_sub_quad_data.v2 != v2 || tex_sub_quad_data.G != G) { diff --git a/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp index 25f3712eb1..3afd38a2e1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp @@ -187,14 +187,15 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth, p = GenerateVSOutputStruct(p, components, API_D3D11); p += sprintf(p, "\n%s", LINE_GS_COMMON); - std::stringstream numTexCoordsStr; - numTexCoordsStr << xfregs.numTexGen.numTexGens; + std::stringstream numTexCoordsStream; + numTexCoordsStream << xfregs.numTexGen.numTexGens; INFO_LOG(VIDEO, "Compiling line geometry shader for components 0x%.08X (num texcoords %d)", components, xfregs.numTexGen.numTexGens); + const std::string& numTexCoordsStr = numTexCoordsStream.str(); D3D_SHADER_MACRO macros[] = { - { "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() }, + { "NUM_TEXCOORDS", numTexCoordsStr.c_str() }, { NULL, NULL } }; ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp index 5418923bf8..fe33c4db80 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp @@ -41,6 +41,7 @@ namespace DX11 PixelShaderCache::PSCache PixelShaderCache::PixelShaders; const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry; +PIXELSHADERUID PixelShaderCache::last_uid; LinearDiskCache<PIXELSHADERUID, u8> g_ps_disk_cache; @@ -412,6 +413,11 @@ void PixelShaderCache::Init() SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); PixelShaderCacheInserter inserter; g_ps_disk_cache.OpenAndRead(cache_filename, inserter); + + if (g_Config.bEnableShaderDebugging) + Clear(); + + last_entry = NULL; } // ONLY to be used during shutdown. @@ -420,6 +426,8 @@ void PixelShaderCache::Clear() for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++) iter->second.Destroy(); PixelShaders.clear(); + + last_entry = NULL; } // Used in Swap() when AA mode has changed @@ -454,28 +462,31 @@ void PixelShaderCache::Shutdown() bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) { PIXELSHADERUID uid; - GetPixelShaderId(&uid, dstAlphaMode); + GetPixelShaderId(&uid, dstAlphaMode, components); // Check if the shader is already set - if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount) + if (last_entry) { - PSCache::const_iterator iter = PixelShaders.find(uid); - GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); - return (iter != PixelShaders.end() && iter->second.shader); + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); + ValidatePixelShaderIDs(API_D3D11, last_entry->safe_uid, last_entry->code, dstAlphaMode, components); + return (last_entry->shader != NULL); + } } - memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID)); + last_uid = uid; // Check if the shader is already in the cache PSCache::iterator iter; iter = PixelShaders.find(uid); if (iter != PixelShaders.end()) { - iter->second.frameCount = frameCount; const PSCacheEntry &entry = iter->second; last_entry = &entry; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); + ValidatePixelShaderIDs(API_D3D11, entry.safe_uid, entry.code, dstAlphaMode, components); return (entry.shader != NULL); } @@ -485,36 +496,38 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) D3DBlob* pbytecode; if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode)) { - PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_ps_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); - g_ps_disk_cache.Sync(); - bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); + bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); pbytecode->Release(); + + if (g_ActiveConfig.bEnableShaderDebugging && success) + { + PixelShaders[uid].code = code; + GetSafePixelShaderId(&PixelShaders[uid].safe_uid, dstAlphaMode, components); + } + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return result; + return success; } bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen) { ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen); if (shader == NULL) - { - PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__); return false; - } + // TODO: Somehow make the debug name a bit more specific D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache"); // Make an entry in the table PSCacheEntry newentry; newentry.shader = shader; - newentry.frameCount = frameCount; PixelShaders[uid] = newentry; last_entry = &PixelShaders[uid]; @@ -539,20 +552,22 @@ static const unsigned int ps_constant_offset_table[] = { 16, 20, 24, 28, // C_KCOLORS, 16 32, // C_ALPHA, 4 36, 40, 44, 48, 52, 56, 60, 64, // C_TEXDIMS, 32 - 68, 72, // C_ZBIAS, 8 - 76, 80, // C_INDTEXSCALE, 8 - 84, 88, 92, 96, 100, 104, // C_INDTEXMTX, 24 - 108, 112, 116, // C_FOG, 12 - 120, 124, 128, 132, 136, // C_PLIGHTS0, 20 - 140, 144, 148, 152, 156, // C_PLIGHTS1, 20 - 160, 164, 168, 172, 176, // C_PLIGHTS2, 20 - 180, 184, 188, 192, 196, // C_PLIGHTS3, 20 - 200, 204, 208, 212, 216, // C_PLIGHTS4, 20 - 220, 224, 228, 232, 236, // C_PLIGHTS5, 20 - 240, 244, 248, 252, 256, // C_PLIGHTS6, 20 - 260, 264, 268, 272, 276, // C_PLIGHTS7, 20 - 280, 284, 288, 292 // C_PMATERIALS, 16 + 68, 72, 76, 80, // C_VTEXSCALE, 16 (unused) + 84, 88, // C_ZBIAS, 8 + 92, 96, // C_INDTEXSCALE, 8 + 100, 104, 108, 112, 116, 120, // C_INDTEXMTX, 24 + 124, 128, 132, // C_FOG, 12 + 136, 140, 144, 148, 152, // C_PLIGHTS0, 20 + 156, 160, 164, 168, 172, // C_PLIGHTS1, 20 + 176, 180, 184, 188, 192, // C_PLIGHTS2, 20 + 196, 200, 204, 208, 212, // C_PLIGHTS3, 20 + 216, 220, 224, 228, 232, // C_PLIGHTS4, 20 + 236, 240, 244, 248, 252, // C_PLIGHTS5, 20 + 256, 260, 264, 268, 272, // C_PLIGHTS6, 20 + 276, 280, 284, 288, 292, // C_PLIGHTS7, 20 + 296, 300, 304, 308, // C_PMATERIALS, 16 }; + void Renderer::SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { psconstants[ps_constant_offset_table[const_number] ] = f1; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h index 046f551657..874a47e4c1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h @@ -17,11 +17,12 @@ #pragma once -#include <map> +#include "PixelShaderGen.h" #include <d3d11.h> -class PIXELSHADERUID; +#include <map> + enum DSTALPHA_MODE; namespace DX11 @@ -52,9 +53,11 @@ private: struct PSCacheEntry { ID3D11PixelShader* shader; - int frameCount; - PSCacheEntry() : shader(NULL), frameCount(0) {} + PIXELSHADERUIDSAFE safe_uid; + std::string code; + + PSCacheEntry() : shader(NULL) {} void Destroy() { SAFE_RELEASE(shader); } }; @@ -62,6 +65,7 @@ private: static PSCache PixelShaders; static const PSCacheEntry* last_entry; + static PIXELSHADERUID last_uid; }; } // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp index fcf3315802..ad23786610 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp @@ -181,14 +181,15 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize, p = GenerateVSOutputStruct(p, components, API_D3D11); p += sprintf(p, "\n%s", POINT_GS_COMMON); - std::stringstream numTexCoordsStr; - numTexCoordsStr << xfregs.numTexGen.numTexGens; + std::stringstream numTexCoordsStream; + numTexCoordsStream << xfregs.numTexGen.numTexGens; INFO_LOG(VIDEO, "Compiling point geometry shader for components 0x%.08X (num texcoords %d)", components, xfregs.numTexGen.numTexGens); + const std::string& numTexCoordsStr = numTexCoordsStream.str(); D3D_SHADER_MACRO macros[] = { - { "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() }, + { "NUM_TEXCOORDS", numTexCoordsStr.c_str() }, { NULL, NULL } }; ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index d0756bfa98..69f0d0215a 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -42,6 +42,8 @@ #include "Movie.h" #include "Television.h" #include "Host.h" +#include "BPFunctions.h" +#include "AVIDump.h" namespace DX11 { @@ -61,6 +63,8 @@ ID3D11BlendState* resetblendstate = NULL; ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11RasterizerState* resetraststate = NULL; +static ID3D11Texture2D* s_screenshot_texture = NULL; + // GX pipeline state struct { @@ -295,9 +299,14 @@ void SetupDeviceObjects() hr = D3D::device->CreateRasterizerState(&rastdesc, &resetraststate); CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState"); D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState"); + + D3D11_TEXTURE2D_DESC scrtex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE); + hr = D3D::device->CreateTexture2D(&scrtex_desc, NULL, &s_screenshot_texture); + CHECK(hr==S_OK, "Create screenshot staging texture"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)s_screenshot_texture, "staging screenshot texture"); } -// Kill off all POOL_DEFAULT device objects. +// Kill off all device objects void TeardownDeviceObjects() { delete g_framebuffer_manager; @@ -313,6 +322,7 @@ void TeardownDeviceObjects() SAFE_RELEASE(resetblendstate); SAFE_RELEASE(resetdepthstate); SAFE_RELEASE(resetraststate); + SAFE_RELEASE(s_screenshot_texture); s_television.Shutdown(); } @@ -343,6 +353,7 @@ Renderer::Renderer() SetupDeviceObjects(); + // Setup GX pipeline state memset(&gx_state.blenddc, 0, sizeof(gx_state.blenddc)); gx_state.blenddc.AlphaToCoverageEnable = FALSE; @@ -444,51 +455,9 @@ bool Renderer::CheckForResize() return false; } -bool Renderer::SetScissorRect() +void Renderer::SetScissorRect(const TargetRectangle& rc) { - TargetRectangle rc; - GetScissorRect(rc); - - if (rc.left < 0) rc.left = 0; - if (rc.right < 0) rc.right = 0; - if (rc.top < 0) rc.top = 0; - if (rc.bottom < 0) rc.bottom = 0; - - if (rc.left > EFB_WIDTH) rc.left = EFB_WIDTH; - if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH; - if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT; - if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT; - - rc.left = EFBToScaledX(rc.left); - rc.right = EFBToScaledX(rc.right); - rc.top = EFBToScaledY(rc.top); - rc.bottom = EFBToScaledY(rc.bottom); - - if (rc.left > rc.right) - { - int temp = rc.right; - rc.right = rc.left; - rc.left = temp; - } - if (rc.top > rc.bottom) - { - int temp = rc.bottom; - rc.bottom = rc.top; - rc.top = temp; - } - - if (rc.right >= rc.left && rc.bottom >= rc.top) - { - D3D::context->RSSetScissorRects(1, rc.AsRECT()); - return true; - } - else - { - //WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); - *rc.AsRECT() = CD3D11_RECT(0.f, 0.f, s_target_width, s_target_height); - D3D::context->RSSetScissorRects(1, rc.AsRECT()); - return false; - } + D3D::context->RSSetScissorRects(1, rc.AsRECT()); } void Renderer::SetColorMask() @@ -726,15 +695,18 @@ void Renderer::UpdateViewport(Matrix44& vpCorrection) int Ht = intendedHt; if (Y + Ht > GetTargetHeight()) Ht = GetTargetHeight() - Y; - + // If GX viewport is off the render target, we must clamp our viewport // within the bounds. Use the correction matrix to compensate. ViewportCorrectionMatrix(vpCorrection, - intendedX, intendedY, intendedWd, intendedHt, - X, Y, Wd, Ht); + (float)intendedX, (float)intendedY, + (float)intendedWd, (float)intendedHt, + (float)X, (float)Y, + (float)Wd, (float)Ht); // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work - D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht, + D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)X, (float)Y, + (float)Wd, (float)Ht, 0.f, // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f; 1.f); // xfregs.viewport.farZ / 16777216.0f; D3D::context->RSSetViewports(1, &vp); @@ -779,7 +751,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(true); else { - PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype); + ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype); return; } @@ -876,15 +848,11 @@ void Renderer::SetBlendMode(bool forceUpdate) bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc) { // copy back buffer to system memory - ID3D11Texture2D* buftex; - D3D11_TEXTURE2D_DESC tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE); - HRESULT hr = D3D::device->CreateTexture2D(&tex_desc, NULL, &buftex); - if (FAILED(hr)) PanicAlert("Failed to create screenshot buffer texture"); - D3D::context->CopyResource(buftex, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); + D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves D3D11_MAPPED_SUBRESOURCE map; - D3D::context->Map(buftex, 0, D3D11_MAP_READ_WRITE, 0, &map); + D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); for (unsigned int y = 0; y < D3D::GetBackBufferHeight(); ++y) { u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; @@ -894,21 +862,38 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle ptr += 4; } } - D3D::context->Unmap(buftex, 0); + D3D::context->Unmap(s_screenshot_texture, 0); // ready to be saved - hr = PD3DX11SaveTextureToFileA(D3D::context, buftex, D3DX11_IFF_PNG, filename.c_str()); - buftex->Release(); + HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str()); return SUCCEEDED(hr); } +void formatBufferDump(const char *in, char *out, int w, int h, int p) +{ + for (int y = 0; y < h; ++y) + { + const u8 *line = (u8*)(in + (h - y - 1) * p); + for (int x = 0; x < w; ++x) + { + out[0] = line[2]; + out[1] = line[1]; + out[2] = line[0]; + out += 3; + line += 4; + } + } +} // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -920,6 +905,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -1025,6 +1013,64 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons s_bScreenshot = false; } + // Dump frames + static int w = 0, h = 0; + if (g_ActiveConfig.bDumpFrames) + { + static int s_recordWidth; + static int s_recordHeight; + + D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); + if (!bLastFrameDumped) + { + s_recordWidth = dst_rect.GetWidth(); + s_recordHeight = dst_rect.GetHeight(); + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); + if (!bAVIDumping) + { + PanicAlert("Error dumping frames to AVI."); + } + else + { + char msg [255]; + sprintf_s(msg,255, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), s_recordWidth, s_recordHeight); + OSD::AddMessage(msg, 2000); + } + } + if (bAVIDumping) + { + D3D11_MAPPED_SUBRESOURCE map; + D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map); + + if (!frame_data || w != s_recordWidth || h != s_recordHeight) + { + delete[] frame_data; + frame_data = new char[3 * s_recordWidth * s_recordHeight]; + w = s_recordWidth; + h = s_recordHeight; + } + char* source_ptr = (char*)map.pData + dst_rect.left*4 + dst_rect.top*map.RowPitch; + formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch); + AVIDump::AddFrame(frame_data); + D3D::context->Unmap(s_screenshot_texture, 0); + } + bLastFrameDumped = true; + } + else + { + if (bLastFrameDumped && bAVIDumping) + { + SAFE_DELETE_ARRAY(frame_data); + w = h = 0; + + AVIDump::Stop(); + bAVIDumping = false; + OSD::AddMessage("Stop dumping frames to AVI", 2000); + } + bLastFrameDumped = false; + } + // Finish up the current frame, print some stats if (g_ActiveConfig.bShowFPS) { @@ -1063,12 +1109,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons DLCache::ProgressiveCleanup(); TextureCache::Cleanup(); - // reload textures if these settings changed - if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache || - g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) + // Reload textures if this settings changes + if (g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) TextureCache::Invalidate(false); - // Enable any configuration changes + // Enable configuration changes UpdateActiveConfig(); SetWindowSize(fbWidth, fbHeight); @@ -1163,7 +1208,7 @@ void Renderer::RestoreAPIState() D3D::stateman->PopDepthState(); D3D::stateman->PopRasterizerState(); VertexShaderManager::SetViewportChanged(); - SetScissorRect(); + BPFunctions::SetScissor(); } void Renderer::ApplyState(bool bUseDstAlpha) @@ -1385,4 +1430,4 @@ void Renderer::SetInterlacingMode() // TODO } -} // namespace DX11
\ No newline at end of file +} // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.h b/Source/Plugins/Plugin_VideoDX11/Src/Render.h index 5d1c24bc23..8f6c78fae1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.h @@ -15,7 +15,7 @@ public: void SetColorMask(); void SetBlendMode(bool forceUpdate); - bool SetScissorRect(); + void SetScissorRect(const TargetRectangle& rc); void SetGenerationMode(); void SetDepthMode(); void SetLogicOpMode(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 39018c83bc..e59fbd496e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -102,12 +102,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo bool isIntensity, bool scaleByHalf, unsigned int cbufid, const float *colmat) { - if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { g_renderer->ResetAPIState(); // stretch picture with increased internal resolution - const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtualW, (float)virtualH); + const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtual_width, (float)virtual_height); D3D::context->RSSetViewports(1, &vp); // set transformation @@ -149,17 +149,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (!g_ActiveConfig.bCopyEFBToTexture) { u8* dst = Memory::GetPointer(dstAddr); - size_t encodeSize = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf); - hash = GetHash64(dst, encodeSize, g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (g_ActiveConfig.bEFBCopyCacheEnable) - { - // If the texture in RAM is already in the texture cache, - // do not copy it again as it has not changed. - if (TextureCache::Find(dstAddr, hash)) - return; - } + size_t encoded_size = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf); + + hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); - TextureCache::MakeRangeDynamic(dstAddr, encodeSize); + // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date + if (!g_ActiveConfig.bEFBCopyCacheEnable) + TextureCache::MakeRangeDynamic(addr, (u32)encoded_size); + else if (!TextureCache::Find(addr, hash)) + TextureCache::MakeRangeDynamic(addr, (u32)encoded_size); } } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index e1e40047e4..1079863347 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -228,12 +228,13 @@ void VertexManager::vFlush() 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.texMode1[i&3].max_lod >> 4)); + tex.texMode1[i&3].max_lod >> 4, + tex.texImage1[i&3].image_type); if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D11); } else ERROR_LOG(VIDEO, "error loading texture"); @@ -242,7 +243,7 @@ void VertexManager::vFlush() // set global constants VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); + PixelShaderManager::SetConstants(API_D3D11); bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp index 041caba28c..d727ce1ebf 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp @@ -37,6 +37,7 @@ namespace DX11 { VertexShaderCache::VSCache VertexShaderCache::vshaders; const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; +VERTEXSHADERUID VertexShaderCache::last_uid; static ID3D11VertexShader* SimpleVertexShader = NULL; static ID3D11VertexShader* ClearVertexShader = NULL; @@ -174,6 +175,11 @@ void VertexShaderCache::Init() SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); + + if (g_Config.bEnableShaderDebugging) + Clear(); + + last_entry = NULL; } void VertexShaderCache::Clear() @@ -181,6 +187,8 @@ void VertexShaderCache::Clear() for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter) iter->second.Destroy(); vshaders.clear(); + + last_entry = NULL; } void VertexShaderCache::Shutdown() @@ -202,22 +210,26 @@ bool VertexShaderCache::SetShader(u32 components) { VERTEXSHADERUID uid; GetVertexShaderId(&uid, components); - if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) + if (last_entry) { - GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return (vshaders[uid].shader != NULL); + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); + ValidateVertexShaderIDs(API_D3D11, last_entry->safe_uid, last_entry->code, components); + return (last_entry->shader != NULL); + } } - memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); + last_uid = uid; VSCache::iterator iter = vshaders.find(uid); if (iter != vshaders.end()) { - iter->second.frameCount = frameCount; const VSCacheEntry &entry = iter->second; last_entry = &entry; GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); + ValidateVertexShaderIDs(API_D3D11, entry.safe_uid, entry.code, components); return (entry.shader != NULL); } @@ -228,34 +240,36 @@ bool VertexShaderCache::SetShader(u32 components) if (pbytecode == NULL) { - PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code); GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } g_vs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); - g_vs_disk_cache.Sync(); - bool result = InsertByteCode(uid, pbytecode); + bool success = InsertByteCode(uid, pbytecode); pbytecode->Release(); + + if (g_ActiveConfig.bEnableShaderDebugging && success) + { + vshaders[uid].code = code; + GetSafeVertexShaderId(&vshaders[uid].safe_uid, components); + } + GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return result; + return success; } bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob) { ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob); if (shader == NULL) - { - PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__); return false; - } + // TODO: Somehow make the debug name a bit more specific D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache"); // Make an entry in the table VSCacheEntry entry; entry.shader = shader; - entry.frameCount = frameCount; entry.SetByteCode(bcodeblob); vshaders[uid] = entry; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h index 3c7dadd3e7..6d9537606a 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h @@ -18,12 +18,12 @@ #ifndef _VERTEXSHADERCACHE_H #define _VERTEXSHADERCACHE_H -#include <map> +#include "VertexShaderGen.h" #include "D3DBase.h" #include "D3DBlob.h" -class VERTEXSHADERUID; +#include <map> namespace DX11 { @@ -51,9 +51,11 @@ private: { ID3D11VertexShader* shader; D3DBlob* bytecode; // needed to initialize the input layout - int frameCount; - VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {} + VERTEXSHADERUIDSAFE safe_uid; + std::string code; + + VSCacheEntry() : shader(NULL), bytecode(NULL) {} void SetByteCode(D3DBlob* blob) { SAFE_RELEASE(bytecode); @@ -70,6 +72,7 @@ private: static VSCache vshaders; static const VSCacheEntry* last_entry; + static VERTEXSHADERUID last_uid; }; } // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index ba93890e2b..ba3a67108b 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -68,9 +68,9 @@ unsigned int VideoBackend::PeekMessages() void VideoBackend::UpdateFPSDisplay(const char *text) { - char temp[512]; - sprintf_s(temp, sizeof temp, "%s | DX11 | %s", scm_rev_str, text); - SetWindowTextA(EmuWindow::GetWnd(), temp); + TCHAR temp[512]; + swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs | DX11 | %hs"), scm_rev_str, text); + EmuWindow::SetWindowText(temp); } std::string VideoBackend::GetName() @@ -150,6 +150,7 @@ void VideoBackend::ShowConfig(void *_hParent) bool VideoBackend::Initialize(void *&window_handle) { + InitializeShared(); InitBackendInfo(); frameCount = 0; diff --git a/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj b/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj index 838004a605..604fea8a2b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj +++ b/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj @@ -46,7 +46,7 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> + <WholeProgramOptimization>false</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -57,7 +57,6 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp index de610eab39..ff3f68a6cd 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp @@ -28,7 +28,8 @@ D3DXCOMPILESHADERTYPE PD3DXCompileShader = NULL; namespace DX9 { - +static char vsVersions[5][7] = {"ERROR", "vs_1_4", "vs_2_a", "vs_3_0", "vs_4_0"}; +static char psVersions[5][7] = {"ERROR", "ps_1_4", "ps_2_a", "ps_3_0", "ps_4_0"}; // D3DX HINSTANCE hD3DXDll = NULL; int d3dx_dll_ref = 0; @@ -55,6 +56,7 @@ static bool auto_depth_stencil = false; #define VENDOR_NVIDIA 4318 #define VENDOR_ATI 4098 +#define VENDOR_INTEL 32902 bool bFrameInProgress = false; @@ -112,6 +114,10 @@ bool IsATIDevice() { return GetCurAdapter().ident.VendorId == VENDOR_ATI; } +bool IsIntelDevice() +{ + return GetCurAdapter().ident.VendorId == VENDOR_INTEL; +} HRESULT Init() @@ -139,6 +145,11 @@ HRESULT Init() int adapter = g_Config.iAdapter; D3D->GetDeviceCaps((adapter >= 0 && adapter < std::min(MAX_ADAPTERS, numAdapters)) ? adapter : D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); Enumerate(); + if(IsIntelDevice()){ + // Murder the a because Intel doesn't support 2.0a because the 'a' part was a ATI and Nvidia war going on + psVersions[2][5] = '0'; + vsVersions[2][5] = '0'; + } return S_OK; } @@ -522,16 +533,14 @@ D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format) const char *VertexShaderVersionString() { - static const char *versions[5] = {"ERROR", "vs_1_4", "vs_2_a", "vs_3_0", "vs_4_0"}; int version = ((D3D::caps.VertexShaderVersion >> 8) & 0xFF); - return versions[std::min(4, version)]; + return vsVersions[std::min(4, version)]; } const char *PixelShaderVersionString() { - static const char *versions[5] = {"ERROR", "ps_1_4", "ps_2_a", "ps_3_0", "ps_4_0"}; int version = ((D3D::caps.PixelShaderVersion >> 8) & 0xFF); - return versions[std::min(4, version)]; + return psVersions[std::min(4, version)]; } LPDIRECT3DSURFACE9 GetBackBufferSurface() diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h index f4a5244dbe..d1e7eeaa91 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h @@ -47,6 +47,7 @@ namespace D3D #define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))) bool IsATIDevice(); +bool IsIntelDevice(); HRESULT Init(); HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth); void Close(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp index cfb74df225..9510ad444c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp @@ -383,7 +383,7 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture, float v2=((float)rSource->bottom) * sh; float g = 1.0f/Gamma; - struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = { + const struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = { {-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh, g}, {-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh, g}, { 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh, g}, @@ -434,15 +434,13 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture, // Fills a certain area of the current render target with the specified color // Z buffer disabled; destination coordinates normalized to (-1;1) -void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, float x2, float y2) +void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2) { - float dw = 1.f / (float)DestWidth; - float dh = 1.f / (float)DestHeight; struct CQVertex { float x, y, z, rhw; u32 col; } coords[4] = { - { x1-dw, y2+dh, 0.f, 1.f, Color }, - { x2-dw, y2+dh, 0.f, 1.f, Color }, - { x1-dw, y1+dh, 0.f, 1.f, Color }, - { x2-dw, y1+dh, 0.f, 1.f, Color }, + { x1, y2, 0.f, 1.f, Color }, + { x2, y2, 0.f, 1.f, Color }, + { x1, y1, 0.f, 1.f, Color }, + { x2, y1, 0.f, 1.f, Color }, }; dev->SetVertexShader(VertexShaderCache::GetClearVertexShader()); dev->SetPixelShader(PixelShaderCache::GetClearProgram()); @@ -451,15 +449,13 @@ void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, RestoreShaders(); } -void drawClearQuad(int DestWidth, int DestHeight, u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader) +void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader) { - float dw = 1.f / (float)DestWidth; - float dh = 1.f / (float)DestHeight; struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = { - {-1.0f-dw, 1.0f+dh, z, 1.0f, Color}, - { 1.0f-dw, 1.0f+dh, z, 1.0f, Color}, - { 1.0f-dw, -1.0f+dh, z, 1.0f, Color}, - {-1.0f-dw, -1.0f+dh, z, 1.0f, Color} + {-1.0f, 1.0f, z, 1.0f, Color}, + { 1.0f, 1.0f, z, 1.0f, Color}, + { 1.0f, -1.0f, z, 1.0f, Color}, + {-1.0f, -1.0f, z, 1.0f, Color} }; dev->SetVertexShader(Vshader); dev->SetPixelShader(PShader); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h index 93e60f938b..882f112ece 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h @@ -82,8 +82,8 @@ namespace D3D IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader, float Gamma = 1.0f); - void drawClearQuad(int DestWidth, int DestHeight, u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader); - void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, float x2, float y2); + void drawClearQuad(u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader); + void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2); void SaveRenderStates(); void RestoreRenderStates(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index f76837837d..f66d096ab6 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -43,6 +43,7 @@ namespace DX9 PixelShaderCache::PSCache PixelShaderCache::PixelShaders; const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry; +PIXELSHADERUID PixelShaderCache::last_uid; static LinearDiskCache<PIXELSHADERUID, u8> g_ps_disk_cache; static std::set<u32> unique_shaders; @@ -233,6 +234,8 @@ static LPDIRECT3DPIXELSHADER9 CreateCopyShader(int copyMatrixType, int depthConv void PixelShaderCache::Init() { + last_entry = NULL; + //program used for clear screen { char pprog[3072]; @@ -283,6 +286,9 @@ void PixelShaderCache::Init() SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); PixelShaderCacheInserter inserter; g_ps_disk_cache.OpenAndRead(cache_filename, inserter); + + if (g_Config.bEnableShaderDebugging) + Clear(); } // ONLY to be used during shutdown. @@ -292,7 +298,7 @@ void PixelShaderCache::Clear() iter->second.Destroy(); PixelShaders.clear(); - memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid)); + last_entry = NULL; } void PixelShaderCache::Shutdown() @@ -326,41 +332,47 @@ void PixelShaderCache::Shutdown() bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) { + const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30; PIXELSHADERUID uid; - GetPixelShaderId(&uid, dstAlphaMode); + GetPixelShaderId(&uid, dstAlphaMode, components); // Check if the shader is already set - if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount) + if (last_entry) { - PSCache::const_iterator iter = PixelShaders.find(uid); - GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return (iter != PixelShaders.end() && iter->second.shader); + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); + ValidatePixelShaderIDs(api, last_entry->safe_uid, last_entry->code, dstAlphaMode, components); + return last_entry->shader != NULL; + } } - memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID)); + last_uid = uid; // Check if the shader is already in the cache PSCache::iterator iter; iter = PixelShaders.find(uid); if (iter != PixelShaders.end()) { - iter->second.frameCount = frameCount; const PSCacheEntry &entry = iter->second; last_entry = &entry; if (entry.shader) D3D::SetPixelShader(entry.shader); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); + ValidatePixelShaderIDs(api, entry.safe_uid, entry.code, dstAlphaMode, components); return (entry.shader != NULL); } - // Need to compile a new shader - const char *code = GeneratePixelShaderCode(dstAlphaMode, ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30, components); + const char *code = GeneratePixelShaderCode(dstAlphaMode, api, components); - u32 code_hash = HashAdler32((const u8 *)code, strlen(code)); - unique_shaders.insert(code_hash); - SETSTAT(stats.numUniquePixelShaders, unique_shaders.size()); + if (g_ActiveConfig.bEnableShaderDebugging) + { + u32 code_hash = HashAdler32((const u8 *)code, strlen(code)); + unique_shaders.insert(code_hash); + SETSTAT(stats.numUniquePixelShaders, unique_shaders.size()); + } #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { @@ -381,14 +393,19 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) // Insert the bytecode into the caches g_ps_disk_cache.Append(uid, bytecode, bytecodelen); - g_ps_disk_cache.Sync(); // And insert it into the shader cache. - bool result = InsertByteCode(uid, bytecode, bytecodelen, true); + bool success = InsertByteCode(uid, bytecode, bytecodelen, true); delete [] bytecode; + if (g_ActiveConfig.bEnableShaderDebugging && success) + { + PixelShaders[uid].code = code; + GetSafePixelShaderId(&PixelShaders[uid].safe_uid, dstAlphaMode, components); + } + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return result; + return success; } bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) @@ -398,7 +415,6 @@ bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytec // Make an entry in the table PSCacheEntry newentry; newentry.shader = shader; - newentry.frameCount = frameCount; PixelShaders[uid] = newentry; last_entry = &PixelShaders[uid]; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h index 2f3c552e2a..c771984d36 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h @@ -40,9 +40,11 @@ private: { LPDIRECT3DPIXELSHADER9 shader; bool owns_shader; - int frameCount; - PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {} + PIXELSHADERUIDSAFE safe_uid; + std::string code; + + PSCacheEntry() : shader(NULL), owns_shader(true) {} void Destroy() { if (shader && owns_shader) @@ -55,6 +57,7 @@ private: static PSCache PixelShaders; static const PSCacheEntry *last_entry; + static PIXELSHADERUID last_uid; static void Clear(); public: diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index e333cbc168..a5aaa6485b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -53,18 +53,13 @@ #include "Debugger.h" #include "Core.h" #include "Movie.h" +#include "BPFunctions.h" namespace DX9 { static int s_fps = 0; -static int s_recordWidth; -static int s_recordHeight; - -static bool s_bLastFrameDumped; -static bool s_bAVIDumping; - static u32 s_blendMode; static u32 s_LastAA; static bool IS_AMD; @@ -296,9 +291,6 @@ Renderer::Renderer() // Make sure to use valid texture sizes D3D::FixTextureSize(s_target_width, s_target_height); - s_bLastFrameDumped = false; - s_bAVIDumping = false; - // We're not using fixed function. // Let's just set the matrices to identity to be sure. D3DXMATRIX mtx; @@ -341,10 +333,6 @@ Renderer::~Renderer() D3D::Present(); D3D::Close(); - if (s_bAVIDumping) - { - AVIDump::Stop(); - } delete[] st; } @@ -426,55 +414,9 @@ bool Renderer::CheckForResize() return false; } -bool Renderer::SetScissorRect() +void Renderer::SetScissorRect(const TargetRectangle& rc) { - TargetRectangle rc; - GetScissorRect(rc); - - if (rc.left < 0) rc.left = 0; - if (rc.right < 0) rc.right = 0; - if (rc.top < 0) rc.top = 0; - if (rc.bottom < 0) rc.bottom = 0; - - if (rc.left > EFB_WIDTH) rc.left = EFB_WIDTH; - if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH; - if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT; - if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT; - - if (rc.left > rc.right) - { - int temp = rc.right; - rc.right = rc.left; - rc.left = temp; - } - if (rc.top > rc.bottom) - { - int temp = rc.bottom; - rc.bottom = rc.top; - rc.top = temp; - } - - rc.left = EFBToScaledX(rc.left); - rc.top = EFBToScaledY(rc.top); - rc.right = EFBToScaledX(rc.right); - rc.bottom = EFBToScaledY(rc.bottom); - - // Check that the coordinates are good - if (rc.right != rc.left && rc.bottom != rc.top) - { - D3D::dev->SetScissorRect(rc.AsRECT()); - return true; - } - else - { - //WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); - rc.left = 0; - rc.top = 0; - rc.right = s_target_width; - rc.bottom = s_target_height; - D3D::dev->SetScissorRect(rc.AsRECT()); - } - return false; + D3D::dev->SetScissorRect(rc.AsRECT()); } void Renderer::SetColorMask() @@ -680,7 +622,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { // TODO: Speed this up by batching pokes? ResetAPIState(); - D3D::drawColorQuad(GetTargetWidth(), GetTargetHeight(), poke_data, + D3D::drawColorQuad(poke_data, (float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f, - (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f, (float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f, @@ -805,7 +747,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE vp.MinZ = 0.0; vp.MaxZ = 1.0; D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); RestoreAPIState(); } @@ -819,7 +761,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(); else { - PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype); + ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype); return; } @@ -889,12 +831,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { - static char* data = 0; - static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && data) - AVIDump::AddFrame(data); + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -907,6 +848,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { + if (g_ActiveConfig.bDumpFrames && frame_data) + AVIDump::AddFrame(frame_data); + Core::Callback_VideoCopiedToXFB(false); return; } @@ -952,7 +896,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons vp.MinZ = 0.0f; vp.MaxZ = 1.0f; D3D::dev->SetViewport(&vp); - D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), 0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); + D3D::drawClearQuad(0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); } else { @@ -1072,15 +1016,21 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons SaveScreenshot(s_sScreenshotName, dst_rect); s_bScreenshot = false; } + + // Dump frames + static int w = 0, h = 0; if (g_ActiveConfig.bDumpFrames) { + static int s_recordWidth; + static int s_recordHeight; + HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface); - if (!s_bLastFrameDumped) + if (!bLastFrameDumped) { s_recordWidth = dst_rect.GetWidth(); s_recordHeight = dst_rect.GetHeight(); - s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); - if (!s_bAVIDumping) + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight); + if (!bAVIDumping) { PanicAlert("Error dumping frames to AVI."); } @@ -1092,40 +1042,40 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage(msg, 2000); } } - if (s_bAVIDumping) + if (bAVIDumping) { D3DLOCKED_RECT rect; if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, dst_rect.AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) { - if (!data || w != s_recordWidth || h != s_recordHeight) + if (!frame_data || w != s_recordWidth || h != s_recordHeight) { - free(data); - data = (char*)malloc(3 * s_recordWidth * s_recordHeight); + delete[] frame_data; + frame_data = new char[3 * s_recordWidth * s_recordHeight]; w = s_recordWidth; h = s_recordHeight; } - formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch); - AVIDump::AddFrame(data); + formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch); + AVIDump::AddFrame(frame_data); ScreenShootMEMSurface->UnlockRect(); } } - s_bLastFrameDumped = true; + bLastFrameDumped = true; } else { - if (s_bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && bAVIDumping) { - if (data) + if (frame_data) { - free(data); - data = 0; + delete[] frame_data; + frame_data = 0; w = h = 0; } AVIDump::Stop(); - s_bAVIDumping = false; + bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); } - s_bLastFrameDumped = false; + bLastFrameDumped = false; } // Finish up the current frame, print some stats @@ -1164,12 +1114,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons DLCache::ProgressiveCleanup(); TextureCache::Cleanup(); - // reload textures if these settings changed - if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache || - g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) + // Reload textures if these settings changed + if (g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) TextureCache::Invalidate(false); - // Enable any configuration changes + // Enable configuration changes UpdateActiveConfig(); SetWindowSize(fbWidth, fbHeight); @@ -1293,7 +1242,7 @@ void Renderer::RestoreAPIState() D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID); D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); VertexShaderManager::SetViewportChanged(); - SetScissorRect(); + BPFunctions::SetScissor(); if (bpmem.zmode.testenable) { D3D::SetRenderState(D3DRS_ZENABLE, TRUE); if (bpmem.zmode.updateenable) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.h b/Source/Plugins/Plugin_VideoDX9/Src/Render.h index b3c89f82f9..6e5198b3cd 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.h @@ -15,7 +15,7 @@ public: void SetColorMask(); void SetBlendMode(bool forceUpdate); - bool SetScissorRect(); + void SetScissorRect(const TargetRectangle& rc); void SetGenerationMode(); void SetDepthMode(); void SetLogicOpMode(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 7c741e08a9..2a3f12ddcf 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -21,6 +21,7 @@ #include "Statistics.h" #include "MemoryUtil.h" #include "Hash.h" +#include "HW/Memmap.h" #include "CommonPaths.h" #include "FileUtil.h" @@ -78,7 +79,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture(); - if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { LPDIRECT3DSURFACE9 Rendersurf = NULL; texture->GetSurfaceLevel(0, &Rendersurf); @@ -90,15 +91,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo // Stretch picture with increased internal resolution vp.X = 0; vp.Y = 0; - vp.Width = virtualW; - vp.Height = virtualH; + vp.Width = virtual_width; + vp.Height = virtual_height; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; D3D::dev->SetViewport(&vp); RECT destrect; - destrect.bottom = virtualH; + destrect.bottom = virtual_height; destrect.left = 0; - destrect.right = virtualW; + destrect.right = virtual_width; destrect.top = 0; PixelShaderManager::SetColorMatrix(colmat); // set transformation @@ -133,7 +134,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo D3D::drawShadedTexQuad(read_texture, &sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), - virtualW, virtualH, + virtual_width, virtual_height, // TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them? PixelShaderCache::GetDepthMatrixProgram(SSAAMode, (srcFormat == PIXELFMT_Z24) && bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8), VertexShaderCache::GetSimpleVertexShader(SSAAMode)); @@ -143,16 +144,25 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (!g_ActiveConfig.bCopyEFBToTexture) { - hash = TextureConverter::EncodeToRamFromTexture( - addr, - read_texture, - Renderer::GetTargetWidth(), - Renderer::GetTargetHeight(), - srcFormat == PIXELFMT_Z24, - isIntensity, - dstFormat, - scaleByHalf, - srcRect); + int encoded_size = TextureConverter::EncodeToRamFromTexture( + addr, + read_texture, + Renderer::GetTargetWidth(), + Renderer::GetTargetHeight(), + srcFormat == PIXELFMT_Z24, + isIntensity, + dstFormat, + scaleByHalf, + srcRect); + + u8* dst = Memory::GetPointer(addr); + hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date + if (!g_ActiveConfig.bEFBCopyCacheEnable) + TextureCache::MakeRangeDynamic(addr,encoded_size); + else if (!TextureCache::Find(addr, hash)) + TextureCache::MakeRangeDynamic(addr,encoded_size); } D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp index d14a3f29ea..7c38b154b9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.cpp @@ -252,10 +252,10 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr s_texConvReadSurface = TrnBuffers[index].ReadSurface; Rendersurf = TrnBuffers[index].RenderSurface; - + hr = D3D::dev->SetDepthStencilSurface(NULL); hr = D3D::dev->SetRenderTarget(0, Rendersurf); - + if (linearFilter) { D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); @@ -290,7 +290,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER); // .. and then read back the results. // TODO: make this less slow. - + hr = D3D::dev->GetRenderTargetData(Rendersurf,s_texConvReadSurface); D3DLOCKED_RECT drect; @@ -313,76 +313,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr hr = s_texConvReadSurface->UnlockRect(); } -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) -{ - u32 format = copyfmt; - - if (bFromZBuffer) - { - format |= _GX_TF_ZTF; - if (copyfmt == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) - format |= _GX_TF_CTF; - - LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format); - if (!texconv_shader) - return; - - u8 *dest_ptr = Memory::GetPointer(address); - - LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture(); - int width = (source.right - source.left) >> bScaleByHalf; - int height = (source.bottom - source.top) >> bScaleByHalf; - - int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); - - // Invalidate any existing texture covering this memory range. - // TODO - don't delete the texture if it already exists, just replace the contents. - TextureCache::InvalidateRange(address, size_in_bytes); - - u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; - u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; - u16 samples = TextureConversionShader::GetEncodedSampleCount(format); - - // only copy on cache line boundaries - // extra pixels are copied but not displayed in the resulting texture - s32 expandedWidth = (width + blkW) & (~blkW); - s32 expandedHeight = (height + blkH) & (~blkH); - - float sampleStride = bScaleByHalf ? 2.f : 1.f; - TextureConversionShader::SetShaderParameters( - (float)expandedWidth, - (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? - (float)Renderer::EFBToScaledX(source.left), - (float)Renderer::EFBToScaledY(source.top), - Renderer::EFBToScaledXf(sampleStride), - Renderer::EFBToScaledYf(sampleStride), - (float)Renderer::GetTargetWidth(), - (float)Renderer::GetTargetHeight()); - - TargetRectangle scaledSource; - scaledSource.top = 0; - scaledSource.bottom = expandedHeight; - scaledSource.left = 0; - scaledSource.right = expandedWidth / samples; - int cacheBytes = 32; - if ((format & 0x0f) == 6) - cacheBytes = 64; - - int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); - g_renderer->ResetAPIState(); - EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f); - D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface()); - g_renderer->RestoreAPIState(); -} - -u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) +int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; @@ -440,16 +371,7 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 So int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f); - u64 hash = GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (g_ActiveConfig.bEFBCopyCacheEnable) - { - // If the texture in RAM is already in the texture cache, do not copy it again as it has not changed. - if (TextureCache::Find(address, hash)) - return hash; - } - - TextureCache::MakeRangeDynamic(address,size_in_bytes); - return hash; + return size_in_bytes; // TODO: D3D11 is calculating this value differently! } void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma) @@ -490,7 +412,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE destTexture->GetSurfaceLevel(0,&Rendersurf); D3D::dev->SetDepthStencilSurface(NULL); D3D::dev->SetRenderTarget(0, Rendersurf); - + D3DVIEWPORT9 vp; // Stretch picture with increased internal resolution diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h index aa4757e4c9..4036f21447 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureConverter.h @@ -35,15 +35,13 @@ namespace TextureConverter void Init(); void Shutdown(); -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, - u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); - void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture); -u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); +// returns size of the encoded data (in bytes) +int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index d9c33b67ef..2083d4f1d8 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -137,12 +137,13 @@ void VertexManager::vFlush() 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.texMode1[i&3].max_lod >> 4)); + tex.texMode1[i&3].max_lod >> 4, + tex.texImage1[i&3].image_type); if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_D3D9); } else ERROR_LOG(VIDEO, "error loading texture"); @@ -151,7 +152,7 @@ void VertexManager::vFlush() // set global constants VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); + PixelShaderManager::SetConstants(API_D3D9); if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components)) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp index 5fc2b6dee2..e392cf3de0 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp @@ -38,6 +38,7 @@ namespace DX9 VertexShaderCache::VSCache VertexShaderCache::vshaders; const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; +VERTEXSHADERUID VertexShaderCache::last_uid; #define MAX_SSAA_SHADERS 3 @@ -151,6 +152,11 @@ void VertexShaderCache::Init() SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); + + if (g_Config.bEnableShaderDebugging) + Clear(); + + last_entry = NULL; } void VertexShaderCache::Clear() @@ -159,7 +165,7 @@ void VertexShaderCache::Clear() iter->second.Destroy(); vshaders.clear(); - memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid)); + last_entry = NULL; } void VertexShaderCache::Shutdown() @@ -184,23 +190,27 @@ bool VertexShaderCache::SetShader(u32 components) { VERTEXSHADERUID uid; GetVertexShaderId(&uid, components); - if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) + if (last_entry) { - GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return (vshaders[uid].shader != NULL); + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); + ValidateVertexShaderIDs(API_D3D9, last_entry->safe_uid, last_entry->code, components); + return (last_entry->shader != NULL); + } } - memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); + last_uid = uid; VSCache::iterator iter = vshaders.find(uid); if (iter != vshaders.end()) { - iter->second.frameCount = frameCount; const VSCacheEntry &entry = iter->second; last_entry = &entry; if (entry.shader) D3D::SetVertexShader(entry.shader); GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); + ValidateVertexShaderIDs(API_D3D9, entry.safe_uid, entry.code, components); return (entry.shader != NULL); } @@ -213,12 +223,16 @@ bool VertexShaderCache::SetShader(u32 components) return false; } g_vs_disk_cache.Append(uid, bytecode, bytecodelen); - g_vs_disk_cache.Sync(); - bool result = InsertByteCode(uid, bytecode, bytecodelen, true); + bool success = InsertByteCode(uid, bytecode, bytecodelen, true); + if (g_ActiveConfig.bEnableShaderDebugging && success) + { + vshaders[uid].code = code; + GetSafeVertexShaderId(&vshaders[uid].safe_uid, components); + } delete [] bytecode; GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return result; + return success; } bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) { @@ -227,7 +241,6 @@ bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *byt // Make an entry in the table VSCacheEntry entry; entry.shader = shader; - entry.frameCount = frameCount; vshaders[uid] = entry; last_entry = &vshaders[uid]; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h index b516f46f9a..c9c447e35b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h @@ -34,11 +34,11 @@ private: struct VSCacheEntry { LPDIRECT3DVERTEXSHADER9 shader; - int frameCount; -#if defined(_DEBUG) || defined(DEBUGFAST) + std::string code; -#endif - VSCacheEntry() : shader(NULL), frameCount(0) {} + VERTEXSHADERUIDSAFE safe_uid; + + VSCacheEntry() : shader(NULL) {} void Destroy() { if (shader) @@ -51,6 +51,7 @@ private: static VSCache vshaders; static const VSCacheEntry *last_entry; + static VERTEXSHADERUID last_uid; static void Clear(); public: diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 1d733f7dc3..6c52219f97 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -78,7 +78,7 @@ void VideoBackend::UpdateFPSDisplay(const char *text) { TCHAR temp[512]; swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs | DX9 | %hs"), scm_rev_str, text); - SetWindowText(EmuWindow::GetWnd(), temp); + EmuWindow::SetWindowText(temp); } std::string VideoBackend::GetName() @@ -132,6 +132,7 @@ void VideoBackend::ShowConfig(void* parent) bool VideoBackend::Initialize(void *&window_handle) { + InitializeShared(); InitBackendInfo(); frameCount = 0; diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt index c57106645f..b506087106 100644 --- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt @@ -22,8 +22,10 @@ if(wxWidgets_FOUND) set(LIBS ${LIBS} ${wxWidgets_LIBRARIES}) endif(wxWidgets_FOUND) -if(APPLE OR WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux") +if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(LIBS ${LIBS} Cg CgGL) +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + list(APPEND LIBS "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework") endif() if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj index d12f779d53..f782fd2c93 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj @@ -46,7 +46,7 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> + <WholeProgramOptimization>false</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> @@ -57,7 +57,6 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index bedcaa6245..cbdb702885 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -73,8 +73,9 @@ void OpenGL_SetWindowText(const char *text) #elif defined(__APPLE__) [GLWin.cocoaWin setTitle: [NSString stringWithUTF8String: text]]; #elif defined(_WIN32) - // TODO convert text to unicode and change SetWindowTextA to SetWindowText - SetWindowTextA(EmuWindow::GetWnd(), text); + TCHAR temp[512]; + swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs"), text); + EmuWindow::SetWindowText(temp); #elif defined(HAVE_X11) && HAVE_X11 // Tell X to ask the window manager to set the window title. // (X itself doesn't provide window title functionality.) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp index fb4c226f77..61e41008b3 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp @@ -44,7 +44,8 @@ bool PixelShaderCache::s_displayCompileAlert; GLuint PixelShaderCache::CurrentShader; bool PixelShaderCache::ShaderEnabled; -static FRAGMENTSHADER* pShaderLast = NULL; +PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry = NULL; +PIXELSHADERUID PixelShaderCache::last_uid; GLuint PixelShaderCache::GetDepthMatrixProgram() { @@ -61,10 +62,9 @@ void PixelShaderCache::Init() glEnable(GL_FRAGMENT_PROGRAM_ARB); ShaderEnabled = true; CurrentShader = 0; + last_entry = NULL; GL_REPORT_ERRORD(); - memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid)); - s_displayCompileAlert = true; glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions); @@ -184,38 +184,43 @@ void PixelShaderCache::Shutdown() FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) { PIXELSHADERUID uid; - GetPixelShaderId(&uid, dstAlphaMode); - + GetPixelShaderId(&uid, dstAlphaMode, components); + // Check if the shader is already set - if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount) + if (last_entry) { - GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return pShaderLast; + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); + ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components); + return &last_entry->shader; + } } - memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID)); + last_uid = uid; PSCache::iterator iter = PixelShaders.find(uid); - if (iter != PixelShaders.end()) { - iter->second.frameCount = frameCount; PSCacheEntry &entry = iter->second; - if (&entry.shader != pShaderLast) - { - pShaderLast = &entry.shader; - } + last_entry = &entry; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return pShaderLast; + ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components); + return &last_entry->shader; } // Make an entry in the table PSCacheEntry& newentry = PixelShaders[uid]; - newentry.frameCount = frameCount; - pShaderLast = &newentry.shader; + last_entry = &newentry; const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components); + if (g_ActiveConfig.bEnableShaderDebugging && code) + { + GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components); + newentry.shader.strprog = code; + } + #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { static int counter = 0; @@ -234,7 +239,7 @@ FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 comp INCSTAT(stats.numPixelShadersCreated); SETSTAT(stats.numPixelShadersAlive, PixelShaders.size()); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return pShaderLast; + return &last_entry->shader; } bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) @@ -247,7 +252,7 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr #if defined HAVE_CG && HAVE_CG char stropt[128]; - sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions); + sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions); const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts); @@ -318,9 +323,6 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr cgDestroyProgram(tempprog); #endif -#if defined(_DEBUG) || defined(DEBUGFAST) - ps.strprog = pstrprogram; -#endif return true; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h index f404b206a2..f528eeb35b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h @@ -39,9 +39,7 @@ struct FRAGMENTSHADER } } GLuint glprogid; // opengl program id -#if defined(_DEBUG) || defined(DEBUGFAST) std::string strprog; -#endif }; class PixelShaderCache @@ -49,13 +47,13 @@ class PixelShaderCache struct PSCacheEntry { FRAGMENTSHADER shader; - int frameCount; - PSCacheEntry() : frameCount(0) {} + PSCacheEntry() {} ~PSCacheEntry() {} void Destroy() { shader.Destroy(); } + PIXELSHADERUIDSAFE safe_uid; }; typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache; @@ -67,6 +65,8 @@ class PixelShaderCache static bool s_displayCompileAlert; static GLuint CurrentShader; + static PSCacheEntry* last_entry; + static PIXELSHADERUID last_uid; static bool ShaderEnabled; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 0c9d904cad..9883d35fbb 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -60,6 +60,7 @@ #include "Core.h" #include "Movie.h" #include "Host.h" +#include "BPFunctions.h" #include "main.h" // Local #ifdef _WIN32 @@ -109,12 +110,6 @@ int s_fps=0; RasterFont* s_pfont = NULL; -#if defined _WIN32 || defined HAVE_LIBAV -static bool s_bAVIDumping = false; -#else -static File::IOFile f_pFrameDump; -#endif - // 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA. static int s_MSAASamples = 1; static int s_MSAACoverageSamples = 0; @@ -128,6 +123,12 @@ static u32 s_blendMode; static std::thread scrshotThread; #endif +// EFB cache related +const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks. +const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up +const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; +static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; +static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR static const GLenum glSrcFactors[8] = { @@ -249,9 +250,6 @@ Renderer::Renderer() s_fps=0; s_blendMode = 0; -#if defined _WIN32 || defined HAVE_LIBAV - s_bAVIDumping = false; -#endif #if defined HAVE_CG && HAVE_CG g_cgcontext = cgCreateContext(); @@ -515,19 +513,6 @@ Renderer::~Renderer() #endif delete g_framebuffer_manager; - -#if defined _WIN32 || defined HAVE_LIBAV - if(s_bAVIDumping) - { - AVIDump::Stop(); - s_bLastFrameDumped = false; - s_bAVIDumping = false; - } -#else - if (f_pFrameDump.IsOpen()) - f_pFrameDump.Close(); - s_bLastFrameDumped = false; -#endif } // Create On-Screen-Messages @@ -610,7 +595,7 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color) { const int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth(); const int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight(); - + glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f, ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f); @@ -642,49 +627,9 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) // Renderer::GetTargetHeight() = the fixed ini file setting // donkopunchstania - it appears scissorBR is the bottom right pixel inside the scissor box // therefore the width and height are (scissorBR + 1) - scissorTL -bool Renderer::SetScissorRect() +void Renderer::SetScissorRect(const TargetRectangle& rc) { - MathUtil::Rectangle<float> rc; - GetScissorRect(rc); - - if (rc.left < 0) rc.left = 0; - if (rc.top < 0) rc.top = 0; - if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH; - if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT; - - if (rc.left > rc.right) - { - int temp = rc.right; - rc.right = rc.left; - rc.left = temp; - } - if (rc.top > rc.bottom) - { - int temp = rc.bottom; - rc.bottom = rc.top; - rc.top = temp; - } - - // Check that the coordinates are good - if (rc.right != rc.left && rc.bottom != rc.top) - { - glScissor( - EFBToScaledX(rc.left), // x = 0 for example - EFBToScaledY(EFB_HEIGHT - rc.bottom), // y = 0 for example - EFBToScaledX(rc.right - rc.left), // width = 640 for example - EFBToScaledY(rc.bottom - rc.top)); // height = 480 for example - return true; - } - else - { - glScissor( - 0, - 0, - Renderer::GetTargetWidth(), - Renderer::GetTargetHeight() - ); - } - return false; + glScissor(rc.left, rc.bottom, rc.GetWidth(), rc.GetHeight()); } void Renderer::SetColorMask() @@ -698,6 +643,42 @@ void Renderer::SetColorMask() glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask); } +void ClearEFBCache() +{ + for (u32 i = 0; i < EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT; ++i) + s_efbCacheValid[0][i] = false; + + for (u32 i = 0; i < EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT; ++i) + s_efbCacheValid[1][i] = false; +} + +void Renderer::UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data) +{ + u32 cacheType = (type == PEEK_Z ? 0 : 1); + + if (!s_efbCache[cacheType][cacheRectIdx].size()) + s_efbCache[cacheType][cacheRectIdx].resize(EFB_CACHE_RECT_SIZE * EFB_CACHE_RECT_SIZE); + + u32 targetPixelRcWidth = targetPixelRc.right - targetPixelRc.left; + + for (u32 yCache = 0; yCache < EFB_CACHE_RECT_SIZE; ++yCache) + { + u32 yEFB = efbPixelRc.top + yCache; + u32 yPixel = (EFBToScaledY(EFB_HEIGHT - yEFB) + EFBToScaledY(EFB_HEIGHT - yEFB - 1)) / 2; + u32 yData = yPixel - targetPixelRc.bottom; + + for (u32 xCache = 0; xCache < EFB_CACHE_RECT_SIZE; ++xCache) + { + u32 xEFB = efbPixelRc.left + xCache; + u32 xPixel = (EFBToScaledX(xEFB) + EFBToScaledX(xEFB + 1)) / 2; + u32 xData = xPixel - targetPixelRc.left; + s_efbCache[cacheType][cacheRectIdx][yCache * EFB_CACHE_RECT_SIZE + xCache] = data[yData * targetPixelRcWidth + xData]; + } + } + + s_efbCacheValid[cacheType][cacheRectIdx] = true; +} + // This function allows the CPU to directly access the EFB. // There are EFB peeks (which will read the color or depth of a pixel) // and EFB pokes (which will change the color or depth of a pixel). @@ -717,34 +698,50 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) if (!g_ActiveConfig.bEFBAccessEnable) return 0; - // Get the rectangular target region covered by the EFB pixel + u32 cacheRectIdx = (y / EFB_CACHE_RECT_SIZE) * EFB_CACHE_WIDTH + + (x / EFB_CACHE_RECT_SIZE); + + // Get the rectangular target region containing the EFB pixel EFBRectangle efbPixelRc; - efbPixelRc.left = x; - efbPixelRc.top = y; - efbPixelRc.right = x + 1; - efbPixelRc.bottom = y + 1; + efbPixelRc.left = (x / EFB_CACHE_RECT_SIZE) * EFB_CACHE_RECT_SIZE; + efbPixelRc.top = (y / EFB_CACHE_RECT_SIZE) * EFB_CACHE_RECT_SIZE; + efbPixelRc.right = efbPixelRc.left + EFB_CACHE_RECT_SIZE; + efbPixelRc.bottom = efbPixelRc.top + EFB_CACHE_RECT_SIZE; TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc); + u32 targetPixelRcWidth = targetPixelRc.right - targetPixelRc.left; + u32 targetPixelRcHeight = targetPixelRc.top - targetPixelRc.bottom; // TODO (FIX) : currently, AA path is broken/offset and doesn't return the correct pixel switch (type) { case PEEK_Z: { - if (s_MSAASamples > 1) + u32 z; + + if (!s_efbCacheValid[0][cacheRectIdx]) { - // Resolve our rectangle. - FramebufferManager::GetEFBDepthTexture(efbPixelRc); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer()); - } + if (s_MSAASamples > 1) + { + // Resolve our rectangle. + FramebufferManager::GetEFBDepthTexture(efbPixelRc); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer()); + } + + u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight]; - // Sample from the center of the target region. - int srcX = (targetPixelRc.left + targetPixelRc.right) / 2; - int srcY = (targetPixelRc.top + targetPixelRc.bottom) / 2; + glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight, + GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depthMap); + GL_REPORT_ERRORD(); - u32 z = 0; - glReadPixels(srcX, srcY, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &z); - GL_REPORT_ERRORD(); + UpdateEFBCache(type, cacheRectIdx, efbPixelRc, targetPixelRc, depthMap); + + delete[] depthMap; + } + + u32 xRect = x % EFB_CACHE_RECT_SIZE; + u32 yRect = y % EFB_CACHE_RECT_SIZE; + z = s_efbCache[0][cacheRectIdx][yRect * EFB_CACHE_RECT_SIZE + xRect]; // Scale the 32-bit value returned by glReadPixels to a 24-bit // value (GC uses a 24-bit Z-buffer). @@ -769,21 +766,31 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) // determine if we're aiming at an enemy (0x80 / 0x88) or not (0x70) // Wind Waker is also using it for the pictograph to determine the color of each pixel - if (s_MSAASamples > 1) + u32 color; + + if (!s_efbCacheValid[1][cacheRectIdx]) { - // Resolve our rectangle. - FramebufferManager::GetEFBColorTexture(efbPixelRc); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer()); - } + if (s_MSAASamples > 1) + { + // Resolve our rectangle. + FramebufferManager::GetEFBColorTexture(efbPixelRc); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer()); + } + + u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight]; + + glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, colorMap); + GL_REPORT_ERRORD(); - // Sample from the center of the target region. - int srcX = (targetPixelRc.left + targetPixelRc.right) / 2; - int srcY = (targetPixelRc.top + targetPixelRc.bottom) / 2; + UpdateEFBCache(type, cacheRectIdx, efbPixelRc, targetPixelRc, colorMap); + + delete[] colorMap; + } - // Read back pixel in BGRA format, then byteswap to get GameCube's ARGB Format. - u32 color = 0; - glReadPixels(srcX, srcY, 1, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &color); - GL_REPORT_ERRORD(); + u32 xRect = x % EFB_CACHE_RECT_SIZE; + u32 yRect = y % EFB_CACHE_RECT_SIZE; + color = s_efbCache[1][cacheRectIdx][yRect * EFB_CACHE_RECT_SIZE + xRect]; // check what to do with the alpha channel (GX_PokeAlphaRead) PixelEngine::UPEAlphaReadReg alpha_read_mode; @@ -865,41 +872,35 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE { ResetAPIState(); - GLenum ColorMask = GL_FALSE, AlphaMask = GL_FALSE; - if (colorEnable) ColorMask = GL_TRUE; - if (alphaEnable) AlphaMask = GL_TRUE; - glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask); + // color + GLboolean const + color_mask = colorEnable ? GL_TRUE : GL_FALSE, + alpha_mask = alphaEnable ? GL_TRUE : GL_FALSE; + glColorMask(color_mask, color_mask, color_mask, alpha_mask); - if (zEnable) - { - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glDepthFunc(GL_ALWAYS); - } - else - { - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDepthFunc(GL_NEVER); - } + glClearColor( + float((color >> 16) & 0xFF) / 255.0f, + float((color >> 8) & 0xFF) / 255.0f, + float((color >> 0) & 0xFF) / 255.0f, + float((color >> 24) & 0xFF) / 255.0f); + + // depth + glDepthMask(zEnable ? GL_TRUE : GL_FALSE); + + glClearDepth(float(z & 0xFFFFFF) / float(0xFFFFFF)); + + // Update rect for clearing the picture + glEnable(GL_SCISSOR_TEST); + + TargetRectangle const targetRc = ConvertEFBRectangle(rc); + glScissor(targetRc.left, targetRc.bottom, targetRc.GetWidth(), targetRc.GetHeight()); - // Update viewport for clearing the picture - TargetRectangle targetRc = ConvertEFBRectangle(rc); - glViewport(targetRc.left, targetRc.bottom, targetRc.GetWidth(), targetRc.GetHeight()); - glDepthRange(0.0, (float)(z & 0xFFFFFF) / float(0xFFFFFF)); - - glColor4f((float)((color >> 16) & 0xFF) / 255.0f, - (float)((color >> 8) & 0xFF) / 255.0f, - (float)(color & 0xFF) / 255.0f, - (float)((color >> 24) & 0xFF) / 255.0f); - glBegin(GL_QUADS); - glVertex3f(-1.f, -1.f, 1.f); - glVertex3f(-1.f, 1.f, 1.f); - glVertex3f( 1.f, 1.f, 1.f); - glVertex3f( 1.f, -1.f, 1.f); - glEnd(); + // glColorMask/glDepthMask/glScissor affect glClear (glViewport does not) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); RestoreAPIState(); + + ClearEFBCache(); } void Renderer::ReinterpretPixelData(unsigned int convtype) @@ -986,15 +987,14 @@ void Renderer::SetBlendMode(bool forceUpdate) // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { - static u8 *data = NULL; static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { - if (g_ActiveConfig.bDumpFrames && data) + if (g_ActiveConfig.bDumpFrames && frame_data) #ifdef _WIN32 - AVIDump::AddFrame((char *) data); + AVIDump::AddFrame(frame_data); #elif defined HAVE_LIBAV - AVIDump::AddFrame(data, w, h); + AVIDump::AddFrame((u8*)frame_data, w, h); #endif Core::Callback_VideoCopiedToXFB(false); return; @@ -1008,12 +1008,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { - if (g_ActiveConfig.bDumpFrames && data) - #ifdef _WIN32 - AVIDump::AddFrame((char *) data); - #elif defined HAVE_LIBAV - AVIDump::AddFrame(data, w, h); - #endif + if (g_ActiveConfig.bDumpFrames && frame_data) + { +#ifdef _WIN32 + AVIDump::AddFrame(frame_data); +#elif defined HAVE_LIBAV + AVIDump::AddFrame((u8*)frame_data, w, h); +#endif + } Core::Callback_VideoCopiedToXFB(false); return; } @@ -1172,26 +1174,26 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons if (g_ActiveConfig.bDumpFrames) { std::lock_guard<std::mutex> lk(s_criticalScreenshot); - if (!data || w != dst_rect.GetWidth() || + if (!frame_data || w != dst_rect.GetWidth() || h != dst_rect.GetHeight()) { - if (data) delete[] data; + if (frame_data) delete[] frame_data; w = dst_rect.GetWidth(); h = dst_rect.GetHeight(); - data = new u8[3 * w * h]; + frame_data = new char[3 * w * h]; } glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); + glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) { - if (!s_bLastFrameDumped) + if (!bLastFrameDumped) { #ifdef _WIN32 - s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); + bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); #else - s_bAVIDumping = AVIDump::Start(w, h); + bAVIDumping = AVIDump::Start(w, h); #endif - if (!s_bAVIDumping) + if (!bAVIDumping) OSD::AddMessage("AVIDump Start failed", 2000); else { @@ -1200,36 +1202,36 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), w, h).c_str(), 2000); } } - if (s_bAVIDumping) + if (bAVIDumping) { #ifdef _WIN32 - AVIDump::AddFrame((char *) data); + AVIDump::AddFrame(frame_data); #else - FlipImageData(data, w, h); - AVIDump::AddFrame(data, w, h); + FlipImageData((u8*)frame_data, w, h); + AVIDump::AddFrame((u8*)frame_data, w, h); #endif } - s_bLastFrameDumped = true; + bLastFrameDumped = true; } else NOTICE_LOG(VIDEO, "Error reading framebuffer"); } else { - if (s_bLastFrameDumped && s_bAVIDumping) + if (bLastFrameDumped && bAVIDumping) { - if (data) + if (frame_data) { - delete[] data; - data = NULL; + delete[] frame_data; + frame_data = NULL; w = h = 0; } AVIDump::Stop(); - s_bAVIDumping = false; + bAVIDumping = false; OSD::AddMessage("Stop dumping frames", 2000); } - s_bLastFrameDumped = false; + bLastFrameDumped = false; } #else if (g_ActiveConfig.bDumpFrames) @@ -1238,16 +1240,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons std::string movie_file_name; w = dst_rect.GetWidth(); h = dst_rect.GetHeight(); - data = new u8[3 * w * h]; + frame_data = new char[3 * w * h]; glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); + glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data); if (GL_REPORT_ERROR() == GL_NO_ERROR) { - if (!s_bLastFrameDumped) + if (!bLastFrameDumped) { movie_file_name = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump.raw"; - f_pFrameDump.Open(movie_file_name, "wb"); - if (!f_pFrameDump) + pFrameDump.Open(movie_file_name, "wb"); + if (!pFrameDump) OSD::AddMessage("Error opening framedump.raw for writing.", 2000); else { @@ -1256,22 +1258,22 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons OSD::AddMessage(msg, 2000); } } - if (f_pFrameDump) + if (pFrameDump) { - FlipImageData(data, w, h); - f_pFrameDump.WriteBytes(data, w * 3 * h); - f_pFrameDump.Flush(); + FlipImageData((u8*)frame_data, w, h); + pFrameDump.WriteBytes(frame_data, w * 3 * h); + pFrameDump.Flush(); } - s_bLastFrameDumped = true; + bLastFrameDumped = true; } - delete[] data; + delete[] frame_data; } else { - if (s_bLastFrameDumped) - f_pFrameDump.Close(); - s_bLastFrameDumped = false; + if (bLastFrameDumped) + pFrameDump.Close(); + bLastFrameDumped = false; } #endif @@ -1392,8 +1394,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons g_Config.iSaveTargetId = 0; // reload textures if these settings changed - if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache || - g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) + if (g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips) TextureCache::Invalidate(false); if (g_Config.bCopyEFBToTexture != g_ActiveConfig.bCopyEFBToTexture) @@ -1407,6 +1408,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons // GetTargetWidth(), GetTargetHeight()); Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); XFBWrited = false; + + // Invalidate EFB cache + ClearEFBCache(); } // ALWAYS call RestoreAPIState for each ResetAPIState call you're doing @@ -1422,9 +1426,6 @@ void Renderer::ResetAPIState() glDisable(GL_BLEND); glDepthMask(GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - // make sure to disable wireframe when drawing the clear quad - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } void Renderer::RestoreAPIState() @@ -1432,14 +1433,13 @@ void Renderer::RestoreAPIState() // Gets us back into a more game-like state. glEnable(GL_SCISSOR_TEST); SetGenerationMode(); - SetScissorRect(); + BPFunctions::SetScissor(); SetColorMask(); SetDepthMode(); SetBlendMode(true); VertexShaderManager::SetViewportChanged(); - if (g_ActiveConfig.bWireFrame) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, g_ActiveConfig.bWireFrame ? GL_LINE : GL_FILL); VertexShaderCache::SetCurrentShader(0); PixelShaderCache::SetCurrentShader(0); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h index 5805c524ae..9cf1573b56 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h @@ -7,6 +7,8 @@ namespace OGL { +void ClearEFBCache(); + class Renderer : public ::Renderer { public: @@ -15,7 +17,7 @@ public: void SetColorMask(); void SetBlendMode(bool forceUpdate); - bool SetScissorRect(); + void SetScissorRect(const TargetRectangle& rc); void SetGenerationMode(); void SetDepthMode(); void SetLogicOpMode(); @@ -57,6 +59,9 @@ public: void SetVSConstant4fv(unsigned int const_number, const float *f); void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f); + +private: + void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data); }; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index 4a9431a563..f78eb11905 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -39,6 +39,7 @@ #include "Globals.h" #include "Hash.h" #include "HiresTextures.h" +#include "HW/Memmap.h" #include "ImageWrite.h" #include "MemoryUtil.h" #include "PixelShaderCache.h" @@ -124,7 +125,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[]) std::string tga_filename(filename); tga_filename.replace(tga_filename.size() - 3, 3, "tga"); - return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, realW, realH); + return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, @@ -278,7 +279,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo GL_REPORT_ERRORD(); - if (false == isDynamic || g_ActiveConfig.bCopyEFBToTexture) + if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { if (s_TempFramebuffer == 0) glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); @@ -294,7 +295,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo glEnable(GL_TEXTURE_RECTANGLE_ARB); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture); - glViewport(0, 0, virtualW, virtualH); + glViewport(0, 0, virtual_width, virtual_height); PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram()); PixelShaderManager::SetColorMatrix(colmat); // set transformation @@ -317,7 +318,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (false == g_ActiveConfig.bCopyEFBToTexture) { - hash = TextureConverter::EncodeToRamFromTexture( + int encoded_size = TextureConverter::EncodeToRamFromTexture( addr, read_texture, srcFormat == PIXELFMT_Z24, @@ -325,6 +326,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo dstFormat, scaleByHalf, srcRect); + + u8* dst = Memory::GetPointer(addr); + hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples); + + // Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date + if (!g_ActiveConfig.bEFBCopyCacheEnable) + TextureCache::MakeRangeDynamic(addr,encoded_size); + else if (!TextureCache::Find(addr, hash)) + TextureCache::MakeRangeDynamic(addr,encoded_size); } FramebufferManager::SetFramebuffer(0); @@ -337,7 +347,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo { static int count = 0; SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++).c_str(), GL_TEXTURE_2D, texture, realW, realH); + count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height); } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index c715775194..c73d3abdbf 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -250,78 +250,7 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar } -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) -{ - u32 format = copyfmt; - - if (bFromZBuffer) - { - format |= _GX_TF_ZTF; - if (copyfmt == 11) - format = GX_TF_Z16; - else if (format < GX_TF_Z8 || format > GX_TF_Z24X8) - format |= _GX_TF_CTF; - } - else - if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) - format |= _GX_TF_CTF; - - FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format); - if (texconv_shader.glprogid == 0) - return; - - u8 *dest_ptr = Memory::GetPointer(address); - - GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source); - - int width = (source.right - source.left) >> bScaleByHalf; - int height = (source.bottom - source.top) >> bScaleByHalf; - - int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format); - - // Invalidate any existing texture covering this memory range. - // TODO - don't delete the texture if it already exists, just replace the contents. - TextureCache::InvalidateRange(address, size_in_bytes); - - u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1; - u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1; - u16 samples = TextureConversionShader::GetEncodedSampleCount(format); - - // only copy on cache line boundaries - // extra pixels are copied but not displayed in the resulting texture - s32 expandedWidth = (width + blkW) & (~blkW); - s32 expandedHeight = (height + blkH) & (~blkH); - - float sampleStride = bScaleByHalf ? 2.f : 1.f; - TextureConversionShader::SetShaderParameters( - (float)expandedWidth, - (float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this? - (float)Renderer::EFBToScaledX(source.left), - (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight), - Renderer::EFBToScaledXf(sampleStride), - Renderer::EFBToScaledYf(sampleStride)); - - TargetRectangle scaledSource; - scaledSource.top = 0; - scaledSource.bottom = expandedHeight; - scaledSource.left = 0; - scaledSource.right = expandedWidth / samples; - int cacheBytes = 32; - if ((format & 0x0f) == 6) - cacheBytes = 64; - - int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format); - g_renderer->ResetAPIState(); - EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0); - FramebufferManager::SetFramebuffer(0); - VertexShaderManager::SetViewportChanged(); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - TextureCache::DisableStage(0); - g_renderer->RestoreAPIState(); - GL_REPORT_ERRORD(); -} - -u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) +int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) { u32 format = copyfmt; @@ -379,19 +308,8 @@ u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer); + return size_in_bytes; // TODO: D3D11 is calculating this value differently! - u64 hash = GetHash64(dest_ptr, size_in_bytes, - g_ActiveConfig.iSafeTextureCache_ColorSamples); - if (g_ActiveConfig.bEFBCopyCacheEnable) - { - // If the texture in RAM is already in the texture cache, - // do not copy it again as it has not changed. - if (TextureCache::Find(address, hash)) - return hash; - } - - TextureCache::MakeRangeDynamic(address,size_in_bytes); - return hash; } void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h index 719ac1b7fc..4113778603 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.h @@ -32,15 +32,13 @@ namespace TextureConverter void Init(); void Shutdown(); -void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, - u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); - void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight); void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture); -u64 EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); +// returns size of the encoded data (in bytes) +int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index a101d6c2d6..5117f6ddb6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -155,12 +155,13 @@ void VertexManager::vFlush() 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.texMode1[i&3].max_lod >> 4)); + tex.texMode1[i&3].max_lod >> 4, + tex.texImage1[i&3].image_type); if (tentry) { // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0); + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, tentry->virtual_width, tentry->virtual_height, 0, 0, API_OPENGL); if (g_ActiveConfig.iLog & CONF_SAVETEXTURES) { @@ -178,7 +179,7 @@ void VertexManager::vFlush() // set global constants VertexShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); + PixelShaderManager::SetConstants(API_OPENGL); bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; @@ -268,6 +269,8 @@ void VertexManager::vFlush() #endif g_Config.iSaveTargetId++; + ClearEFBCache(); + GL_REPORT_ERRORD(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp index 96f2d5a2ae..dbbb7ee29b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp @@ -41,7 +41,9 @@ VertexShaderCache::VSCache VertexShaderCache::vshaders; GLuint VertexShaderCache::CurrentShader; bool VertexShaderCache::ShaderEnabled; -static VERTEXSHADER *pShaderLast = NULL; +VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL; +VERTEXSHADERUID VertexShaderCache::last_uid; + static int s_nMaxVertexInstructions; @@ -50,7 +52,7 @@ void VertexShaderCache::Init() glEnable(GL_VERTEX_PROGRAM_ARB); ShaderEnabled = true; CurrentShader = 0; - memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid)); + last_entry = NULL; glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions); if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxVertexInstructions = 4096; @@ -74,31 +76,34 @@ VERTEXSHADER* VertexShaderCache::SetShader(u32 components) { VERTEXSHADERUID uid; GetVertexShaderId(&uid, components); - if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) + if (last_entry) { - GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return pShaderLast; + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); + ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components); + return &last_entry->shader; + } } - memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); + + last_uid = uid; VSCache::iterator iter = vshaders.find(uid); if (iter != vshaders.end()) { - iter->second.frameCount = frameCount; VSCacheEntry &entry = iter->second; - if (&entry.shader != pShaderLast) { - pShaderLast = &entry.shader; - } + last_entry = &entry; GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return pShaderLast; + ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components); + return &last_entry->shader; } // Make an entry in the table VSCacheEntry& entry = vshaders[uid]; - entry.frameCount = frameCount; - pShaderLast = &entry.shader; + last_entry = &entry; const char *code = GenerateVertexShaderCode(components, API_OPENGL); + GetSafeVertexShaderId(&entry.safe_uid, components); #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { @@ -118,7 +123,7 @@ VERTEXSHADER* VertexShaderCache::SetShader(u32 components) INCSTAT(stats.numVertexShadersCreated); SETSTAT(stats.numVertexShadersAlive, vshaders.size()); GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return pShaderLast; + return &last_entry->shader; } bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram) @@ -182,9 +187,8 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr cgDestroyProgram(tempprog); #endif -#if defined(_DEBUG) || defined(DEBUGFAST) - vs.strprog = pstrprogram; -#endif + if (g_ActiveConfig.bEnableShaderDebugging) + vs.strprog = pstrprogram; return true; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h index e311fde77b..6f4cbe25c2 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h @@ -32,9 +32,7 @@ struct VERTEXSHADER VERTEXSHADER() : glprogid(0) {} GLuint glprogid; // opengl program id -#if defined(_DEBUG) || defined(DEBUGFAST) std::string strprog; -#endif }; class VertexShaderCache @@ -42,8 +40,8 @@ class VertexShaderCache struct VSCacheEntry { VERTEXSHADER shader; - int frameCount; - VSCacheEntry() : frameCount(0) {} + VERTEXSHADERUIDSAFE safe_uid; + VSCacheEntry() {} void Destroy() { // printf("Destroying vs %i\n", shader.glprogid); glDeleteProgramsARB(1, &shader.glprogid); @@ -55,6 +53,9 @@ class VertexShaderCache static VSCache vshaders; + static VSCacheEntry* last_entry; + static VERTEXSHADERUID last_uid; + static GLuint CurrentShader; static bool ShaderEnabled; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index a25f9cd839..251512fe6b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -155,6 +155,7 @@ void VideoBackend::ShowConfig(void *_hParent) bool VideoBackend::Initialize(void *&window_handle) { + InitializeShared(); InitBackendInfo(); frameCount = 0; diff --git a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj index 26ccad4175..db6f072f20 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj +++ b/Source/Plugins/Plugin_VideoSoftware/Plugin_VideoSoftware.vcxproj @@ -46,13 +46,12 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> + <WholeProgramOptimization>false</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'"> <ConfigurationType>StaticLibrary</ConfigurationType> diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp index 404424f634..95ec555181 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/BPMemLoader.cpp @@ -101,14 +101,14 @@ void SWBPWritten(int address, int newvalue) // TODO - figure out a cleaner way. if (Core::g_CoreStartupParameter.bWii) - ptr = Memory::GetPointer(bpmem.tlutXferSrc << 5); + ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5); else - ptr = Memory::GetPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5); + ptr = Memory::GetPointer((bpmem.tmem_config.tlut_src & 0xFFFFF) << 5); if (ptr) memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount); else - PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5); + 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); break; } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index abfd9155f5..c591bd0957 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -215,6 +215,12 @@ bool VideoSoftware::Video_IsPossibleWaitingSetDrawDone(void) return false; } +bool VideoSoftware::Video_IsHiWatermarkActive(void) +{ + return false; +} + + void VideoSoftware::Video_AbortFrame(void) { } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h index 08b4c155ad..7c52e34291 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoBackend.h @@ -36,7 +36,7 @@ class VideoSoftware : public VideoBackend void Video_SetRendering(bool bEnabled); void Video_GatherPipeBursted(); - + bool Video_IsHiWatermarkActive(); bool Video_IsPossibleWaitingSetDrawDone(); void Video_AbortFrame(); |
