ogl: rework DriverDetails framework + detect UBO mesa bug
This commit is contained in:
parent
d9485cbf23
commit
7a5374258e
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)" : ""
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue