mirror of
				https://bitbucket.org/mfeemster/fractorium.git
				synced 2025-10-31 09:20:23 -04:00 
			
		
		
		
	--User changes
-Add support for multiple GPU devices.
  --These options are present in the command line and in Fractorium.
 -Change scheme of specifying devices from platform,device to just total device index.
  --Single number on the command line.
  --Change from combo boxes for device selection to a table of all devices in Fractorium.
 -Temporal samples defaults to 100 instead of 1000 which was needless overkill.
--Bug fixes
 -EmberAnimate, EmberRender, FractoriumSettings, FinalRenderDialog: Fix wrong order of arguments to Clamp() when assigning thread priority.
 -VariationsDC.h: Fix NVidia OpenCL compilation error in DCTriangleVariation.
 -FractoriumXformsColor.cpp: Checking for null pixmap pointer is not enough, must also check if the underlying buffer is null via call to QPixmap::isNull().
--Code changes
 -Ember.h: Add case for FLAME_MOTION_NONE and default in ApplyFlameMotion().
 -EmberMotion.h: Call base constructor.
 -EmberPch.h: #pragma once only on Windows.
 -EmberToXml.h:
  --Handle different types of exceptions.
  --Add default cases to ToString().
 -Isaac.h: Remove unused variable in constructor.
 -Point.h: Call base constructor in Color().
 -Renderer.h/cpp:
  --Add bool to Alloc() to only allocate memory for the histogram. Needed for multi-GPU.
  --Make CoordMap() return a const ref, not a pointer.
 -SheepTools.h:
  --Use 64-bit types like the rest of the code already does.
  --Fix some comment misspellings.
 -Timing.h: Make BeginTime(), EndTime(), ElapsedTime() and Format() be const functions.
 -Utils.h:
  --Add new functions Equal() and Split().
  --Handle more exception types in ReadFile().
  --Get rid of most legacy blending of C and C++ argument parsing.
 -XmlToEmber.h:
  --Get rid of most legacy blending of C and C++ code from flam3.
  --Remove some unused variables.
 -EmberAnimate:
  --Support multi-GPU processing that alternates full frames between devices.
  --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
  --Remove bucketT template parameter, and hard code float in its place.
  --If a render fails, exit since there is no point in continuing an animation with a missing frame.
  --Pass variables to threaded save better, which most likely fixes a very subtle bug that existed before.
  --Remove some unused variables.
 -EmberGenome, EmberRender:
  --Support multi-GPU processing that alternates full frames between devices.
  --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
  --Remove bucketT template parameter, and hard code float in its place.
 -EmberRender:
  --Support multi-GPU processing that alternates full frames between devices.
  --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option.
  --Remove bucketT template parameter, and hard code float in its place.
  --Only print values when not rendering with OpenCL, since they're always 0 in that case.
 -EmberCLPch.h:
  --#pragma once only on Windows.
  --#include <atomic>.
 -IterOpenCLKernelCreator.h: Add new kernel for summing two histograms. This is needed for multi-GPU.
 -OpenCLWrapper.h:
  --Move all OpenCL info related code into its own class OpenCLInfo.
  --Add members to cache the values of global memory size and max allocation size.
 -RendererCL.h/cpp:
  --Redesign to accomodate multi-GPU.
  --Constructor now takes a vector of devices.
  --Remove DumpErrorReport() function, it's handled in the base.
  --ClearBuffer(), ReadPoints(), WritePoints(), ReadHist() and WriteHist() now optionally take a device index as a parameter.
  --MakeDmap() override and m_DmapCL member removed because it no longer applies since the histogram is always float since the last commit.
  --Add new function SumDeviceHist() to sum histograms from two devices by first copying to a temporary on the host, then a temporary on the device, then summing.
  --m_Calls member removed, as it's now per-device.
  --OpenCLWrapper removed.
  --m_Seeds member is now a vector of vector of seeds, to accomodate a separate and different array of seeds for each device.
  --Added member m_Devices, a vector of unique_ptr of RendererCLDevice.
 -EmberCommon.h
  --Added Devices() function to convert from a vector of device indices to a vector of platform,device indices.
  --Changed CreateRenderer() to accept a vector of devices to create a single RendererCL which will split work across multiple devices.
  --Added CreateRenderers() function to accept a vector of devices to create multiple RendererCL, each which will render on a single device.
  --Add more comments to some existing functions.
 -EmberCommonPch.h: #pragma once only on Windows.
 -EmberOptions.h:
  --Remove --platform option, it's just sequential device number now with the --device option.
  --Make --out be OPT_USE_RENDER instead of OPT_RENDER_ANIM since it's an error condition when animating. It makes no sense to write all frames to a single image.
  --Add Devices() function to parse comma separated --device option string and return a vector of device indices.
  --Make int and uint types be 64-bit, so intmax_t and size_t.
  --Make better use of macros.
 -JpegUtils.h: Make string parameters to WriteJpeg() and WritePng() be const ref.
 -All project files: Turn off buffer security check option in Visual Studio (/Gs-)
 -deployment.pri: Remove the line OTHER_FILES +=, it's pointless and was causing problems.
 -Ember.pro, EmberCL.pro: Add CONFIG += plugin, otherwise it wouldn't link.
 -EmberCL.pro: Add new files for multi-GPU support.
 -build_all.sh: use -j4 and QMAKE=${QMAKE:/usr/bin/qmake}
 -shared_settings.pri:
  -Add version string.
  -Remove old DESTDIR definitions.
  -Add the following lines or else nothing would build:
   CONFIG(release, debug|release) {
    CONFIG += warn_off
    DESTDIR = ../../../Bin/release
   }
   CONFIG(debug, debug|release) {
    DESTDIR = ../../../Bin/debug
   }
   QMAKE_POST_LINK += $$quote(cp --update ../../../Data/flam3-palettes.xml $${DESTDIR}$$escape_expand(\n\t))
   LIBS += -L/usr/lib -lpthread
 -AboutDialog.ui: Another futile attempt to make it look correct on Linux.
 -FinalRenderDialog.h/cpp:
  --Add support for multi-GPU.
  --Change from combo boxes for device selection to a table of all devices.
  --Ensure device selection makes sense.
  --Remove "FinalRender" prefix of various function names, it's implied given the context.
 -FinalRenderEmberController.h/cpp:
  --Add support for multi-GPU.
  --Change m_FinishedImageCount to be atomic.
  --Move CancelRender() from the base to FinalRenderEmberController<T>.
  --Refactor RenderComplete() to omit any progress related functionality or image saving since it can be potentially ran in a thread.
  --Consolidate setting various renderer fields into SyncGuiToRenderer().
 -Fractorium.cpp: Allow for resizing of the options dialog to show the entire device table.
 -FractoriumCommon.h: Add various functions to handle a table showing the available OpenCL devices on the system.
 -FractoriumEmberController.h/cpp: Remove m_FinalImageIndex, it's no longer needed.
 -FractoriumRender.cpp: Scale the interactive sub batch count and quality by the number of devices used.
 -FractoriumSettings.h/cpp:
  --Temporal samples defaults to 100 instead of 1000 which was needless overkill.
  --Add multi-GPU support, remove old device,platform pair.
 -FractoriumToolbar.cpp: Disable OpenCL toolbar button if there are no devices present on the system.
 -FractoriumOptionsDialog.h/cpp:
  --Add support for multi-GPU.
  --Consolidate more assignments in DataToGui().
  --Enable/disable CPU/OpenCL items in response to OpenCL checkbox event.
 -Misc: Convert almost everything to size_t for unsigned, intmax_t for signed.
			
			
