ogl: rework DriverDetails framework + detect UBO mesa bug

This commit is contained in:
degasus 2013-08-23 10:52:29 +02:00
parent d9485cbf23
commit 7a5374258e
4 changed files with 74 additions and 63 deletions

View File

@ -11,8 +11,9 @@ namespace DriverDetails
{ {
struct BugInfo 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 Bug m_bug; // Which bug it is
u32 m_devfamily; // Which device(family) has the error
double m_versionstart; // When it started double m_versionstart; // When it started
double m_versionend; // When it ended double m_versionend; // When it ended
bool m_hasbug; // Does it have it? bool m_hasbug; // Does it have it?
@ -21,40 +22,27 @@ namespace DriverDetails
// Local members // Local members
Vendor m_vendor = VENDOR_UNKNOWN; Vendor m_vendor = VENDOR_UNKNOWN;
Driver m_driver = DRIVER_UNKNOWN; Driver m_driver = DRIVER_UNKNOWN;
u32 m_devfamily = 0;
double m_version = 0.0; double m_version = 0.0;
// This is a list of all known bugs for each vendor // This is a list of all known bugs for each vendor
// We use this to check if the device and driver has a issue // We use this to check if the device and driver has a issue
BugInfo m_qualcommbugs[] = { BugInfo m_known_bugs[] = {
{BUG_NODYNUBOACCESS, 300, 14.0, -1.0}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true},
{BUG_BROKENCENTROID, 300, 14.0, -1.0}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true},
{BUG_BROKENINFOLOG, 300, -1.0, -1.0}, {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<std::pair<Vendor, Bug>, BugInfo> m_bugs; std::map<Bug, BugInfo> m_bugs;
// Private function void Init(Vendor vendor, Driver driver, const double version)
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;
}
}
void Init(Vendor vendor, Driver driver, const u32 devfamily, const double version)
{ {
m_vendor = vendor; m_vendor = vendor;
m_driver = driver; m_driver = driver;
m_devfamily = devfamily;
m_version = version; m_version = version;
InitBugMap();
if (driver == DRIVER_UNKNOWN) if (driver == DRIVER_UNKNOWN)
switch(vendor) switch(vendor)
{ {
@ -68,12 +56,6 @@ namespace DriverDetails
case VENDOR_INTEL: case VENDOR_INTEL:
m_driver = DRIVER_INTEL; m_driver = DRIVER_INTEL;
break; break;
case VENDOR_ARM:
m_driver = DRIVER_ARM;
break;
case VENDOR_QUALCOMM:
m_driver = DRIVER_QUALCOMM;
break;
case VENDOR_IMGTEC: case VENDOR_IMGTEC:
m_driver = DRIVER_IMGTEC; m_driver = DRIVER_IMGTEC;
break; break;
@ -84,15 +66,21 @@ namespace DriverDetails
break; break;
} }
for (auto it = m_bugs.begin(); it != m_bugs.end(); ++it) for(unsigned int a = 0; a < (sizeof(m_known_bugs) / sizeof(BugInfo)); ++a)
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)) if(
it->second.m_hasbug = true; ( 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) 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()) if (it == m_bugs.end())
return false; return false;
return it->second.m_hasbug; return it->second.m_hasbug;

View File

@ -10,7 +10,8 @@ namespace DriverDetails
// Tegra and Nvidia are separated out due to such substantial differences // Tegra and Nvidia are separated out due to such substantial differences
enum Vendor enum Vendor
{ {
VENDOR_NVIDIA = 0, VENDOR_ALL = 0,
VENDOR_NVIDIA,
VENDOR_ATI, VENDOR_ATI,
VENDOR_INTEL, VENDOR_INTEL,
VENDOR_ARM, VENDOR_ARM,
@ -18,20 +19,25 @@ namespace DriverDetails
VENDOR_IMGTEC, VENDOR_IMGTEC,
VENDOR_TEGRA, VENDOR_TEGRA,
VENDOR_VIVANTE, VENDOR_VIVANTE,
VENDOR_MESA,
VENDOR_UNKNOWN VENDOR_UNKNOWN
}; };
// Enum of known drivers // Enum of known drivers
enum Driver 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_NOUVEAU, // OSS nouveau
DRIVER_ATI, // Official ATI DRIVER_ATI, // Official ATI
DRIVER_RADEONHD, // OSS Radeon DRIVER_R600, // OSS Radeon
DRIVER_INTEL, // Official Intel 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_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_FREEDRENO, // OSS Adreno driver
DRIVER_IMGTEC, // OSS PowerVR driver DRIVER_IMGTEC, // OSS PowerVR driver
DRIVER_VIVANTE, // Official vivante driver DRIVER_VIVANTE, // Official vivante driver
@ -69,10 +75,18 @@ namespace DriverDetails
// Adreno devices /always/ return 0 when querying GL_INFO_LOG_LENGTH // 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 // They also max out at 1024 bytes(1023 characters + null terminator) for the log
BUG_BROKENINFOLOG, 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 // 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. // Once Vendor and driver version is set, this will return if it has the applicable bug passed to it.
bool HasBug(Bug bug); bool HasBug(Bug bug);

View File

@ -538,8 +538,8 @@ void ProgramShaderCache::CreateHeader ( void )
, v==GLSL_120 ? "attribute" : "in" , v==GLSL_120 ? "attribute" : "in"
, v==GLSL_120 ? "attribute" : "out" , v==GLSL_120 ? "attribute" : "out"
, DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "in" : v==GLSL_120 ? "varying" : "centroid in" , v==GLSL_120 ? "varying" : DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "in" : "centroid in"
, DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "out" : v==GLSL_120 ? "varying" : "centroid out" , v==GLSL_120 ? "varying" : DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "out" : "centroid out"
, v==GLSL_120 ? "#define texture texture2D" : "" , v==GLSL_120 ? "#define texture texture2D" : ""
, v==GLSL_120 ? "#define round(x) floor((x)+0.5f)" : "" , v==GLSL_120 ? "#define round(x) floor((x)+0.5f)" : ""

View File

@ -271,9 +271,9 @@ void InitDriverInfo()
{ {
std::string svendor = std::string(g_ogl_config.gl_vendor); std::string svendor = std::string(g_ogl_config.gl_vendor);
std::string srenderer = std::string(g_ogl_config.gl_renderer); 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::Vendor vendor = DriverDetails::VENDOR_UNKNOWN;
DriverDetails::Driver driver = DriverDetails::DRIVER_UNKNOWN; DriverDetails::Driver driver = DriverDetails::DRIVER_UNKNOWN;
u32 devfamily = 0;
double version = 0.0; double version = 0.0;
// Get the vendor first // Get the vendor first
@ -281,13 +281,12 @@ void InitDriverInfo()
vendor = DriverDetails::VENDOR_NVIDIA; vendor = DriverDetails::VENDOR_NVIDIA;
else if (svendor == "ATI Technologies Inc." || svendor == "Advanced Micro Devices, Inc.") else if (svendor == "ATI Technologies Inc." || svendor == "Advanced Micro Devices, Inc.")
vendor = DriverDetails::VENDOR_ATI; vendor = DriverDetails::VENDOR_ATI;
else if (std::string::npos != sversion.find("Mesa"))
vendor = DriverDetails::VENDOR_MESA;
else if (std::string::npos != svendor.find("Intel")) else if (std::string::npos != svendor.find("Intel"))
vendor = DriverDetails::VENDOR_INTEL; vendor = DriverDetails::VENDOR_INTEL;
else if (svendor == "ARM") else if (svendor == "ARM")
{
vendor = DriverDetails::VENDOR_ARM; vendor = DriverDetails::VENDOR_ARM;
driver = DriverDetails::DRIVER_ARM;
}
else if (svendor == "http://limadriver.org/") else if (svendor == "http://limadriver.org/")
{ {
vendor = DriverDetails::VENDOR_ARM; vendor = DriverDetails::VENDOR_ARM;
@ -308,24 +307,40 @@ void InitDriverInfo()
case DriverDetails::VENDOR_QUALCOMM: case DriverDetails::VENDOR_QUALCOMM:
{ {
if (std::string::npos != srenderer.find("Adreno (TM) 3")) if (std::string::npos != srenderer.find("Adreno (TM) 3"))
devfamily = 300; driver = DriverDetails::DRIVER_QUALCOMM_3XX;
else else
devfamily = 200; driver = DriverDetails::DRIVER_QUALCOMM_2XX;
double glVersion; double glVersion;
sscanf(g_ogl_config.gl_version, "OpenGL ES %lg V@%lg", &glVersion, &version); sscanf(g_ogl_config.gl_version, "OpenGL ES %lg V@%lg", &glVersion, &version);
} }
break; break;
case DriverDetails::VENDOR_ARM: case DriverDetails::VENDOR_ARM:
if (std::string::npos != srenderer.find("Mali-T6")) if (std::string::npos != srenderer.find("Mali-T6"))
devfamily = 600; driver = DriverDetails::DRIVER_ARM_T6XX;
else if(std::string::npos != srenderer.find("Mali-4")) 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; break;
// We don't care about these // We don't care about these
default: default:
break; break;
} }
DriverDetails::Init(vendor, driver, devfamily, version); DriverDetails::Init(vendor, driver, version);
} }
// Init functions // Init functions
@ -491,18 +506,12 @@ Renderer::Renderer()
if(g_ogl_config.max_samples < 1) if(g_ogl_config.max_samples < 1)
g_ogl_config.max_samples = 1; g_ogl_config.max_samples = 1;
if(g_Config.backend_info.bSupportsGLSLUBO && ( if(g_Config.backend_info.bSupportsGLSLUBO && DriverDetails::HasBug(DriverDetails::BUG_BROKENUBO))
// 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") )
)) {
g_Config.backend_info.bSupportsGLSLUBO = false; g_Config.backend_info.bSupportsGLSLUBO = false;
ERROR_LOG(VIDEO, "Buggy driver detected. Disable UBO"); 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(); UpdateActiveConfig();