diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp index bcf4d3ea769..e6a13e04b48 100644 --- a/intern/cycles/app/cycles_server.cpp +++ b/intern/cycles/app/cycles_server.cpp @@ -34,8 +34,9 @@ int main(int argc, const char **argv) /* device types */ string devices = ""; string devicename = "cpu"; + bool list = false; - vector types = Device::available_types(); + vector& types = Device::available_types(); foreach(DeviceType type, types) { if(devices != "") @@ -49,6 +50,7 @@ int main(int argc, const char **argv) ap.options ("Usage: cycles_server [options]", "--device %s", &devicename, ("Devices to use: " + devices).c_str(), + "--list-devices", &list, "List information about all available devices", NULL); if(ap.parse(argc, argv) < 0) { @@ -56,11 +58,34 @@ int main(int argc, const char **argv) ap.usage(); exit(EXIT_FAILURE); } + else if(list) { + vector& devices = Device::available_devices(); - DeviceType dtype = Device::type_from_string(devicename.c_str()); + printf("Devices:\n"); + + foreach(DeviceInfo& info, devices) { + printf(" %s%s\n", + info.description.c_str(), + (info.display_device)? " (display)": ""); + } + + exit(EXIT_SUCCESS); + } + + /* find matching device */ + DeviceType device_type = Device::type_from_string(devicename.c_str()); + vector& devices = Device::available_devices(); + DeviceInfo device_info; + + foreach(DeviceInfo& device, devices) { + if(device_type == device.type) { + device_info = device; + break; + } + } while(1) { - Device *device = Device::create(dtype); + Device *device = Device::create(device_info); printf("Cycles Server with device: %s\n", device->description().c_str()); device->server_run(); delete device; diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index d9386f75141..0b8853d7036 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -203,17 +203,18 @@ static void options_parse(int argc, const char **argv) options.session = NULL; options.quiet = false; - /* devices */ - string devices = ""; + /* device names */ + string device_names = ""; string devicename = "cpu"; + bool list = false; - vector types = Device::available_types(); + vector& types = Device::available_types(); foreach(DeviceType type, types) { - if(devices != "") - devices += ", "; + if(device_names != "") + device_names += ", "; - devices += Device::string_from_type(type); + device_names += Device::string_from_type(type); } /* shading system */ @@ -230,7 +231,7 @@ static void options_parse(int argc, const char **argv) ap.options ("Usage: cycles_test [options] file.xml", "%*", files_parse, "", - "--device %s", &devicename, ("Devices to use: " + devices).c_str(), + "--device %s", &devicename, ("Devices to use: " + device_names).c_str(), "--shadingsys %s", &ssname, "Shading system to use: svm, osl", "--background", &options.session_params.background, "Render in background, without user interface", "--quiet", &options.quiet, "In background mode, don't print progress messages", @@ -239,6 +240,7 @@ static void options_parse(int argc, const char **argv) "--threads %d", &options.session_params.threads, "CPU Rendering Threads", "--width %d", &options.width, "Window width in pixel", "--height %d", &options.height, "Window height in pixel", + "--list-devices", &list, "List information about all available devices", "--help", &help, "Print help message", NULL); @@ -247,26 +249,44 @@ static void options_parse(int argc, const char **argv) ap.usage(); exit(EXIT_FAILURE); } + else if(list) { + vector& devices = Device::available_devices(); + printf("Devices:\n"); + + foreach(DeviceInfo& info, devices) { + printf(" %s%s\n", + info.description.c_str(), + (info.display_device)? " (display)": ""); + } + + exit(EXIT_SUCCESS); + } else if(help || options.filepath == "") { ap.usage(); exit(EXIT_SUCCESS); } - options.session_params.device_type = Device::type_from_string(devicename.c_str()); - if(ssname == "osl") options.scene_params.shadingsystem = SceneParams::OSL; else if(ssname == "svm") options.scene_params.shadingsystem = SceneParams::SVM; + /* find matching device */ + DeviceType device_type = Device::type_from_string(devicename.c_str()); + vector& devices = Device::available_devices(); + DeviceInfo device_info; + bool device_available = false; + + foreach(DeviceInfo& device, devices) { + if(device_type == device.type) { + options.session_params.device = device; + device_available = true; + break; + } + } + /* handle invalid configurations */ - bool type_available = false; - - foreach(DeviceType dtype, types) - if(options.session_params.device_type == dtype) - type_available = true; - - if(options.session_params.device_type == DEVICE_NONE || !type_available) { + if(options.session_params.device.type == DEVICE_NONE || !device_available) { fprintf(stderr, "Unknown device: %s\n", devicename.c_str()); exit(EXIT_FAILURE); } @@ -278,7 +298,7 @@ static void options_parse(int argc, const char **argv) fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str()); exit(EXIT_FAILURE); } - else if(options.scene_params.shadingsystem == SceneParams::OSL && options.session_params.device_type != DEVICE_CPU) { + else if(options.scene_params.shadingsystem == SceneParams::OSL && options.session_params.device.type != DEVICE_CPU) { fprintf(stderr, "OSL shading system only works with CPU device\n"); exit(EXIT_FAILURE); } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 286a9b5b24f..8f54f291cfb 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -248,10 +248,10 @@ bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background) return (background)? false: get_boolean(cscene, "preview_pause"); } -static bool device_type_available(vector& types, DeviceType dtype) +static bool device_type_available(vector& devices, DeviceType dtype) { - foreach(DeviceType dt, types) - if(dt == dtype) + foreach(DeviceInfo& info, devices) + if(info.type == dtype) return true; return false; @@ -266,24 +266,28 @@ SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background params.experimental = (RNA_enum_get(&cscene, "feature_set") != 0); /* device type */ - params.device_type = DEVICE_CPU; + vector devices = Device::available_devices(); + DeviceType device_type = DEVICE_CPU; if(RNA_enum_get(&cscene, "device") != 0) { - vector types = Device::available_types(); - DeviceType dtype; if(!params.experimental || RNA_enum_get(&cscene, "gpu_type") == 0) - dtype = DEVICE_CUDA; + device_type = DEVICE_CUDA; else - dtype = DEVICE_OPENCL; + device_type = DEVICE_OPENCL; - if(device_type_available(types, dtype)) - params.device_type = dtype; - else if(params.experimental && device_type_available(types, DEVICE_OPENCL)) - params.device_type = DEVICE_OPENCL; - else if(device_type_available(types, DEVICE_CUDA)) - params.device_type = DEVICE_CUDA; + if(device_type_available(devices, device_type)) + ; + else if(params.experimental && device_type_available(devices, DEVICE_OPENCL)) + device_type = DEVICE_OPENCL; + else if(device_type_available(devices, DEVICE_CUDA)) + device_type = DEVICE_CUDA; } + + params.device = devices[0]; + foreach(DeviceInfo& info, devices) + if(info.type == device_type) + params.device = info; /* Background */ params.background = background; diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 55fc3bacbba..83600120fdd 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -118,7 +118,7 @@ void Device::pixels_free(device_memory& mem) mem_free(mem); } -void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height, bool transparent) +void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent) { pixels_copy_from(rgba, y, w, h); @@ -128,7 +128,7 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, in } glPixelZoom((float)width/(float)w, (float)height/(float)h); - glRasterPos2f(0, y); + glRasterPos2f(0, dy); uint8_t *pixels = (uint8_t*)rgba.data_pointer; @@ -145,36 +145,36 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, in glDisable(GL_BLEND); } -Device *Device::create(DeviceType type, bool background, int threads) +Device *Device::create(DeviceInfo& info, bool background, int threads) { Device *device; - switch(type) { + switch(info.type) { case DEVICE_CPU: - device = device_cpu_create(threads); + device = device_cpu_create(info, threads); break; #ifdef WITH_CUDA case DEVICE_CUDA: if(cuLibraryInit()) - device = device_cuda_create(background); + device = device_cuda_create(info, background); else device = NULL; break; #endif #ifdef WITH_MULTI case DEVICE_MULTI: - device = device_multi_create(background); + device = device_multi_create(info, background); break; #endif #ifdef WITH_NETWORK case DEVICE_NETWORK: - device = device_network_create("127.0.0.1"); + device = device_network_create(info, "127.0.0.1"); break; #endif #ifdef WITH_OPENCL case DEVICE_OPENCL: if(clLibraryInit()) - device = device_opencl_create(background); + device = device_opencl_create(info, background); else device = NULL; break; @@ -218,31 +218,68 @@ string Device::string_from_type(DeviceType type) return ""; } -vector Device::available_types() +vector& Device::available_types() { - vector types; + static vector types; + static bool types_init = false; - types.push_back(DEVICE_CPU); + if(!types_init) { + types.push_back(DEVICE_CPU); #ifdef WITH_CUDA - if(cuLibraryInit()) - types.push_back(DEVICE_CUDA); + if(cuLibraryInit()) + types.push_back(DEVICE_CUDA); #endif #ifdef WITH_OPENCL - if(clLibraryInit()) - types.push_back(DEVICE_OPENCL); + if(clLibraryInit()) + types.push_back(DEVICE_OPENCL); #endif #ifdef WITH_NETWORK - types.push_back(DEVICE_NETWORK); + types.push_back(DEVICE_NETWORK); #endif #ifdef WITH_MULTI - types.push_back(DEVICE_MULTI); + types.push_back(DEVICE_MULTI); #endif + types_init = true; + } + return types; } +vector& Device::available_devices() +{ + static vector devices; + static bool devices_init = false; + + if(!devices_init) { + device_cpu_info(devices); + +#ifdef WITH_CUDA + if(cuLibraryInit()) + device_cuda_info(devices); +#endif + +#ifdef WITH_OPENCL + if(clLibraryInit()) + device_opencl_info(devices); +#endif + +#ifdef WITH_MULTI + device_multi_info(devices); +#endif + +#ifdef WITH_NETWORK + device_network_info(devices); +#endif + + devices_init = true; + } + + return devices; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index af9bb694c1b..51505aa9cb9 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -33,6 +33,8 @@ CCL_NAMESPACE_BEGIN class Progress; +/* Device Types */ + enum DeviceType { DEVICE_NONE, DEVICE_CPU, @@ -42,10 +44,22 @@ enum DeviceType { DEVICE_MULTI }; -enum MemoryType { - MEM_READ_ONLY, - MEM_WRITE_ONLY, - MEM_READ_WRITE +class DeviceInfo { +public: + DeviceType type; + string description; + string id; + int num; + bool display_device; + vector multi_devices; + + DeviceInfo() + { + type = DEVICE_CPU; + id = "CPU"; + num = 0; + display_device = false; + } }; /* Device Task */ @@ -91,7 +105,7 @@ public: /* info */ virtual string description() = 0; - const string& error_message() { return error_msg; } + virtual const string& error_message() { return error_msg; } /* regular memory */ virtual void mem_alloc(device_memory& mem, MemoryType type) = 0; @@ -127,7 +141,7 @@ public: /* opengl drawing */ virtual void draw_pixels(device_memory& mem, int y, int w, int h, - int width, int height, bool transparent); + int dy, int width, int height, bool transparent); #ifdef WITH_NETWORK /* networking */ @@ -135,11 +149,12 @@ public: #endif /* static */ - static Device *create(DeviceType type, bool background = true, int threads = 0); + static Device *create(DeviceInfo& info, bool background = true, int threads = 0); static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); - static vector available_types(); + static vector& available_types(); + static vector& available_devices(); }; CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 145eab9ff59..c93c6ff17da 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -258,10 +258,22 @@ public: } }; -Device *device_cpu_create(int threads) +Device *device_cpu_create(DeviceInfo& info, int threads) { return new CPUDevice(threads); } +void device_cpu_info(vector& devices) +{ + DeviceInfo info; + + info.type = DEVICE_CPU; + info.description = system_cpu_brand_string(); + info.id = "CPU"; + info.num = 0; + + devices.push_back(info); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 3c5aafd3f60..73d87ae4a2e 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -159,11 +159,11 @@ public: cuda_assert(cuCtxSetCurrent(NULL)); } - CUDADevice(bool background_) + CUDADevice(DeviceInfo& info, bool background_) { background = background_; - cuDevId = 0; + cuDevId = info.num; cuDevice = 0; cuContext = 0; @@ -205,7 +205,7 @@ public: string description() { /* print device information */ - char deviceName[100]; + char deviceName[256]; cuda_push_context(); cuDeviceGetName(deviceName, 256, cuDevId); @@ -768,7 +768,7 @@ public: } } - void draw_pixels(device_memory& mem, int y, int w, int h, int width, int height, bool transparent) + void draw_pixels(device_memory& mem, int y, int w, int h, int dy, int width, int height, bool transparent) { if(!background) { PixelMem pmem = pixel_mem_map[mem.device_pointer]; @@ -794,7 +794,7 @@ public: glColor3f(1.0f, 1.0f, 1.0f); glPushMatrix(); - glTranslatef(0.0f, (float)y, 0.0f); + glTranslatef(0.0f, (float)dy, 0.0f); glBegin(GL_QUADS); @@ -822,7 +822,7 @@ public: return; } - Device::draw_pixels(mem, y, w, h, width, height, transparent); + Device::draw_pixels(mem, y, w, h, dy, width, height, transparent); } void task_add(DeviceTask& task) @@ -849,9 +849,40 @@ public: } }; -Device *device_cuda_create(bool background) +Device *device_cuda_create(DeviceInfo& info, bool background) { - return new CUDADevice(background); + return new CUDADevice(info, background); +} + +void device_cuda_info(vector& devices) +{ + int count = 0; + + if(cuInit(0) != CUDA_SUCCESS) + return; + if(cuDeviceGetCount(&count) != CUDA_SUCCESS) + return; + + for(int num = 0; num < count; num++) { + char name[256]; + int attr; + + if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS) + continue; + + DeviceInfo info; + + info.type = DEVICE_CUDA; + info.description = string(name); + info.id = string_printf("CUDA_%d", num); + info.num = num; + + /* if device has a kernel timeout, assume it is used for display */ + if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) + info.display_device = true; + + devices.push_back(info); + } } CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index e098ac1f0e3..e3601aa8ad4 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -23,11 +23,17 @@ CCL_NAMESPACE_BEGIN class Device; -Device *device_cpu_create(int threads); -Device *device_opencl_create(bool background); -Device *device_cuda_create(bool background); -Device *device_network_create(const char *address); -Device *device_multi_create(bool background); +Device *device_cpu_create(DeviceInfo& info, int threads); +Device *device_opencl_create(DeviceInfo& info, bool background); +Device *device_cuda_create(DeviceInfo& info, bool background); +Device *device_network_create(DeviceInfo& info, const char *address); +Device *device_multi_create(DeviceInfo& info, bool background); + +void device_cpu_info(vector& devices); +void device_opencl_info(vector& devices); +void device_cuda_info(vector& devices); +void device_network_info(vector& devices); +void device_multi_info(vector& devices); CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 516a6bd0739..3223ca91b9e 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -36,6 +36,12 @@ CCL_NAMESPACE_BEGIN +enum MemoryType { + MEM_READ_ONLY, + MEM_WRITE_ONLY, + MEM_READ_WRITE +}; + /* Supported Data Types */ enum DataType { diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 7f24e5789cc..f8b512f209c 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -44,32 +44,18 @@ public: list devices; device_ptr unique_ptr; - MultiDevice(bool background_) + MultiDevice(DeviceInfo& info, bool background_) : unique_ptr(1) { Device *device; + background = background_; - /* add CPU device */ - device = Device::create(DEVICE_CPU, background); - devices.push_back(SubDevice(device)); - -#ifdef WITH_CUDA - /* try to add GPU device */ - device = Device::create(DEVICE_CUDA, background); - if(device) { + foreach(DeviceInfo& subinfo, info.multi_devices) { + device = Device::create(subinfo, background); devices.push_back(SubDevice(device)); } - else -#endif - { -#ifdef WITH_OPENCL - device = Device::create(DEVICE_OPENCL, background); - if(device) - devices.push_back(SubDevice(device)); -#endif - } -#ifdef WITH_NETWORK +#if 0 //def WITH_NETWORK /* try to add network devices */ ServerDiscovery discovery(true); time_sleep(1.0); @@ -77,7 +63,7 @@ public: list servers = discovery.get_server_list(); foreach(string& server, servers) { - device = device_network_create(server.c_str()); + device = device_network_create(info, server.c_str()); if(device) devices.push_back(SubDevice(device)); } @@ -100,6 +86,19 @@ public: return true; } + const string& error_message() + { + foreach(SubDevice& sub, devices) { + if(sub.device->error_message() != "") { + if(error_msg == "") + error_msg = sub.device->error_message(); + break; + } + } + + return error_msg; + } + string description() { /* create map to find duplicate descriptions */ @@ -274,7 +273,7 @@ public: mem.device_pointer = tmp; } - void draw_pixels(device_memory& rgba, int y, int w, int h, int width, int height, bool transparent) + void draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent) { device_ptr tmp = rgba.device_pointer; int i = 0, sub_h = h/devices.size(); @@ -284,10 +283,11 @@ public: int sy = y + i*sub_h; int sh = (i == (int)devices.size() - 1)? h - sub_h*i: sub_h; int sheight = (i == (int)devices.size() - 1)? height - sub_height*i: sub_height; + int sdy = dy + i*sub_height; /* adjust math for w/width */ rgba.device_pointer = sub.ptr_map[tmp]; - sub.device->draw_pixels(rgba, sy, w, sh, width, sheight, transparent); + sub.device->draw_pixels(rgba, sy, w, sh, sdy, width, sheight, transparent); i++; } @@ -327,9 +327,103 @@ public: } }; -Device *device_multi_create(bool background) +Device *device_multi_create(DeviceInfo& info, bool background) { - return new MultiDevice(background); + return new MultiDevice(info, background); +} + +static void device_multi_add(vector& devices, DeviceType type, bool skip_display, const char *id_fmt, int num) +{ + DeviceInfo info; + + /* create map to find duplicate descriptions */ + map dupli_map; + map::iterator dt; + int num_added = 0, num_skipped = 0; + + foreach(DeviceInfo& subinfo, devices) { + if(subinfo.type == type) { + if(skip_display && subinfo.display_device) { + num_skipped++; + } + else { + string key = subinfo.description; + + if(dupli_map.find(key) == dupli_map.end()) + dupli_map[key] = 1; + else + dupli_map[key]++; + + info.multi_devices.push_back(subinfo); + if(subinfo.display_device) + info.display_device = true; + num_added++; + } + } + } + + if(num_added <= 1 || (skip_display && num_skipped == 0)) + return; + + /* generate string */ + stringstream desc; + vector last_tokens; + bool first = true; + + for(dt = dupli_map.begin(); dt != dupli_map.end(); dt++) { + if(!first) desc << " + "; + first = false; + + /* get name and count */ + string name = dt->first; + int count = dt->second; + + /* strip common prefixes */ + vector tokens; + string_split(tokens, dt->first); + + if(tokens.size() > 1) { + int i; + + for(i = 0; i < tokens.size() && i < last_tokens.size(); i++) + if(tokens[i] != last_tokens[i]) + break; + + name = ""; + for(; i < tokens.size(); i++) { + name += tokens[i]; + if(i != tokens.size() - 1) + name += " "; + } + } + + last_tokens = tokens; + + /* add */ + if(count > 1) + desc << name << " (" << count << "x)"; + else + desc << name; + } + + /* add info */ + info.type = DEVICE_MULTI; + info.description = desc.str(); + info.id = string_printf(id_fmt, num); + info.num = 0; + + devices.push_back(info); +} + +void device_multi_info(vector& devices) +{ + int num = 0; + device_multi_add(devices, DEVICE_CUDA, true, "CUDA_MULTI_%d", num++); + device_multi_add(devices, DEVICE_CUDA, false, "CUDA_MULTI_%d", num++); + + num = 0; + device_multi_add(devices, DEVICE_OPENCL, true, "OPENCL_MULTI_%d", num++); + device_multi_add(devices, DEVICE_OPENCL, false, "OPENCL_MULTI_%d", num++); } CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index a5ad84831fc..4347d7eecd8 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -220,11 +220,22 @@ public: } }; -Device *device_network_create(const char *address) +Device *device_network_create(DeviceInfo& info, const char *address) { return new NetworkDevice(address); } +void device_network_info(vector& devices) +{ + DeviceInfo info; + + info.type = DEVICE_NETWORK; + info.description = "Network Device"; + info.id = "NETWORK"; + info.num = 0; + + devices.push_back(info); +} void Device::server_run() { diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 6014dd0fdb7..41844d37f50 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -141,7 +141,7 @@ public: } } - OpenCLDevice(bool background_) + OpenCLDevice(DeviceInfo& info, bool background_) { background = background_; cpPlatform = NULL; @@ -153,10 +153,9 @@ public: null_mem = 0; device_initialized = false; - vector platform_ids; + /* setup platform */ cl_uint num_platforms; - /* setup device */ ciErr = clGetPlatformIDs(0, NULL, &num_platforms); if(opencl_error(ciErr)) return; @@ -166,14 +165,7 @@ public: return; } - platform_ids.resize(num_platforms); - ciErr = clGetPlatformIDs(num_platforms, &platform_ids[0], NULL); - if(opencl_error(ciErr)) - return; - - cpPlatform = platform_ids[0]; /* todo: pick specified platform && device */ - - ciErr = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 1, &cdDevice, NULL); + ciErr = clGetPlatformIDs(num_platforms, &cpPlatform, NULL); if(opencl_error(ciErr)) return; @@ -181,6 +173,29 @@ public: clGetPlatformInfo(cpPlatform, CL_PLATFORM_NAME, sizeof(name), &name, NULL); platform_name = name; + /* get devices */ + vector device_ids; + cl_uint num_devices; + + if(opencl_error(clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &num_devices))) + return; + + if(info.num > num_devices) { + if(num_devices == 0) + opencl_error("OpenCL: no devices found."); + else + opencl_error("OpenCL: specified device not found."); + return; + } + + device_ids.resize(num_devices); + + if(opencl_error(clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, num_devices, &device_ids[0], NULL))) + return; + + cdDevice = device_ids[info.num]; + + /* create context */ cxContext = clCreateContext(0, 1, &cdDevice, NULL, NULL, &ciErr); if(opencl_error(ciErr)) return; @@ -689,9 +704,50 @@ public: } }; -Device *device_opencl_create(bool background) +Device *device_opencl_create(DeviceInfo& info, bool background) { - return new OpenCLDevice(background); + return new OpenCLDevice(info, background); +} + +void device_opencl_info(vector& devices) +{ + vector device_ids; + cl_uint num_devices; + cl_platform_id platform_id; + cl_uint num_platforms; + + /* get devices */ + if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS || num_platforms == 0) + return; + + if(clGetPlatformIDs(num_platforms, &platform_id, NULL) != CL_SUCCESS) + return; + + if(clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &num_devices) != CL_SUCCESS) + return; + + device_ids.resize(num_devices); + + if(clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, num_devices, &device_ids[0], NULL) != CL_SUCCESS) + return; + + /* add devices */ + for(int num = 0; num < num_devices; num++) { + cl_device_id device_id = device_ids[num]; + char name[1024]; + + if(clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(name), &name, NULL) != CL_SUCCESS) + continue; + + DeviceInfo info; + + info.type = DEVICE_OPENCL; + info.description = string(name); + info.id = string_printf("OPENCL_%d", num); + info.num = num; + + devices.push_back(info); + } } CCL_NAMESPACE_END diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 29141b25b59..dd78ccd8f32 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -183,7 +183,7 @@ void DisplayBuffer::draw(Device *device) if(transparent) draw_transparency_grid(); - device->draw_pixels(rgba, 0, draw_width, draw_height, params.width, params.height, transparent); + device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent); } } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index be2e493dc7f..4634e4de0d8 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -35,9 +35,9 @@ Session::Session(const SessionParams& params_) : params(params_), tile_manager(params.progressive, params.samples, params.tile_size, params.min_size) { - device_use_gl = ((params.device_type != DEVICE_CPU) && !params.background); + device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); - device = Device::create(params.device_type, params.background, params.threads); + device = Device::create(params.device, params.background, params.threads); buffers = new RenderBuffers(device); display = new DisplayBuffer(device); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 89979b8c451..a662948c15b 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -40,7 +40,7 @@ class Scene; class SessionParams { public: - DeviceType device_type; + DeviceInfo device; bool background; string output_path; @@ -57,7 +57,6 @@ public: SessionParams() { - device_type = DEVICE_CPU; background = false; output_path = ""; @@ -74,7 +73,8 @@ public: } bool modified(const SessionParams& params) - { return !(device_type == params.device_type + { return !(device.type == params.device.type + && device.id == params.device.id && background == params.background && output_path == params.output_path /* && samples == params.samples */ diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 40833e5b08b..04e48d44029 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -71,8 +71,8 @@ void TileManager::set_tiles() int resolution = state.resolution; int image_w = max(1, params.width/resolution); int image_h = max(1, params.height/resolution); - int tile_w = (image_w + tile_size - 1)/tile_size; - int tile_h = (image_h + tile_size - 1)/tile_size; + int tile_w = (tile_size >= image_w)? 1: (image_w + tile_size - 1)/tile_size; + int tile_h = (tile_size >= image_h)? 1: (image_h + tile_size - 1)/tile_size; int sub_w = image_w/tile_w; int sub_h = image_h/tile_h;