[Bf-blender-cvs] [a055073] blender-v2.75-release: Cycles: Rework the way how OpenCL devices are created

Sergey Sharybin noreply at git.blender.org
Mon Jun 29 16:18:37 CEST 2015


Commit: a05507341c1c73124558e3dc2fa6a1a84b6582c6
Author: Sergey Sharybin
Date:   Sat Jun 27 15:03:51 2015 +0200
Branches: blender-v2.75-release
https://developer.blender.org/rBa05507341c1c73124558e3dc2fa6a1a84b6582c6

Cycles: Rework the way how OpenCL devices are created

It was annoying copy-paste happened across OpenCL device constructor, device
enumeration and split kernel checks. Now those areas are using an utility
function which returns pairs of platform and device IDs for devices which are
supported by Cycles and enumeration is happening inside that list.

This makes it so filtering is happening in a single place, so there's no need
to keep 3 different functions in sync.

This commit also fixes a bug with wrong enumeration of devices caused by recent
fixes. Those fixes were in fact wrong and only happened to appear to be working
on laptop with optimus card on Linux. Root of those issues is in fact in bad
Linux driver for optimus cards.

===================================================================

M	intern/cycles/device/device_opencl.cpp

===================================================================

diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index cf8e139..14c65e4 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -62,7 +62,17 @@ CCL_NAMESPACE_BEGIN
  */
 #define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB
 
