Commit ce1ed238 by Jamie Madill Committed by Commit Bot

D3D11: Detect driver version for blit workaround.

Since the newer driver versions are required for WebGL 2 conformance, we need a solution that can detect a driver version to know if we should apply the workaround. Use a modified copy of Chrome's Windows GPU driver detection code. In the future we should extend this to a full module when we port the command buffer workarounds. BUG=angleproject:1452 Change-Id: I783d5726454671cc22585a2bf990c071d539aa9f Reviewed-on: https://chromium-review.googlesource.com/361962Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 1048e43f
...@@ -326,7 +326,11 @@ static_library("libANGLE") { ...@@ -326,7 +326,11 @@ static_library("libANGLE") {
if (angle_enable_d3d11) { if (angle_enable_d3d11) {
sources += rebase_path(gles_gypi.libangle_d3d11_sources, ".", "src") sources += rebase_path(gles_gypi.libangle_d3d11_sources, ".", "src")
sources += rebase_path(gles_gypi.libangle_d3d11_win32_sources, ".", "src") sources += rebase_path(gles_gypi.libangle_d3d11_win32_sources, ".", "src")
libs += [ "dxguid.lib" ] libs += [
"dxguid.lib",
"Cfgmgr32.lib",
"setupapi.lib",
]
} }
if (angle_enable_gl) { if (angle_enable_gl) {
......
...@@ -6,8 +6,17 @@ ...@@ -6,8 +6,17 @@
// DisplayD3D.cpp: D3D implementation of egl::Display // DisplayD3D.cpp: D3D implementation of egl::Display
// These headers annoyingly have to be the first lines in the file.
#include <Windows.h>
#include <cfgmgr32.h>
#include <strsafe.h>
#include <setupapi.h>
#include <VersionHelpers.h>
#include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h"
#include <EGL/eglext.h>
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Config.h" #include "libANGLE/Config.h"
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
...@@ -19,8 +28,6 @@ ...@@ -19,8 +28,6 @@
#include "libANGLE/renderer/d3d/SwapChainD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h"
#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/DeviceD3D.h"
#include <EGL/eglext.h>
#if defined (ANGLE_ENABLE_D3D9) #if defined (ANGLE_ENABLE_D3D9)
# include "libANGLE/renderer/d3d/d3d9/Renderer9.h" # include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#endif // ANGLE_ENABLE_D3D9 #endif // ANGLE_ENABLE_D3D9
...@@ -350,4 +357,101 @@ egl::Error DisplayD3D::waitNative(EGLint engine, ...@@ -350,4 +357,101 @@ egl::Error DisplayD3D::waitNative(EGLint engine,
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
// TODO(jmadill): Do more complete GPU info collection.
egl::Error DisplayD3D::getDriverVersion(const std::string &deviceId, std::string *resultOut)
{
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
// TODO(jmadill): Figure out what to return for Windows Store.
*resultOut = "";
return gl::NoError();
#else
// Display adapter class GUID from
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
GUID displayClass = {
0x4d36e968, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
// create device info for the display device
HDEVINFO deviceInfo;
if (!IsWindowsVistaOrGreater())
{
// Collection of information on all adapters is much slower on XP (almost
// 100ms), and not very useful (as it's not going to use the GPU anyway), so
// just collect information on the current device. http://crbug.com/456178
deviceInfo = SetupDiGetClassDevsA(nullptr, deviceId.c_str(), nullptr,
DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
}
else
{
deviceInfo = SetupDiGetClassDevsA(&displayClass, nullptr, nullptr, DIGCF_PRESENT);
}
if (deviceInfo == INVALID_HANDLE_VALUE)
{
return egl::Error(EGL_BAD_MATCH, "Creating device info failed");
}
bool found = false;
DWORD index = 0;
SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof(deviceInfoData);
while (SetupDiEnumDeviceInfo(deviceInfo, index++, &deviceInfoData))
{
CHAR value[255];
if (SetupDiGetDeviceRegistryPropertyA(deviceInfo, &deviceInfoData, SPDRP_DRIVER, nullptr,
reinterpret_cast<PBYTE>(value), sizeof(value),
nullptr))
{
HKEY key;
std::string driverKey = "System\\CurrentControlSet\\Control\\Class\\";
driverKey += value;
LONG result =
RegOpenKeyExA(HKEY_LOCAL_MACHINE, driverKey.c_str(), 0, KEY_QUERY_VALUE, &key);
if (result == ERROR_SUCCESS)
{
DWORD dwcbData = sizeof(value);
std::string driverVersion;
result = RegQueryValueExA(key, "DriverVersion", nullptr, nullptr,
reinterpret_cast<LPBYTE>(value), &dwcbData);
if (result == ERROR_SUCCESS)
driverVersion = value;
std::string driverDate;
dwcbData = sizeof(value);
result = RegQueryValueExA(key, "DriverDate", nullptr, nullptr,
reinterpret_cast<LPBYTE>(value), &dwcbData);
if (result == ERROR_SUCCESS)
driverDate = value;
std::string driverVendor;
dwcbData = sizeof(value);
result = RegQueryValueExA(key, "ProviderName", nullptr, nullptr,
reinterpret_cast<LPBYTE>(value), &dwcbData);
if (result == ERROR_SUCCESS)
driverVendor = value;
char newDeviceID[MAX_DEVICE_ID_LEN];
CONFIGRET status =
CM_Get_Device_IDA(deviceInfoData.DevInst, newDeviceID, MAX_DEVICE_ID_LEN, 0);
if (status == CR_SUCCESS)
{
std::string id = newDeviceID;
if (id.compare(0, deviceId.size(), deviceId) == 0)
{
*resultOut = driverVersion;
found = true;
}
}
RegCloseKey(key);
}
}
}
return found ? egl::Error(EGL_SUCCESS) : egl::Error(EGL_BAD_MATCH, "No driver version found");
#endif // defined(ANGLE_ENABLE_WINDOWS_STORE)
}
} // namespace rx } // namespace rx
...@@ -70,6 +70,8 @@ class DisplayD3D : public DisplayImpl ...@@ -70,6 +70,8 @@ class DisplayD3D : public DisplayImpl
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface) const override; egl::Surface *readSurface) const override;
egl::Error getDriverVersion(const std::string &deviceId, std::string *resultOut);
private: private:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
......
...@@ -48,9 +48,11 @@ struct WorkaroundsD3D ...@@ -48,9 +48,11 @@ struct WorkaroundsD3D
// emulation that is implemented using instanced quads. // emulation that is implemented using instanced quads.
bool useInstancedPointSpriteEmulation = false; bool useInstancedPointSpriteEmulation = false;
// NVIDIA driver versions 347.88 <= x < 368.69 have a bug where using CopySubresourceRegion // A bug fixed in NVIDIA driver version 347.88 < x <= 368.81 triggers a TDR when using
// from a staging texture to a depth/stencil texture triggers a timeout/TDR. The workaround // CopySubresourceRegion from a staging texture to a depth/stencil in D3D11. The workaround
// is to use UpdateSubresource to trigger an extra copy. // is to use UpdateSubresource to trigger an extra copy. We disable this workaround on newer
// NVIDIA driver versions because of a second driver bug present with the workaround enabled.
// (See: http://anglebug.com/1452)
bool depthStencilBlitExtraCopy = false; bool depthStencilBlitExtraCopy = false;
// The HLSL optimizer has a bug with optimizing "pow" in certain integer-valued expressions. // The HLSL optimizer has a bug with optimizing "pow" in certain integer-valued expressions.
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <iomanip>
#include <sstream> #include <sstream>
#include <versionhelpers.h> #include <versionhelpers.h>
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
#include "libANGLE/Program.h" #include "libANGLE/Program.h"
#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/d3d/CompilerD3D.h" #include "libANGLE/renderer/d3d/CompilerD3D.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/d3d11/Blit11.h" #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h" #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
...@@ -4133,7 +4135,22 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC ...@@ -4133,7 +4135,22 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC
WorkaroundsD3D Renderer11::generateWorkarounds() const WorkaroundsD3D Renderer11::generateWorkarounds() const
{ {
return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription); auto displayD3D = GetImplAs<DisplayD3D>(mDisplay);
std::string driverVersion;
std::stringstream deviceStr;
deviceStr << std::uppercase << std::hex;
deviceStr << "PCI\\VEN_" << std::setfill('0') << std::setw(4) << mAdapterDescription.VendorId;
deviceStr << "&DEV_" << std::setfill('0') << std::setw(4) << mAdapterDescription.DeviceId;
deviceStr << "&SUBSYS_" << std::setfill('0') << std::setw(8) << mAdapterDescription.SubSysId;
deviceStr << "&REV_" << std::setfill('0') << std::setw(2) << mAdapterDescription.Revision;
auto err = displayD3D->getDriverVersion(deviceStr.str(), &driverVersion);
if (err.isError())
{
ERR("error getting driver version: ", err.getMessage().c_str());
}
return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription, driverVersion);
} }
gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
......
...@@ -1507,7 +1507,8 @@ ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device) ...@@ -1507,7 +1507,8 @@ ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
} }
WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
const DXGI_ADAPTER_DESC &adapterDesc) const DXGI_ADAPTER_DESC &adapterDesc,
const std::string &driverVersion)
{ {
bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
...@@ -1518,7 +1519,29 @@ WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, ...@@ -1518,7 +1519,29 @@ WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
workarounds.useInstancedPointSpriteEmulation = is9_3; workarounds.useInstancedPointSpriteEmulation = is9_3;
// TODO(jmadill): Narrow problematic driver range. // TODO(jmadill): Narrow problematic driver range.
workarounds.depthStencilBlitExtraCopy = (adapterDesc.VendorId == VENDOR_ID_NVIDIA); if (adapterDesc.VendorId == VENDOR_ID_NVIDIA)
{
if (!driverVersion.empty())
{
// parse the major and minor version numbers
uint32_t x, y, z, w;
std::stringstream parser(driverVersion);
parser >> x;
parser.ignore(1);
parser >> y;
parser.ignore(1);
parser >> z;
parser.ignore(1);
parser >> w;
// Disable the workaround to fix a second driver bug on newer NVIDIA.
workarounds.depthStencilBlitExtraCopy = (z <= 13u && w < 6881);
}
else
{
workarounds.depthStencilBlitExtraCopy = true;
}
}
// TODO(jmadill): Disable workaround when we have a fixed compiler DLL. // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
workarounds.expandIntegerPowExpressions = true; workarounds.expandIntegerPowExpressions = true;
......
...@@ -347,7 +347,8 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c ...@@ -347,7 +347,8 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c
} }
WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
const DXGI_ADAPTER_DESC &adapterDesc); const DXGI_ADAPTER_DESC &adapterDesc,
const std::string &driverVersion);
enum ReservedConstantBufferSlot enum ReservedConstantBufferSlot
{ {
......
...@@ -797,16 +797,20 @@ ...@@ -797,16 +797,20 @@
{ {
'AdditionalDependencies': 'AdditionalDependencies':
[ [
'Cfgmgr32.lib',
'dxguid.lib', 'dxguid.lib',
'setupapi.lib',
], ],
}], }],
['angle_build_winrt==1', ['angle_build_winrt==1',
{ {
'AdditionalDependencies': 'AdditionalDependencies':
[ [
'Cfgmgr32.lib',
'dxguid.lib', 'dxguid.lib',
'd3d11.lib', 'd3d11.lib',
'd3dcompiler.lib', 'd3dcompiler.lib',
'setupapi.lib',
], ],
}], }],
], ],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment