diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index b9df2ebe8e..179560ddfa 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -392,7 +392,7 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api // compute window position if needed because binding semantic WPOS is not widely supported if (numTexgen < 7) { - for (int i = 0; i < numTexgen; ++i) + for (unsigned int i = 0; i < numTexgen; ++i) out.Write(",\n in %s float3 uv%d : TEXCOORD%d", optCentroid, i, i); out.Write(",\n in %s float4 clipPos : TEXCOORD%d", optCentroid, numTexgen); if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) @@ -1190,13 +1190,6 @@ static void WriteFog(T& out, pixel_shader_uid_data& uid_data) void GetPixelShaderUid(PixelShaderUid& object, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components) { GeneratePixelShader(object, dstAlphaMode, ApiType, components); - - if (g_ActiveConfig.bEnableShaderDebugging) - { - PixelShaderCode code; - GeneratePixelShaderCode(code, dstAlphaMode, API_OPENGL, components); - CheckForUidMismatch(code, object, "Pixel", "p"); - } } void GeneratePixelShaderCode(PixelShaderCode& object, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components) diff --git a/Source/Core/VideoCommon/Src/ShaderGenCommon.h b/Source/Core/VideoCommon/Src/ShaderGenCommon.h index 4b3d16b8d7..ebf2ae1b87 100644 --- a/Source/Core/VideoCommon/Src/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/Src/ShaderGenCommon.h @@ -113,6 +113,9 @@ public: template inline T& GetUidData() { return data; } + const uid_data& GetUidData() const { return data; } + size_t GetUidDataSize() const { return sizeof(values); } + private: union { @@ -217,42 +220,68 @@ struct LightingUidData * Checks if there has been */ template -void CheckForUidMismatch(CodeT& new_code, const UidT& new_uid, const char* shader_type, const char* dump_prefix) +class UidChecker { - // TODO: Might be sensitive to config changes - static std::map s_shaders; - static std::vector s_uids; - - bool uid_is_indexed = std::find(s_uids.begin(), s_uids.end(), new_uid) != s_uids.end(); - if (!uid_is_indexed) +public: + void Invalidate() { - s_uids.push_back(new_uid); - s_shaders[new_uid] = new_code.GetBuffer(); + m_shaders.clear(); + m_uids.clear(); } - else + + void AddToIndexAndCheck(CodeT& new_code, const UidT& new_uid, const char* shader_type, const char* dump_prefix) { - // uid is already in the index => check if there's a shader with the same uid but different code - auto& old_code = s_shaders[new_uid]; - if (strcmp(old_code.c_str(), new_code.GetBuffer()) != 0) + bool uid_is_indexed = std::find(m_uids.begin(), m_uids.end(), new_uid) != m_uids.end(); + if (!uid_is_indexed) { - static int num_failures = 0; + m_uids.push_back(new_uid); + m_shaders[new_uid] = new_code.GetBuffer(); + } + else + { + // uid is already in the index => check if there's a shader with the same uid but different code + auto& old_code = m_shaders[new_uid]; + if (strcmp(old_code.c_str(), new_code.GetBuffer()) != 0) + { + static int num_failures = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%s%ssuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), - dump_prefix, - ++num_failures); + char szTemp[MAX_PATH]; + sprintf(szTemp, "%s%ssuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), + dump_prefix, + ++num_failures); - // TODO: Should also dump uids - std::ofstream file; - OpenFStream(file, szTemp, std::ios_base::out); - file << "Old shader code:\n" << old_code; - file << "\n\nNew shader code:\n" << new_code.GetBuffer(); - file.close(); + // TODO: Should also dump uids + std::ofstream file; + OpenFStream(file, szTemp, std::ios_base::out); + file << "Old shader code:\n" << old_code; + file << "\n\nNew shader code:\n" << new_code.GetBuffer(); + file << "\n\nShader uid:\n"; + for (unsigned int i = 0; i < new_uid.GetUidDataSize(); ++i) + { + u32 value = ((u32*)&new_uid.GetUidData())[i]; + if ((i % 4) == 0) + { + unsigned int last_value = (i+3 < new_uid.GetUidDataSize()-1) ? i+3 : new_uid.GetUidDataSize(); + file << std::setfill(' ') << std::dec; + file << "Values " << std::setw(2) << i << " - " << last_value << ": "; + } - // TODO: Make this more idiot-proof - ERROR_LOG(VIDEO, "%s shader uid mismatch!", shader_type); + file << std::setw(8) << std::setfill('0') << std::hex << value << std::setw(1); + if ((i % 4) < 3) + file << ' '; + else + file << std::endl; + } + file.close(); + + ERROR_LOG(VIDEO, "%s shader uid mismatch! See %s for details", shader_type, szTemp); + } } } -} + +private: + std::map m_shaders; + std::vector m_uids; +}; #endif // _SHADERGENCOMMON_H diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index 81b8c79553..6cbf273097 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -538,13 +538,6 @@ static void GenerateVertexShader(T& out, u32 components, API_TYPE api_type) void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type) { GenerateVertexShader(object, components, api_type); - - if (g_ActiveConfig.bEnableShaderDebugging) - { - VertexShaderCode code; - GenerateVertexShaderCode(code, components, API_OPENGL); - CheckForUidMismatch(code, object, "Vertex", "v"); - } } void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE api_type) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp index 9db0a53d13..0adf82fef9 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp @@ -29,6 +29,7 @@ namespace DX11 PixelShaderCache::PSCache PixelShaderCache::PixelShaders; const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry; PixelShaderUid PixelShaderCache::last_uid; +UidChecker PixelShaderCache::pixel_uid_checker; LinearDiskCache g_ps_disk_cache; @@ -412,7 +413,8 @@ void PixelShaderCache::Clear() { for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++) iter->second.Destroy(); - PixelShaders.clear(); + PixelShaders.clear(); + pixel_uid_checker.Invalidate(); last_entry = NULL; } @@ -450,6 +452,12 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) { PixelShaderUid uid; GetPixelShaderUid(uid, dstAlphaMode, API_D3D11, components); + if (g_ActiveConfig.bEnableShaderDebugging) + { + PixelShaderCode code; + GeneratePixelShaderCode(code, dstAlphaMode, API_D3D11, components); + pixel_uid_checker.AddToIndexAndCheck(code, uid, "Pixel", "p"); + } // Check if the shader is already set if (last_entry) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h index ace3a9ac6a..dee930ccfe 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h @@ -52,6 +52,8 @@ private: static PSCache PixelShaders; static const PSCacheEntry* last_entry; static PixelShaderUid last_uid; + + static UidChecker pixel_uid_checker; }; } // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp index 19b276ddb6..2754267b09 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp @@ -25,6 +25,7 @@ namespace DX11 { VertexShaderCache::VSCache VertexShaderCache::vshaders; const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; VertexShaderUid VertexShaderCache::last_uid; +UidChecker VertexShaderCache::vertex_uid_checker; static ID3D11VertexShader* SimpleVertexShader = NULL; static ID3D11VertexShader* ClearVertexShader = NULL; @@ -174,6 +175,7 @@ void VertexShaderCache::Clear() for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter) iter->second.Destroy(); vshaders.clear(); + vertex_uid_checker.Invalidate(); last_entry = NULL; } @@ -197,6 +199,13 @@ bool VertexShaderCache::SetShader(u32 components) { VertexShaderUid uid; GetVertexShaderUid(uid, components, API_D3D11); + if (g_ActiveConfig.bEnableShaderDebugging) + { + VertexShaderCode code; + GenerateVertexShaderCode(code, components, API_D3D11); + vertex_uid_checker.AddToIndexAndCheck(code, uid, "Vertex", "v"); + } + if (last_entry) { if (uid == last_uid) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h index 04f74bc055..b80dbcd7b1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h @@ -59,6 +59,8 @@ private: static VSCache vshaders; static const VSCacheEntry* last_entry; static VertexShaderUid last_uid; + + static UidChecker vertex_uid_checker; }; } // namespace DX11 diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index eb47614ae5..bbb46e4d56 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -31,6 +31,7 @@ namespace DX9 PixelShaderCache::PSCache PixelShaderCache::PixelShaders; const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry; PixelShaderUid PixelShaderCache::last_uid; +UidChecker PixelShaderCache::pixel_uid_checker; static LinearDiskCache g_ps_disk_cache; static std::set unique_shaders; @@ -284,6 +285,7 @@ void PixelShaderCache::Clear() for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++) iter->second.Destroy(); PixelShaders.clear(); + pixel_uid_checker.Invalidate(); last_entry = NULL; } @@ -322,6 +324,12 @@ 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; GetPixelShaderUid(uid, dstAlphaMode, API_D3D9, components); + if (g_ActiveConfig.bEnableShaderDebugging) + { + PixelShaderCode code; + GeneratePixelShaderCode(code, dstAlphaMode, API_D3D9, components); + pixel_uid_checker.AddToIndexAndCheck(code, uid, "Pixel", "p"); + } // Check if the shader is already set if (last_entry) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h index aadd2c02f7..733a68233a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h @@ -44,6 +44,8 @@ private: static PSCache PixelShaders; static const PSCacheEntry *last_entry; static PixelShaderUid last_uid; + static UidChecker pixel_uid_checker; + static void Clear(); public: diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp index 9223533b3a..2d11368a6d 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp @@ -26,6 +26,7 @@ namespace DX9 VertexShaderCache::VSCache VertexShaderCache::vshaders; const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; VertexShaderUid VertexShaderCache::last_uid; +UidChecker VertexShaderCache::vertex_uid_checker; #define MAX_SSAA_SHADERS 3 @@ -150,6 +151,7 @@ void VertexShaderCache::Clear() for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter) iter->second.Destroy(); vshaders.clear(); + vertex_uid_checker.Invalidate(); last_entry = NULL; } @@ -176,6 +178,13 @@ bool VertexShaderCache::SetShader(u32 components) { VertexShaderUid uid; GetVertexShaderUid(uid, components, API_D3D9); + if (g_ActiveConfig.bEnableShaderDebugging) + { + VertexShaderCode code; + GenerateVertexShaderCode(code, components, API_D3D9); + vertex_uid_checker.AddToIndexAndCheck(code, uid, "Vertex", "v"); + } + if (last_entry) { if (uid == last_uid) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h index 88c295c435..32fbea92be 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h @@ -38,6 +38,9 @@ private: static VSCache vshaders; static const VSCacheEntry *last_entry; static VertexShaderUid last_uid; + + static UidChecker vertex_uid_checker; + static void Clear(); public: diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp index bab52073fb..732c63ac67 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp @@ -29,6 +29,8 @@ static GLuint CurrentProgram = 0; ProgramShaderCache::PCache ProgramShaderCache::pshaders; ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry; SHADERUID ProgramShaderCache::last_uid; +UidChecker ProgramShaderCache::pixel_uid_checker; +UidChecker ProgramShaderCache::vertex_uid_checker; static char s_glsl_header[1024] = ""; @@ -351,6 +353,17 @@ void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, { GetPixelShaderUid(uid->puid, dstAlphaMode, API_OPENGL, components); GetVertexShaderUid(uid->vuid, components, API_OPENGL); + + if (g_ActiveConfig.bEnableShaderDebugging) + { + PixelShaderCode pcode; + GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); + pixel_uid_checker.AddToIndexAndCheck(pcode, uid->puid, "Pixel", "p"); + + VertexShaderCode vcode; + GenerateVertexShaderCode(vcode, components, API_OPENGL); + vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v"); + } } ProgramShaderCache::PCacheEntry ProgramShaderCache::GetShaderProgram(void) @@ -448,6 +461,9 @@ void ProgramShaderCache::Shutdown(void) iter->second.Destroy(); pshaders.clear(); + pixel_uid_checker.Invalidate(); + vertex_uid_checker.Invalidate(); + if (g_ActiveConfig.backend_info.bSupportsGLSLUBO) { delete s_buffer; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h index 9cd9a9b12c..30428ad6de 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h @@ -106,6 +106,9 @@ private: static PCacheEntry* last_entry; static SHADERUID last_uid; + static UidChecker pixel_uid_checker; + static UidChecker vertex_uid_checker; + static GLintptr s_vs_data_size; static GLintptr s_ps_data_size; static GLintptr s_vs_data_offset;