Add check for Qualcomm devices on Windows
Some of these devices are not capable of running >=4.0, due to issues with Mesa's Compute Shaders and their D3D drivers. This PR marks those GPUs as unsupported, and prints info to stdout. A driver update will be available for 8cx Gen3 on the 17th October from here: https://www.qualcomm.com/products/mobile/snapdragon/pcs-and-tablets/snapdragon-8-series-mobile-compute-platforms/snapdragon-8cx-gen-3-compute-platform#Software It will take longer via the standard MS Windows Update channels, as there is certification, testing, etc required, but it is possible to get the drivers, at least. This issue applies even when using emulated x64. If this does not get merged, all WoA devices will break with 4.0, where older ones will just launch a grey screen and crash, and newer ones will open, but scenes will not render correctly in Workbench. These devices work by using Mesa's D3D12 Gallium driver ("GLOn12"), which is why we have to read the DirectX driver version - the version reported by OpenGL is the mesa version, which is independent of the driver (which is the part with the bug). Pull Request: https://projects.blender.org/blender/blender/pulls/113674
This commit is contained in:
committed by
Clément Foucault
parent
051b02ed11
commit
4e69e49e7e
@@ -86,6 +86,11 @@ const char *dirname(char *path);
|
||||
bool BLI_windows_is_store_install(void);
|
||||
bool BLI_windows_register_blend_extension(bool all_users);
|
||||
bool BLI_windows_unregister_blend_extension(bool all_users);
|
||||
/* Gets the version of the currently loaded DirectX driver for the first device that matches
|
||||
* deviceString. This is required for Qualcomm devices which use Mesa's Gallium D2D12 layer for
|
||||
* OpenGL functionality */
|
||||
bool BLI_windows_get_directx_driver_version(const wchar_t *deviceSubString,
|
||||
long long *r_driverVersion);
|
||||
|
||||
/**
|
||||
* Set the `root_dir` to the default root directory on MS-Windows,
|
||||
|
||||
@@ -445,6 +445,8 @@ if(WIN32)
|
||||
)
|
||||
list(APPEND LIB
|
||||
bf_intern_utfconv
|
||||
dxguid
|
||||
dxgi
|
||||
)
|
||||
list(APPEND SRC
|
||||
intern/system_win32.c
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
# include <shlwapi.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# define COBJMACROS /* Remove this when converting to C++ */
|
||||
# include <dxgi.h>
|
||||
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
@@ -451,6 +453,37 @@ void BLI_windows_get_default_root_dir(char root[4])
|
||||
}
|
||||
}
|
||||
|
||||
bool BLI_windows_get_directx_driver_version(const wchar_t *deviceSubString,
|
||||
long long *r_driverVersion)
|
||||
{
|
||||
IDXGIFactory *pFactory = NULL;
|
||||
IDXGIAdapter *pAdapter = NULL;
|
||||
if (CreateDXGIFactory(&IID_IDXGIFactory, (void **)&pFactory) == S_OK) {
|
||||
for (UINT i = 0; IDXGIFactory_EnumAdapters(pFactory, i, &pAdapter) != DXGI_ERROR_NOT_FOUND;
|
||||
++i) {
|
||||
LARGE_INTEGER version;
|
||||
if (IDXGIAdapter_CheckInterfaceSupport(pAdapter, &IID_IDXGIDevice, &version) == S_OK) {
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
if (IDXGIAdapter_GetDesc(pAdapter, &desc) == S_OK) {
|
||||
if (wcsstr(desc.Description, deviceSubString)) {
|
||||
*r_driverVersion = version.QuadPart;
|
||||
|
||||
IDXGIAdapter_Release(pAdapter);
|
||||
IDXGIFactory_Release(pFactory);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IDXGIAdapter_Release(pAdapter);
|
||||
}
|
||||
|
||||
IDXGIFactory_Release(pFactory);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* intentionally empty for UNIX */
|
||||
|
||||
@@ -29,7 +29,8 @@ typedef enum eGPUDeviceType {
|
||||
GPU_DEVICE_INTEL_UHD = (1 << 3),
|
||||
GPU_DEVICE_APPLE = (1 << 4),
|
||||
GPU_DEVICE_SOFTWARE = (1 << 5),
|
||||
GPU_DEVICE_UNKNOWN = (1 << 6),
|
||||
GPU_DEVICE_QUALCOMM = (1 << 6),
|
||||
GPU_DEVICE_UNKNOWN = (1 << 7),
|
||||
GPU_DEVICE_ANY = (0xff),
|
||||
} eGPUDeviceType;
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
*/
|
||||
|
||||
#include "BKE_global.h"
|
||||
#if defined(WIN32)
|
||||
# include "BLI_winstuff.h"
|
||||
#endif
|
||||
|
||||
#include "gpu_capabilities_private.hh"
|
||||
#include "gpu_platform_private.hh"
|
||||
@@ -98,8 +101,15 @@ void GLBackend::platform_init()
|
||||
driver = GPU_DRIVER_SOFTWARE;
|
||||
}
|
||||
else if (strstr(vendor, "Microsoft")) {
|
||||
device = GPU_DEVICE_SOFTWARE;
|
||||
driver = GPU_DRIVER_SOFTWARE;
|
||||
/* Qualcomm devices use Mesa's GLOn12, which claims to be vended by Microsoft */
|
||||
if (strstr(renderer, "Qualcomm")) {
|
||||
device = GPU_DEVICE_QUALCOMM;
|
||||
driver = GPU_DRIVER_OFFICIAL;
|
||||
}
|
||||
else {
|
||||
device = GPU_DEVICE_SOFTWARE;
|
||||
driver = GPU_DRIVER_SOFTWARE;
|
||||
}
|
||||
}
|
||||
else if (strstr(vendor, "Apple")) {
|
||||
/* Apple Silicon. */
|
||||
@@ -126,6 +136,31 @@ void GLBackend::platform_init()
|
||||
support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
#if defined(WIN32)
|
||||
long long driverVersion = 0;
|
||||
if (device & GPU_DEVICE_QUALCOMM) {
|
||||
if (BLI_windows_get_directx_driver_version(L"Qualcomm(R) Adreno(TM)", &driverVersion)) {
|
||||
/* Parse out the driver version in format x.x.x.x */
|
||||
WORD ver0 = (driverVersion >> 48) & 0xffff;
|
||||
WORD ver1 = (driverVersion >> 32) & 0xffff;
|
||||
WORD ver2 = (driverVersion >> 16) & 0xffff;
|
||||
|
||||
/* Any Qualcomm driver older than 30.x.x.x will never capable of running blender >= 4.0
|
||||
* As due to an issue in D3D typed UAV load capabilities, Compute Shaders are not available
|
||||
* 30.0.3820.x and above are capable of running blender >=4.0, but these drivers
|
||||
* are only available on 8cx gen3 devices or newer */
|
||||
if (ver0 < 30 || (ver0 == 30 && ver1 == 0 && ver2 < 3820)) {
|
||||
std::cout
|
||||
<< "=====================================\n"
|
||||
<< "Qualcomm drivers older than 30.0.3820.x are not capable of running Blender 4.0\n"
|
||||
<< "If your device is older than an 8cx Gen3, you must use a 3.x LTS release.\n"
|
||||
<< "If you have an 8cx Gen3 or newer device, a driver update may be available.\n"
|
||||
<< "=====================================\n";
|
||||
support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((device & GPU_DEVICE_INTEL) && (os & GPU_OS_WIN)) {
|
||||
/* Old Intel drivers with known bugs that cause material properties to crash.
|
||||
* Version Build 10.18.14.5067 is the latest available and appears to be working
|
||||
@@ -443,6 +478,13 @@ static void detect_workarounds()
|
||||
GCaps.transform_feedback_support = false;
|
||||
}
|
||||
|
||||
/* Right now draw shader parameters are broken on Qualcomm devices
|
||||
* regardless of driver version */
|
||||
if (GPU_type_matches(GPU_DEVICE_QUALCOMM, GPU_OS_WIN, GPU_DRIVER_ANY)) {
|
||||
GCaps.shader_draw_parameters_support = false;
|
||||
GLContext::shader_draw_parameters_support = false;
|
||||
}
|
||||
|
||||
/* Some Intel drivers have issues with using mips as frame-buffer targets if
|
||||
* GL_TEXTURE_MAX_LEVEL is higher than the target MIP.
|
||||
* Only check at the end after all other workarounds because this uses the drawing code.
|
||||
|
||||
@@ -59,14 +59,14 @@ static PyObject *pygpu_platform_version_get(PyObject * /*self*/)
|
||||
return PyUnicode_FromString(GPU_platform_version());
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
pygpu_platform_device_type_get_doc,
|
||||
".. function:: device_type_get()\n"
|
||||
"\n"
|
||||
" Get GPU device type.\n"
|
||||
"\n"
|
||||
" :return: Device type ('APPLE', 'NVIDIA', 'AMD', 'INTEL', 'SOFTWARE', 'UNKNOWN').\n"
|
||||
" :rtype: str\n");
|
||||
PyDoc_STRVAR(pygpu_platform_device_type_get_doc,
|
||||
".. function:: device_type_get()\n"
|
||||
"\n"
|
||||
" Get GPU device type.\n"
|
||||
"\n"
|
||||
" :return: Device type ('APPLE', 'NVIDIA', 'AMD', 'INTEL', 'SOFTWARE', 'QUALCOMM', "
|
||||
"'UNKNOWN').\n"
|
||||
" :rtype: str\n");
|
||||
static PyObject *pygpu_platform_device_type_get(PyObject * /*self*/)
|
||||
{
|
||||
const char *device;
|
||||
@@ -85,6 +85,10 @@ static PyObject *pygpu_platform_device_type_get(PyObject * /*self*/)
|
||||
else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
||||
device = "SOFTWARE";
|
||||
}
|
||||
/* Right now we can only detect Qualcomm GPUs on Windows, not other OSes */
|
||||
else if (GPU_type_matches(GPU_DEVICE_QUALCOMM, GPU_OS_WIN, GPU_DRIVER_ANY)) {
|
||||
device = "QUALCOMM";
|
||||
}
|
||||
else {
|
||||
device = "UNKNOWN";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user