This commit is contained in:
		
							
								
								
									
										406
									
								
								Source/EmberCL/OpenCLInfo.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										406
									
								
								Source/EmberCL/OpenCLInfo.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,406 @@ | ||||
| #include "EmberCLPch.h" | ||||
| #include "OpenCLInfo.h" | ||||
|  | ||||
| namespace EmberCLns | ||||
| { | ||||
| /// <summary> | ||||
| /// Initialize and return a reference to the one and only OpenCLInfo object. | ||||
| /// </summary> | ||||
| /// <returns>A reference to the only OpenCLInfo object.</returns> | ||||
| OpenCLInfo& OpenCLInfo::Instance() | ||||
| { | ||||
| 	static OpenCLInfo instance; | ||||
|  | ||||
| 	return instance; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Initialize the all platforms and devices and keep information about them in lists. | ||||
| /// </summary> | ||||
| OpenCLInfo::OpenCLInfo() | ||||
| { | ||||
| 	cl_int err; | ||||
| 	vector<cl::Platform> platforms; | ||||
| 	vector<vector<cl::Device>> devices; | ||||
| 	intmax_t workingPlatformIndex = -1; | ||||
|  | ||||
| 	m_Init = false; | ||||
| 	cl::Platform::get(&platforms); | ||||
| 	devices.resize(platforms.size()); | ||||
| 	m_Platforms.reserve(platforms.size()); | ||||
| 	m_Devices.reserve(platforms.size()); | ||||
| 	m_DeviceNames.reserve(platforms.size()); | ||||
| 	m_AllDeviceNames.reserve(platforms.size()); | ||||
| 	m_DeviceIndices.reserve(platforms.size()); | ||||
|  | ||||
| 	for (size_t i = 0; i < platforms.size(); i++) | ||||
| 		platforms[i].getDevices(CL_DEVICE_TYPE_ALL, &devices[i]); | ||||
|  | ||||
| 	for (size_t platform = 0; platform < platforms.size(); platform++) | ||||
| 	{ | ||||
| 		bool platformOk = false; | ||||
| 		bool deviceOk = false; | ||||
| 		cl::Context context; | ||||
|  | ||||
| 		if (CreateContext(platforms[platform], context, false))//Platform is ok, now do context. Unshared by default. | ||||
| 		{ | ||||
| 			size_t workingDeviceIndex = 0; | ||||
|  | ||||
| 			for (size_t device = 0; device < devices[platform].size(); device++)//Context is ok, now do devices. | ||||
| 			{ | ||||
| 				auto q = cl::CommandQueue(context, devices[platform][device], 0, &err);//At least one GPU device is present, so create a command queue. | ||||
|  | ||||
| 				if (CheckCL(err, "cl::CommandQueue()")) | ||||
| 				{ | ||||
| 					if (!platformOk) | ||||
| 					{ | ||||
| 						m_Platforms.push_back(platforms[platform]); | ||||
| 						m_PlatformNames.push_back(platforms[platform].getInfo<CL_PLATFORM_VENDOR>(nullptr) + " " + platforms[platform].getInfo<CL_PLATFORM_NAME>(nullptr) + " " + platforms[platform].getInfo<CL_PLATFORM_VERSION>(nullptr)); | ||||
| 						workingPlatformIndex++; | ||||
| 						platformOk = true; | ||||
| 					} | ||||
|  | ||||
| 					if (!deviceOk) | ||||
| 					{ | ||||
| 						m_Devices.push_back(vector<cl::Device>()); | ||||
| 						m_DeviceNames.push_back(vector<string>()); | ||||
| 						m_Devices.back().reserve(devices[platform].size()); | ||||
| 						m_DeviceNames.back().reserve(devices[platform].size()); | ||||
| 						deviceOk = true; | ||||
| 					} | ||||
|  | ||||
| 					m_Devices.back().push_back(devices[platform][device]); | ||||
| 					m_DeviceNames.back().push_back(devices[platform][device].getInfo<CL_DEVICE_VENDOR>(nullptr) + " " + devices[platform][device].getInfo<CL_DEVICE_NAME>(nullptr));// + " " + devices[platform][device].getInfo<CL_DEVICE_VERSION>()); | ||||
| 					m_AllDeviceNames.push_back(m_DeviceNames.back().back()); | ||||
| 					m_DeviceIndices.push_back(pair<size_t, size_t>(workingPlatformIndex, workingDeviceIndex++)); | ||||
| 					m_Init = true;//If at least one platform and device succeeded, OpenCL is ok. It's now ok to begin building and running programs. | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to the vector of available platforms. | ||||
| /// </summary> | ||||
| /// <returns>A const reference to the vector of available platforms</returns> | ||||
| const vector<cl::Platform>& OpenCLInfo::Platforms() const | ||||
| { | ||||
| 	return m_Platforms; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to the platform name at the specified index. | ||||
| /// </summary> | ||||
| /// <param name="i">The platform index to get the name of</param> | ||||
| /// <returns>The platform name if found, else empty string</returns> | ||||
| const string& OpenCLInfo::PlatformName(size_t platform) const | ||||
| { | ||||
| 	static string s; | ||||
| 	return platform < m_PlatformNames.size() ? m_PlatformNames[platform] : s; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to a vector of all available platform names on the system as a vector of strings. | ||||
| /// </summary> | ||||
| /// <returns>All available platform names on the system as a vector of strings</returns> | ||||
| const vector<string>& OpenCLInfo::PlatformNames() const | ||||
| { | ||||
| 	return m_PlatformNames; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to a vector of vectors of all available devices on the system. | ||||
| /// Each outer vector is a different platform. | ||||
| /// </summary> | ||||
| /// <returns>All available devices on the system, grouped by platform.</returns> | ||||
| const vector<vector<cl::Device>>& OpenCLInfo::Devices() const | ||||
| { | ||||
| 	return m_Devices; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to the device name at the specified index on the platform | ||||
| /// at the specified index. | ||||
| /// </summary> | ||||
| /// <param name="platform">The platform index of the device</param> | ||||
| /// <param name="device">The device index</param> | ||||
| /// <returns>The name of the device if found, else empty string</returns> | ||||
| const string& OpenCLInfo::DeviceName(size_t platform, size_t device) const | ||||
| { | ||||
| 	static string s; | ||||
|  | ||||
| 	if (platform < m_Platforms.size() && platform < m_Devices.size()) | ||||
| 		if (device < m_Devices[platform].size()) | ||||
| 			return m_DeviceNames[platform][device]; | ||||
|  | ||||
| 	return s; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to a vector of pairs of uints which contain the platform,device | ||||
| /// indices of all available devices on the system. | ||||
| /// </summary> | ||||
| /// <returns>All available devices on the system as platform,device index pairs</returns> | ||||
| const vector<pair<size_t, size_t>>& OpenCLInfo::DeviceIndices() const | ||||
| { | ||||
| 	return m_DeviceIndices; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to a vector of all available device names on the system as a vector of strings. | ||||
| /// </summary> | ||||
| /// <returns>All available device names on the system as a vector of strings</returns> | ||||
| const vector<string>& OpenCLInfo::AllDeviceNames() const | ||||
| { | ||||
| 	return m_AllDeviceNames; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get a const reference to a vector of all available device names on the platform | ||||
| /// at the specified index as a vector of strings. | ||||
| /// </summary> | ||||
| /// <param name="platform">The platform index whose devices names will be returned</param> | ||||
| /// <returns>All available device names on the platform at the specified index as a vector of strings if within range, else empty vector.</returns> | ||||
| const vector<string>& OpenCLInfo::DeviceNames(size_t platform) const | ||||
| { | ||||
| 	static vector<string> v; | ||||
|  | ||||
| 	if (platform < m_DeviceNames.size()) | ||||
| 		return m_DeviceNames[platform]; | ||||
|  | ||||
| 	return v; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get the total device index at the specified platform and device index. | ||||
| /// </summary> | ||||
| /// <param name="platform">The platform index of the device</param> | ||||
| /// <param name="device">The device index within the platform</param> | ||||
| /// <returns>The total device index if found, else 0</returns> | ||||
| size_t OpenCLInfo::TotalDeviceIndex(size_t platform, size_t device) const | ||||
| { | ||||
| 	size_t index = 0; | ||||
| 	pair<size_t, size_t> p{ platform, device }; | ||||
|  | ||||
| 	for (size_t i = 0; i < m_DeviceIndices.size(); i++) | ||||
| 	{ | ||||
| 		if (p == m_DeviceIndices[i]) | ||||
| 		{ | ||||
| 			index = i; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Create a context that is optionally shared with OpenGL and plact it in the | ||||
| /// passed in context ref parameter. | ||||
| /// </summary> | ||||
| /// <param name="platform">The platform object to create the context on</param> | ||||
| /// <param name="context">The context object to store the result in</param> | ||||
| /// <param name="shared">True if shared with OpenGL, else not shared.</param> | ||||
| /// <returns>True if success, else false.</returns> | ||||
| bool OpenCLInfo::CreateContext(const cl::Platform& platform, cl::Context& context, bool shared) | ||||
| { | ||||
| 	cl_int err; | ||||
|  | ||||
| 	if (shared) | ||||
| 	{ | ||||
| 		//Define OS-specific context properties and create the OpenCL context. | ||||
| 		#if defined (__APPLE__) || defined(MACOSX) | ||||
| 			CGLContextObj kCGLContext = CGLGetCurrentContext(); | ||||
| 			CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); | ||||
| 			cl_context_properties props[] = | ||||
| 			{ | ||||
| 				CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup, | ||||
| 				0 | ||||
| 			}; | ||||
|  | ||||
| 			context = cl::Context(CL_DEVICE_TYPE_GPU, props, nullptr, nullptr, &err);//May need to tinker with this on Mac. | ||||
| 		#else | ||||
| 			#if defined WIN32 | ||||
| 				cl_context_properties props[] = | ||||
| 				{ | ||||
| 					CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(), | ||||
| 					CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(), | ||||
| 					CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>((platform)()), | ||||
| 					0 | ||||
| 				}; | ||||
|  | ||||
| 				context = cl::Context(CL_DEVICE_TYPE_GPU, props, nullptr, nullptr, &err); | ||||
| 			#else | ||||
| 				cl_context_properties props[] = | ||||
| 				{ | ||||
| 					CL_GL_CONTEXT_KHR, cl_context_properties(glXGetCurrentContext()), | ||||
| 					CL_GLX_DISPLAY_KHR, cl_context_properties(glXGetCurrentDisplay()), | ||||
| 					CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>((platform)()), | ||||
| 					0 | ||||
| 				}; | ||||
|  | ||||
| 				context = cl::Context(CL_DEVICE_TYPE_GPU, props, nullptr, nullptr, &err); | ||||
| 			#endif | ||||
| 		#endif | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		cl_context_properties props[3] = | ||||
| 		{ | ||||
| 			CL_CONTEXT_PLATFORM, | ||||
| 			reinterpret_cast<cl_context_properties>((platform)()), | ||||
| 			0 | ||||
| 		}; | ||||
|  | ||||
| 		context = cl::Context(CL_DEVICE_TYPE_ALL, props, nullptr, nullptr, &err); | ||||
| 	} | ||||
|  | ||||
| 	return CheckCL(err, "cl::Context()"); | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Return whether at least one device has been found and properly initialized. | ||||
| /// </summary> | ||||
| /// <returns>True if success, else false.</returns> | ||||
| bool OpenCLInfo::Ok() const | ||||
| { | ||||
| 	return m_Init; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Get all information about all platforms and devices. | ||||
| /// </summary> | ||||
| /// <returns>A string with all information about all platforms and devices</returns> | ||||
| string OpenCLInfo::DumpInfo() const | ||||
| { | ||||
| 	ostringstream os; | ||||
| 	vector<size_t> sizes; | ||||
|  | ||||
| 	os.imbue(locale("")); | ||||
|  | ||||
| 	for (size_t platform = 0; platform < m_Platforms.size(); platform++) | ||||
| 	{ | ||||
| 		os << "Platform " << platform << ": " << PlatformName(platform) << endl; | ||||
|  | ||||
| 		for (size_t device = 0; device < m_Devices[platform].size(); device++) | ||||
| 		{ | ||||
| 			os << "Device " << device << ": " << DeviceName(platform, device) << endl; | ||||
| 			os << "CL_DEVICE_OPENCL_C_VERSION: " << GetInfo<string>(platform, device, CL_DEVICE_OPENCL_C_VERSION) << endl; | ||||
| 			os << "CL_DEVICE_LOCAL_MEM_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_LOCAL_MEM_SIZE) << endl; | ||||
| 			os << "CL_DEVICE_LOCAL_MEM_TYPE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_LOCAL_MEM_TYPE) << endl; | ||||
| 			os << "CL_DEVICE_MAX_COMPUTE_UNITS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_COMPUTE_UNITS) << endl; | ||||
| 			os << "CL_DEVICE_MAX_READ_IMAGE_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_READ_IMAGE_ARGS) << endl; | ||||
| 			os << "CL_DEVICE_MAX_WRITE_IMAGE_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS) << endl; | ||||
| 			os << "CL_DEVICE_MAX_MEM_ALLOC_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE) << endl; | ||||
| 			os << "CL_DEVICE_ADDRESS_BITS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_ADDRESS_BITS) << endl; | ||||
|  | ||||
| 			os << "CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE) << endl; | ||||
| 			os << "CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE) << endl; | ||||
| 			os << "CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE) << endl; | ||||
| 			os << "CL_DEVICE_GLOBAL_MEM_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_GLOBAL_MEM_SIZE) << endl; | ||||
| 			os << "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE) << endl; | ||||
|  | ||||
| 			os << "CL_DEVICE_MAX_CONSTANT_ARGS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_CONSTANT_ARGS) << endl; | ||||
| 			os << "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: " << GetInfo<cl_uint>(platform, device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS) << endl; | ||||
| 			os << "CL_DEVICE_MAX_WORK_GROUP_SIZE: " << GetInfo<size_t>(platform, device, CL_DEVICE_MAX_WORK_GROUP_SIZE) << endl; | ||||
|  | ||||
| 			sizes = GetInfo<vector<size_t>>(platform, device, CL_DEVICE_MAX_WORK_ITEM_SIZES); | ||||
| 			os << "CL_DEVICE_MAX_WORK_ITEM_SIZES: " << sizes[0] << ", " << sizes[1] << ", " << sizes[2] << endl << endl; | ||||
|  | ||||
| 			if (device != m_Devices[platform].size() - 1 && platform != m_Platforms.size() - 1) | ||||
| 				os << endl; | ||||
| 		} | ||||
|  | ||||
| 		os << endl; | ||||
| 	} | ||||
|  | ||||
| 	return os.str(); | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Check an OpenCL return value for errors. | ||||
| /// </summary> | ||||
| /// <param name="err">The error code to inspect</param> | ||||
| /// <param name="name">A description of where the value was gotten from</param> | ||||
| /// <returns>True if success, else false.</returns> | ||||
| bool OpenCLInfo::CheckCL(cl_int err, const char* name) | ||||
| { | ||||
| 	if (err != CL_SUCCESS) | ||||
| 	{ | ||||
| 		ostringstream ss; | ||||
| 		ss << "ERROR: " << ErrorToStringCL(err) << " in " << name << "." << endl; | ||||
| 		m_ErrorReport.push_back(ss.str()); | ||||
| 	} | ||||
|  | ||||
| 	return err == CL_SUCCESS; | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// Translate an OpenCL error code into a human readable string. | ||||
| /// </summary> | ||||
| /// <param name="err">The error code to translate</param> | ||||
| /// <returns>A human readable description of the error passed in</returns> | ||||
| string OpenCLInfo::ErrorToStringCL(cl_int err) | ||||
| { | ||||
| 	switch (err) | ||||
| 	{ | ||||
| 		case CL_SUCCESS:								   return "Success"; | ||||
| 		case CL_DEVICE_NOT_FOUND:						   return "Device not found"; | ||||
| 		case CL_DEVICE_NOT_AVAILABLE:					   return "Device not available"; | ||||
| 		case CL_COMPILER_NOT_AVAILABLE:					   return "Compiler not available"; | ||||
| 		case CL_MEM_OBJECT_ALLOCATION_FAILURE:			   return "Memory object allocation failure"; | ||||
| 		case CL_OUT_OF_RESOURCES:						   return "Out of resources"; | ||||
| 		case CL_OUT_OF_HOST_MEMORY:						   return "Out of host memory"; | ||||
| 		case CL_PROFILING_INFO_NOT_AVAILABLE:			   return "Profiling information not available"; | ||||
| 		case CL_MEM_COPY_OVERLAP:						   return "Memory copy overlap"; | ||||
| 		case CL_IMAGE_FORMAT_MISMATCH:					   return "Image format mismatch"; | ||||
| 		case CL_IMAGE_FORMAT_NOT_SUPPORTED:				   return "Image format not supported"; | ||||
| 		case CL_BUILD_PROGRAM_FAILURE:					   return "Program build failure"; | ||||
| 		case CL_MAP_FAILURE:							   return "Map failure"; | ||||
| 		case CL_MISALIGNED_SUB_BUFFER_OFFSET:			   return "Misaligned sub buffer offset"; | ||||
| 		case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: return "Exec status error for events in wait list"; | ||||
| 		case CL_INVALID_VALUE:							   return "Invalid value"; | ||||
| 		case CL_INVALID_DEVICE_TYPE:					   return "Invalid device type"; | ||||
| 		case CL_INVALID_PLATFORM:						   return "Invalid platform"; | ||||
| 		case CL_INVALID_DEVICE:							   return "Invalid device"; | ||||
| 		case CL_INVALID_CONTEXT:						   return "Invalid context"; | ||||
| 		case CL_INVALID_QUEUE_PROPERTIES:				   return "Invalid queue properties"; | ||||
| 		case CL_INVALID_COMMAND_QUEUE:					   return "Invalid command queue"; | ||||
| 		case CL_INVALID_HOST_PTR:						   return "Invalid host pointer"; | ||||
| 		case CL_INVALID_MEM_OBJECT:						   return "Invalid memory object"; | ||||
| 		case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:		   return "Invalid image format descriptor"; | ||||
| 		case CL_INVALID_IMAGE_SIZE:						   return "Invalid image size"; | ||||
| 		case CL_INVALID_SAMPLER:						   return "Invalid sampler"; | ||||
| 		case CL_INVALID_BINARY:							   return "Invalid binary"; | ||||
| 		case CL_INVALID_BUILD_OPTIONS:					   return "Invalid build options"; | ||||
| 		case CL_INVALID_PROGRAM:						   return "Invalid program"; | ||||
| 		case CL_INVALID_PROGRAM_EXECUTABLE:				   return "Invalid program executable"; | ||||
| 		case CL_INVALID_KERNEL_NAME:					   return "Invalid kernel name"; | ||||
| 		case CL_INVALID_KERNEL_DEFINITION:				   return "Invalid kernel definition"; | ||||
| 		case CL_INVALID_KERNEL:							   return "Invalid kernel"; | ||||
| 		case CL_INVALID_ARG_INDEX:						   return "Invalid argument index"; | ||||
| 		case CL_INVALID_ARG_VALUE:						   return "Invalid argument value"; | ||||
| 		case CL_INVALID_ARG_SIZE:						   return "Invalid argument size"; | ||||
| 		case CL_INVALID_KERNEL_ARGS:					   return "Invalid kernel arguments"; | ||||
| 		case CL_INVALID_WORK_DIMENSION:					   return "Invalid work dimension"; | ||||
| 		case CL_INVALID_WORK_GROUP_SIZE:				   return "Invalid work group size"; | ||||
| 		case CL_INVALID_WORK_ITEM_SIZE:					   return "Invalid work item size"; | ||||
| 		case CL_INVALID_GLOBAL_OFFSET:					   return "Invalid global offset"; | ||||
| 		case CL_INVALID_EVENT_WAIT_LIST:				   return "Invalid event wait list"; | ||||
| 		case CL_INVALID_EVENT:							   return "Invalid event"; | ||||
| 		case CL_INVALID_OPERATION:						   return "Invalid operation"; | ||||
| 		case CL_INVALID_GL_OBJECT:						   return "Invalid OpenGL object"; | ||||
| 		case CL_INVALID_BUFFER_SIZE:					   return "Invalid buffer size"; | ||||
| 		case CL_INVALID_MIP_LEVEL:						   return "Invalid mip-map level"; | ||||
| 		case CL_INVALID_GLOBAL_WORK_SIZE:				   return "Invalid global work size"; | ||||
| 		case CL_INVALID_PROPERTY:						   return "Invalid property"; | ||||
| 		default: | ||||
| 		{ | ||||
| 			ostringstream ss; | ||||
| 			ss << "<Unknown error code> " << err; | ||||
| 			return ss.str(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 mfeemster
					mfeemster