-static cl_device_type opencl_device_type()
+struct OpenCLPlatformDevice {
+	OpenCLPlatformDevice(cl_platform_id platform_id,
+	                     cl_device_id device_id)
+	  : platform_id(platform_id), device_id(device_id) {}
+	cl_platform_id platform_id;
+	cl_device_id device_id;
+};
+
+namespace {
+
+cl_device_type opencl_device_type()
 {
 	char *device = getenv("CYCLES_OPENCL_TEST");
 
@@ -82,12 +92,12 @@ static cl_device_type opencl_device_type()
 	return CL_DEVICE_TYPE_ALL;
 }
 
-static bool opencl_kernel_use_debug()
+bool opencl_kernel_use_debug()
 {
 	return (getenv("CYCLES_OPENCL_DEBUG") != NULL);
 }
 
-static bool opencl_kernel_use_advanced_shading(const string& platform)
+bool opencl_kernel_use_advanced_shading(const string& platform)
 {
 	/* keep this in sync with kernel_types.h! */
 	if(platform == "NVIDIA CUDA")
@@ -102,6 +112,175 @@ static bool opencl_kernel_use_advanced_shading(const string& platform)
 	return false;
 }
 
+bool opencl_kernel_use_split(const string& platform_name,
+                             const cl_device_type device_type)
+{
+	if(getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST") != NULL) {
+		return true;
+	}
+	/* TODO(sergey): Replace string lookups with more enum-like API,
+	 * similar to device/vendor checks blender's gpu.
+	 */
+	if(platform_name == "AMD Accelerated Parallel Processing" &&
+	   device_type == CL_DEVICE_TYPE_GPU)
+	{
+		return true;
+	}
+	return false;
+}
+
+bool opencl_device_supported(const string& platform_name,
+                             const cl_device_id device_id)
+{
+	cl_device_type device_type;
+	clGetDeviceInfo(device_id,
+	                CL_DEVICE_TYPE,
+	                sizeof(cl_device_type),
+	                &device_type,
+	                NULL);
+	if(platform_name == "AMD Accelerated Parallel Processing" &&
+	   device_type == CL_DEVICE_TYPE_GPU)
+	{
+		return true;;
+	}
+	return false;
+}
+
+bool opencl_platform_version_check(cl_platform_id platform,
+                                   string *error = NULL)
+{
+	const int req_major = 1, req_minor = 1;
+	int major, minor;
+	char version[256];
+	clGetPlatformInfo(platform,
+	                  CL_PLATFORM_VERSION,
+	                  sizeof(version),
+	                  &version,
+	                  NULL);
+	if(sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
+		if(error != NULL) {
+			*error = string_printf("OpenCL: failed to parse platform version string (%s).", version);
+		}
+		return false;
+	}
+	if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
+		if(error != NULL) {
+			*error = string_printf("OpenCL: platform version 1.1 or later required, found %d.%d", major, minor);
+		}
+		return false;
+	}
+	if(error != NULL) {
+		*error = "";
+	}
+	return true;
+}
+
+bool opencl_device_version_check(cl_device_id device,
+                                 string *error = NULL)
+{
+	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(error != NULL) {
+			*error = string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version);
+		}
+		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);
+		}
+		return false;
+	}
+	if(error != NULL) {
+		*error = "";
+	}
+	return true;
+}
+
+void opencl_get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices)
+{
+	const bool force_all_platforms =
+	        (getenv("CYCLES_OPENCL_TEST") != NULL) ||
+	        (getenv("CYCLES_OPENCL_SPLIT_KERNEL_TEST")) != NULL;
+	const cl_device_type device_type = opencl_device_type();
+
+	vector<cl_device_id> device_ids;
+	cl_uint num_devices = 0;
+	vector<cl_platform_id> platform_ids;
+	cl_uint num_platforms = 0;
+
+	/* Number of the devices added to the device info list. */
+	cl_uint num_added_devices = 0;
+
+	/* Get devices. */
+	if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS ||
+	   num_platforms == 0)
+	{
+		return;
+	}
+	platform_ids.resize(num_platforms);
+	if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS) {
+		return;
+	}
+	/* Devices are numbered consecutively across platforms. */
+	int num_base = 0;
+	for(int platform = 0;
+	    platform < num_platforms;
+	    platform++, num_base += num_added_devices)
+	{
+		cl_platform_id platform_id = platform_ids[platform];
+		num_devices = num_added_devices = 0;
+		if(clGetDeviceIDs(platform_id,
+		                  device_type,
+		                  0,
+		                  NULL,
+		                  &num_devices) != CL_SUCCESS || num_devices == 0)
+		{
+			continue;
+		}
+		device_ids.resize(num_devices);
+		if(clGetDeviceIDs(platform_id,
+		                  device_type,
+		                  num_devices,
+		                  &device_ids[0],
+		                  NULL) != CL_SUCCESS)
+		{
+			continue;
+		}
+		if(!opencl_platform_version_check(platform_ids[platform])) {
+			continue;
+		}
+		char pname[256];
+		clGetPlatformInfo(platform_id,
+		                  CL_PLATFORM_NAME,
+		                  sizeof(pname),
+		                  &pname,
+		                  NULL);
+		string platform_name = pname;
+		for(int num = 0; num < num_devices; num++) {
+			cl_device_id device_id = device_ids[num];
+			if(!opencl_device_version_check(device_id)) {
+				continue;
+			}
+			if(force_all_platforms ||
+			   opencl_device_supported(platform_name, device_id))
+			{
+				usable_devices->push_back(OpenCLPlatformDevice(platform_id,
+				                                               device_id));
+			}
+		}
+	}
+}
+
+}  /* namespace */
+
 /* thread safe cache for contexts and programs */
 class OpenCLCache
 {
@@ -421,71 +600,19 @@ public:
 		null_mem = 0;
 		device_initialized = false;
 
-		/* setup platform */
-		cl_uint num_platforms;
-
-		ciErr = clGetPlatformIDs(0, NULL, &num_platforms);
-		if(opencl_error(ciErr))
-			return;
-
-		if(num_platforms == 0) {
-			opencl_error("OpenCL: no platforms found.");
-			return;
-		}
-
-		vector<cl_platform_id> platforms(num_platforms, NULL);
-
-		ciErr = clGetPlatformIDs(num_platforms, &platforms[0], NULL);
-		if(opencl_error(ciErr)) {
-			fprintf(stderr, "clGetPlatformIDs failed \n");
-			return;
-		}
-
-		int num_base = 0;
-		int total_devices = 0;
-
-		for(int platform = 0; platform < num_platforms; platform++) {
-			cl_uint num_devices;
-
-			if(opencl_error(clGetDeviceIDs(platforms[platform], opencl_device_type(), 0, NULL, &num_devices)))
-				return;
-
-			total_devices += num_devices;
-
-			if(info.num - num_base >= num_devices) {
-				/* num doesn't refer to a device in this platform */
-				num_base += num_devices;
-				continue;
-			}
-
-			/* device is in this platform */
-			cpPlatform = platforms[platform];
-
-			/* get devices */
-			vector<cl_device_id> device_ids(num_devices, NULL);
-
-			if(opencl_error(clGetDeviceIDs(cpPlatform, opencl_device_type(), num_devices, &device_ids[0], NULL))) {
-				fprintf(stderr, "clGetDeviceIDs failed \n");
-				return;
-			}
-
-			cdDevice = device_ids[info.num - num_base];
-
-			char name[256];
-			clGetPlatformInfo(cpPlatform, CL_PLATFORM_NAME, sizeof(name), &name, NULL);
-			platform_name = name;
-
-			break;
-		}
-
-		if(total_devices == 0) {
+		vector<OpenCLPlatformDevice> usable_devices;
+		opencl_get_usable_devices(&usable_devices);
+		if(usable_devices.size() == 0) {
 			opencl_error("OpenCL: no devices found.");
 			return;
 		}
-		else if(!cdDevice) {
-			opencl_error("OpenCL: specified device not found.");
-			return;
-		}
+		assert(info.num < usable_devices.size());
+		OpenCLPlatformDevice& platform_device = usable_devices[info.num];
+		cpPlatform = platform_device.platform_id;
+		cdDevice = platform_device.device_id;
+		char name[256];
+		clGetPlatformInfo(cpPlatform, CL_PLATFORM_NAME, sizeof(name), &name, NULL);
+		platform_name = name;
 
 		{
 			/* try to use cached context */
@@ -534,56 +661,6 @@ public:
 		fprintf(stderr, "OpenCL error (%s): %s\n", name, err_info);
 	}
 
-	static bool opencl_platform_version_check(cl_platform_id platform,
-	                                          string *error = NULL)
-	{
-		const int req_major = 1, req_minor = 1;
-		int major, minor;
-		char version[256];
-		clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof(version), &version, NULL);
-		if(sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
-			if(error != NULL) {
-				*error = string_printf("OpenCL: failed to parse platform version string (%s).", version);
-			}
-			return false;
-		}
-		if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
-			if(error != NULL) {
-				*error = string_printf("OpenCL: platform version 1.1 or later required, found %d.%d", major, minor);
-			}
-			return false;
-		}
-		if(error != NULL) {
-			*error = "";
-		}
-		return true;
-	}
-
-	static bool opencl_device_version_check(cl_device_id device,
-	                                        string *error = NULL)
-	{
-		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(error != NULL) {
-				*error = string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version);
-			}
-			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);
-			}
-			return false;
-		}
-		if(error != NULL) {
-			*error = "";
-		}
-		return true;
-	}
-
 	bool opencl_version_check()
 	{
 		string e

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list