diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 85b7d3a47f..0a115e1354 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -11,8 +11,9 @@ namespace DriverDetails { struct BugInfo { + Vendor m_vendor; // which vendor has the error + Driver m_driver; // which driver has the error Bug m_bug; // Which bug it is - u32 m_devfamily; // Which device(family) has the error double m_versionstart; // When it started double m_versionend; // When it ended bool m_hasbug; // Does it have it? @@ -21,40 +22,27 @@ namespace DriverDetails // Local members Vendor m_vendor = VENDOR_UNKNOWN; Driver m_driver = DRIVER_UNKNOWN; - u32 m_devfamily = 0; double m_version = 0.0; // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue - BugInfo m_qualcommbugs[] = { - {BUG_NODYNUBOACCESS, 300, 14.0, -1.0}, - {BUG_BROKENCENTROID, 300, 14.0, -1.0}, - {BUG_BROKENINFOLOG, 300, -1.0, -1.0}, + BugInfo m_known_bugs[] = { + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, + {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true}, + {VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true}, + {VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, }; - std::map, BugInfo> m_bugs; - - // Private function - void InitBugMap() - { - switch(m_driver) - { - case DRIVER_QUALCOMM: - for (unsigned int a = 0; a < (sizeof(m_qualcommbugs) / sizeof(BugInfo)); ++a) - m_bugs[std::make_pair(m_vendor, m_qualcommbugs[a].m_bug)] = m_qualcommbugs[a]; - break; - default: - break; - } - } + std::map m_bugs; - void Init(Vendor vendor, Driver driver, const u32 devfamily, const double version) + void Init(Vendor vendor, Driver driver, const double version) { m_vendor = vendor; m_driver = driver; - m_devfamily = devfamily; m_version = version; - InitBugMap(); + if (driver == DRIVER_UNKNOWN) switch(vendor) { @@ -68,12 +56,6 @@ namespace DriverDetails case VENDOR_INTEL: m_driver = DRIVER_INTEL; break; - case VENDOR_ARM: - m_driver = DRIVER_ARM; - break; - case VENDOR_QUALCOMM: - m_driver = DRIVER_QUALCOMM; - break; case VENDOR_IMGTEC: m_driver = DRIVER_IMGTEC; break; @@ -83,16 +65,22 @@ namespace DriverDetails default: break; } - - for (auto it = m_bugs.begin(); it != m_bugs.end(); ++it) - if (it->second.m_devfamily == m_devfamily) - if (it->second.m_versionend == -1.0 || (it->second.m_versionstart <= m_version && it->second.m_versionend > m_version)) - it->second.m_hasbug = true; + + for(unsigned int a = 0; a < (sizeof(m_known_bugs) / sizeof(BugInfo)); ++a) + { + if( + ( m_known_bugs[a].m_vendor == m_vendor || m_known_bugs[a].m_vendor == VENDOR_ALL ) && + ( m_known_bugs[a].m_driver == m_driver || m_known_bugs[a].m_driver == DRIVER_ALL ) && + ( m_known_bugs[a].m_versionstart <= m_version || m_known_bugs[a].m_versionstart == -1 ) && + ( m_known_bugs[a].m_versionend > m_version || m_known_bugs[a].m_versionend == -1 ) + ) + m_bugs.insert(std::make_pair(m_known_bugs[a].m_bug, m_known_bugs[a])); + } } bool HasBug(Bug bug) { - auto it = m_bugs.find(std::make_pair(m_vendor, bug)); + auto it = m_bugs.find(bug); if (it == m_bugs.end()) return false; return it->second.m_hasbug; diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index cb8b104eea..efb0c7c6c0 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -10,7 +10,8 @@ namespace DriverDetails // Tegra and Nvidia are separated out due to such substantial differences enum Vendor { - VENDOR_NVIDIA = 0, + VENDOR_ALL = 0, + VENDOR_NVIDIA, VENDOR_ATI, VENDOR_INTEL, VENDOR_ARM, @@ -18,20 +19,25 @@ namespace DriverDetails VENDOR_IMGTEC, VENDOR_TEGRA, VENDOR_VIVANTE, + VENDOR_MESA, VENDOR_UNKNOWN }; // Enum of known drivers enum Driver { - DRIVER_NVIDIA = 0, // Official Nvidia, including mobile GPU + DRIVER_ALL = 0, + DRIVER_NVIDIA, // Official Nvidia, including mobile GPU DRIVER_NOUVEAU, // OSS nouveau DRIVER_ATI, // Official ATI - DRIVER_RADEONHD, // OSS Radeon + DRIVER_R600, // OSS Radeon DRIVER_INTEL, // Official Intel - DRIVER_ARM, // Official Mali driver + DRIVER_I965, // OSS Intel + DRIVER_ARM_4XX, // Official Mali driver + DRIVER_ARM_T6XX, // Official Mali driver DRIVER_LIMA, // OSS Mali driver - DRIVER_QUALCOMM, // Official Adreno driver + DRIVER_QUALCOMM_3XX, // Official Adreno driver 3xx + DRIVER_QUALCOMM_2XX, // Official Adreno driver 2xx DRIVER_FREEDRENO, // OSS Adreno driver DRIVER_IMGTEC, // OSS PowerVR driver DRIVER_VIVANTE, // Official vivante driver @@ -69,10 +75,18 @@ namespace DriverDetails // Adreno devices /always/ return 0 when querying GL_INFO_LOG_LENGTH // They also max out at 1024 bytes(1023 characters + null terminator) for the log BUG_BROKENINFOLOG, + // Bug: UBO buffer offset broken + // Affected devices: all mesa drivers + // Started Version: 9.0 (mesa doesn't support ubo before) + // Ended Version: up to 9.2 + // The offset of glBindBufferRange was ignored on all Mesa Gallium3D drivers until 9.1.3 + // Nouveau stored the offset as u16 which isn't enough for all cases with range until 9.1.6 + // I965 has broken data fetches from uniform buffers which results in a dithering until 9.2.0 + BUG_BROKENUBO, }; // Initializes our internal vendor, device family, and driver version - void Init(Vendor vendor, Driver driver, const u32 devfamily, const double version); + void Init(Vendor vendor, Driver driver, const double version); // Once Vendor and driver version is set, this will return if it has the applicable bug passed to it. bool HasBug(Bug bug); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp index d1684f0df5..d7cafb49ca 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp @@ -538,8 +538,8 @@ void ProgramShaderCache::CreateHeader ( void ) , v==GLSL_120 ? "attribute" : "in" , v==GLSL_120 ? "attribute" : "out" - , DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "in" : v==GLSL_120 ? "varying" : "centroid in" - , DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "out" : v==GLSL_120 ? "varying" : "centroid out" + , v==GLSL_120 ? "varying" : DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "in" : "centroid in" + , v==GLSL_120 ? "varying" : DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "out" : "centroid out" , v==GLSL_120 ? "#define texture texture2D" : "" , v==GLSL_120 ? "#define round(x) floor((x)+0.5f)" : "" diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index a60aa15a9b..bfeaab6282 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -271,9 +271,9 @@ void InitDriverInfo() { std::string svendor = std::string(g_ogl_config.gl_vendor); std::string srenderer = std::string(g_ogl_config.gl_renderer); + std::string sversion = std::string(g_ogl_config.gl_version); DriverDetails::Vendor vendor = DriverDetails::VENDOR_UNKNOWN; DriverDetails::Driver driver = DriverDetails::DRIVER_UNKNOWN; - u32 devfamily = 0; double version = 0.0; // Get the vendor first @@ -281,13 +281,12 @@ void InitDriverInfo() vendor = DriverDetails::VENDOR_NVIDIA; else if (svendor == "ATI Technologies Inc." || svendor == "Advanced Micro Devices, Inc.") vendor = DriverDetails::VENDOR_ATI; + else if (std::string::npos != sversion.find("Mesa")) + vendor = DriverDetails::VENDOR_MESA; else if (std::string::npos != svendor.find("Intel")) vendor = DriverDetails::VENDOR_INTEL; else if (svendor == "ARM") - { vendor = DriverDetails::VENDOR_ARM; - driver = DriverDetails::DRIVER_ARM; - } else if (svendor == "http://limadriver.org/") { vendor = DriverDetails::VENDOR_ARM; @@ -308,24 +307,40 @@ void InitDriverInfo() case DriverDetails::VENDOR_QUALCOMM: { if (std::string::npos != srenderer.find("Adreno (TM) 3")) - devfamily = 300; + driver = DriverDetails::DRIVER_QUALCOMM_3XX; else - devfamily = 200; + driver = DriverDetails::DRIVER_QUALCOMM_2XX; double glVersion; sscanf(g_ogl_config.gl_version, "OpenGL ES %lg V@%lg", &glVersion, &version); } break; case DriverDetails::VENDOR_ARM: if (std::string::npos != srenderer.find("Mali-T6")) - devfamily = 600; + driver = DriverDetails::DRIVER_ARM_T6XX; else if(std::string::npos != srenderer.find("Mali-4")) - devfamily = 400; + driver = DriverDetails::DRIVER_ARM_4XX; + break; + case DriverDetails::VENDOR_MESA: + { + if(svendor == "nouveau") + driver = DriverDetails::DRIVER_NOUVEAU; + else if(svendor == "Intel Open Source Technology Center") + driver = DriverDetails::DRIVER_I965; + else if(std::string::npos != srenderer.find("AMD") || std::string::npos != srenderer.find("ATI")) + driver = DriverDetails::DRIVER_R600; + + int major = 0; + int minor = 0; + int release = 0; + sscanf(g_ogl_config.gl_version, "%*s Mesa %d.%d.%d", &major, &minor, &release); + version = 100*major + 10*minor + release; + } break; // We don't care about these default: break; } - DriverDetails::Init(vendor, driver, devfamily, version); + DriverDetails::Init(vendor, driver, version); } // Init functions @@ -491,18 +506,12 @@ Renderer::Renderer() if(g_ogl_config.max_samples < 1) g_ogl_config.max_samples = 1; - if(g_Config.backend_info.bSupportsGLSLUBO && ( - // hd3000 get corruption, hd4000 also and a big slowdown - !strcmp(g_ogl_config.gl_vendor, "Intel Open Source Technology Center") && ( - !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.0") || - !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.1") || - !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.2") || - !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.0.3") || - !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.1.0") || - !strcmp(g_ogl_config.gl_version, "3.0 Mesa 9.1.1") ) - )) { + if(g_Config.backend_info.bSupportsGLSLUBO && DriverDetails::HasBug(DriverDetails::BUG_BROKENUBO)) + { g_Config.backend_info.bSupportsGLSLUBO = false; ERROR_LOG(VIDEO, "Buggy driver detected. Disable UBO"); + OSD::AddMessage("Major performance warning: Buggy GPU driver detected.", 20000); + OSD::AddMessage("Please either install the closed-source GPU driver or update your Mesa 3D version.", 20000); } UpdateActiveConfig();