Cycles: use OpenCL C 2.0 if available, to improve performance for AMD
authorBrecht Van Lommel <brecht@blender.org>
Tue, 24 Mar 2020 18:42:23 +0000 (19:42 +0100)
committerBrecht Van Lommel <brecht@blender.org>
Tue, 24 Mar 2020 19:09:36 +0000 (20:09 +0100)
Tested with AMD Radeon Pro WX 9100, where it brings performance back to 2.80
level, and combined with recent changes is about 2-15% faster than 2.80 in
our benchmark scenes.

This somehow appears to specifically address the issue where adding more shader
nodes leads to slower runtime. I found no additional speedup by applying this
to change to 2.80 or removing the new shader node code.

Ref T71479

Patch by Jeroen Bakker.

Differential Revision: https://developer.blender.org/D6252

intern/cycles/device/opencl/device_opencl.h
intern/cycles/device/opencl/device_opencl_impl.cpp
intern/cycles/device/opencl/opencl_util.cpp

index cee29aefcfdcb64315f2cb6a022cdf7b4fc3977a..d6f4fb430619accd025c7fc64bf9c6233c5faa55 100644 (file)
@@ -88,6 +88,10 @@ class OpenCLInfo {
   static bool device_supported(const string &platform_name, const cl_device_id device_id);
   static bool platform_version_check(cl_platform_id platform, string *error = NULL);
   static bool device_version_check(cl_device_id device, string *error = NULL);
+  static bool get_device_version(cl_device_id device,
+                                 int *r_major,
+                                 int *r_minor,
+                                 string *error = NULL);
   static string get_hardware_id(const string &platform_name, cl_device_id device_id);
   static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices);
 
index 6b1b0e4c369f7a40ae452e72a71096f5d03d66a6..b7a2be79804791f9d641194e69ff77b5bd6c7f0d 100644 (file)
@@ -1896,6 +1896,17 @@ string OpenCLDevice::kernel_build_options(const string *debug_src)
 {
   string build_options = "-cl-no-signed-zeros -cl-mad-enable ";
 
+  /* Build with OpenCL 2.0 if available, this improves performance
+   * with AMD OpenCL drivers on Windows and Linux (legacy drivers).
+   * Note that OpenCL selects the highest 1.x version by default,
+   * only for 2.0 do we need the explicit compiler flag. */
+  int version_major, version_minor;
+  if (OpenCLInfo::get_device_version(cdDevice, &version_major, &version_minor)) {
+    if (version_major >= 2) {
+      build_options += "-cl-std=CL2.0 ";
+    }
+  }
+
   if (platform_name == "NVIDIA CUDA") {
     build_options +=
         "-D__KERNEL_OPENCL_NVIDIA__ "
index aca4ccdde26904f02308f943517fe2cdee097e8c..978c75d2e2c5c3ffbf99a0eb4bbc41749c847047 100644 (file)
@@ -810,18 +810,30 @@ bool OpenCLInfo::platform_version_check(cl_platform_id platform, string *error)
   return true;
 }
 
-bool OpenCLInfo::device_version_check(cl_device_id device, string *error)
+bool OpenCLInfo::get_device_version(cl_device_id device, int *r_major, int *r_minor, string *error)
 {
-  const int req_major = 1, req_minor = 1;
-  int major, minor;
   char version[256];
   clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_VERSION, sizeof(version), &version, NULL);
-  if (sscanf(version, "OpenCL C %d.%d", &major, &minor) < 2) {
+  if (sscanf(version, "OpenCL C %d.%d", r_major, r_minor) < 2) {
     if (error != NULL) {
       *error = string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version);
     }
     return false;
   }
+  if (error != NULL) {
+    *error = "";
+  }
+  return true;
+}
+
+bool OpenCLInfo::device_version_check(cl_device_id device, string *error)
+{
+  const int req_major = 1, req_minor = 1;
+  int major, minor;
+  if (!get_device_version(device, &major, &minor, error)) {
+    return false;
+  }
+
   if (!((major == req_major && minor >= req_minor) || (major > req_major))) {
     if (error != NULL) {
       *error = string_printf("OpenCL: C version 1.1 or later required, found %d.%d", major, minor);