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
{
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<std::pair<Vendor, Bug>, 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<Bug, BugInfo> 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;

View File

@ -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);

View File

@ -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)" : ""

View File

@ -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();