Cycles: improve error reporting for opencl and cuda, showing error messages in
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 22 Nov 2011 20:49:33 +0000 (20:49 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 22 Nov 2011 20:49:33 +0000 (20:49 +0000)
viewport instead of only console.

intern/cycles/device/device.h
intern/cycles/device/device_cuda.cpp
intern/cycles/device/device_opencl.cpp
intern/cycles/render/session.cpp

index 5d6ac10dc407e48e9c7957dcfea0d075a331d5c3..5552e6ab7e22210bd6f7b3e553202afc739c47fd 100644 (file)
@@ -76,6 +76,7 @@ protected:
        Device() {}
 
        bool background;
+       string error_msg;
 
 public:
        virtual ~Device() {}
@@ -84,6 +85,7 @@ public:
 
        /* info */
        virtual string description() = 0;
+       const string& error_message() { return error_msg; }
 
        /* regular memory */
        virtual void mem_alloc(device_memory& mem, MemoryType type) = 0;
index 1158cc6c77cd864194dae9bd58afbf96266226b8..e32cbfcc8a7b7272b5eb1107f84f3feb27624527 100644 (file)
@@ -122,7 +122,10 @@ public:
                CUresult result = stmt; \
                \
                if(result != CUDA_SUCCESS) { \
-                       fprintf(stderr, "CUDA error: %s in %s\n", cuda_error_string(result), #stmt); \
+                       string message = string_printf("CUDA error: %s in %s", cuda_error_string(result), #stmt); \
+                       if(error_msg == "") \
+                               error_msg = message; \
+                       fprintf(stderr, "%s\n", message.c_str()); \
                        cuda_abort(); \
                } \
        }
@@ -132,10 +135,20 @@ public:
                if(result == CUDA_SUCCESS)
                        return false;
 
-               fprintf(stderr, "CUDA error: %s\n", cuda_error_string(result));
+               string message = string_printf("CUDA error: %s", cuda_error_string(result));
+               if(error_msg == "")
+                       error_msg = message;
+               fprintf(stderr, "%s\n", message.c_str());
                return true;
        }
 
+       void cuda_error(const string& message)
+       {
+               if(error_msg == "")
+                       error_msg = message;
+               fprintf(stderr, "%s\n", message.c_str());
+       }
+
        void cuda_push_context()
        {
                cuda_assert(cuCtxSetCurrent(cuContext))
@@ -224,14 +237,14 @@ public:
                        return cubin;
 
 #ifdef WITH_CUDA_BINARIES
-               fprintf(stderr, "CUDA binary kernel for this graphics card not found.\n");
+               cuda_error("CUDA binary kernel for this graphics card not found.");
                return "";
 #else
                /* if not, find CUDA compiler */
                string nvcc = cuCompilerPath();
 
                if(nvcc == "") {
-                       fprintf(stderr, "CUDA nvcc compiler not found. Install CUDA toolkit in default location.\n");
+                       cuda_error("CUDA nvcc compiler not found. Install CUDA toolkit in default location.");
                        return "";
                }
 
@@ -251,13 +264,13 @@ public:
                        nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), maxreg, include.c_str());
 
                if(system(command.c_str()) == -1) {
-                       fprintf(stderr, "Failed to execute compilation command.\n");
+                       cuda_error("Failed to execute compilation command, see console for details.");
                        return "";
                }
 
                /* verify if compilation succeeded */
                if(!path_exists(cubin)) {
-                       fprintf(stderr, "CUDA kernel compilation failed.\n");
+                       cuda_error("CUDA kernel compilation failed, see console for details.");
                        return "";
                }
 
@@ -284,7 +297,7 @@ public:
 
                CUresult result = cuModuleLoad(&cuModule, cubin.c_str());
                if(cuda_error(result))
-                       fprintf(stderr, "Failed loading CUDA kernel %s.\n", cubin.c_str());
+                       cuda_error(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
 
                cuda_pop_context();
 
index e0b4f67da057dc2d4ff09341cc6f89026a1d4261..d783ae6c174f522dbc6d47a9a418c27bc0a8e027 100644 (file)
@@ -109,17 +109,30 @@ public:
        bool opencl_error(cl_int err)
        {
                if(err != CL_SUCCESS) {
-                       fprintf(stderr, "OpenCL error (%d): %s\n", err, opencl_error_string(err));
+                       string message = string_printf("OpenCL error (%d): %s", err, opencl_error_string(err));
+                       if(error_msg == "")
+                               error_msg = message;
+                       fprintf(stderr, "%s\n", message.c_str());
                        return true;
                }
 
                return false;
        }
 
+       void opencl_error(const string& message)
+       {
+               if(error_msg == "")
+                       error_msg = message;
+               fprintf(stderr, "%s\n", message.c_str());
+       }
+
        void opencl_assert(cl_int err)
        {
                if(err != CL_SUCCESS) {
-                       fprintf(stderr, "OpenCL error (%d): %s\n", err, opencl_error_string(err));
+                       string message = string_printf("OpenCL error (%d): %s", err, opencl_error_string(err));
+                       if(error_msg == "")
+                               error_msg = message;
+                       fprintf(stderr, "%s\n", message.c_str());
 #ifndef NDEBUG
                        abort();
 #endif
@@ -147,7 +160,7 @@ public:
                        return;
 
                if(num_platforms == 0) {
-                       fprintf(stderr, "OpenCL: no platforms found.\n");
+                       opencl_error("OpenCL: no platforms found.");
                        return;
                }
 
@@ -183,24 +196,24 @@ public:
                clGetPlatformInfo(cpPlatform, CL_PLATFORM_VERSION, sizeof(version), &version, NULL);
 
                if(sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
-                       fprintf(stderr, "OpenCL: failed to parse platform version string (%s).", version);
+                       opencl_error(string_printf("OpenCL: failed to parse platform version string (%s).", version));
                        return false;
                }
 
                if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
-                       fprintf(stderr, "OpenCL: platform version 1.1 or later required, found %d.%d\n", major, minor);
+                       opencl_error(string_printf("OpenCL: platform version 1.1 or later required, found %d.%d", major, minor));
                        return false;
                }
 
                clGetDeviceInfo(cdDevice, CL_DEVICE_OPENCL_C_VERSION, sizeof(version), &version, NULL);
 
                if(sscanf(version, "OpenCL C %d.%d", &major, &minor) < 2) {
-                       fprintf(stderr, "OpenCL: failed to parse OpenCL C version string (%s).", version);
+                       opencl_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))) {
-                       fprintf(stderr, "OpenCL: C version 1.1 or later required, found %d.%d\n", major, minor);
+                       opencl_error(string_printf("OpenCL: C version 1.1 or later required, found %d.%d", major, minor));
                        return false;
                }
 
@@ -216,7 +229,7 @@ public:
                vector<uint8_t> binary;
 
                if(!path_read_binary(clbin, binary)) {
-                       fprintf(stderr, "OpenCL failed to read cached binary %s.\n", clbin.c_str());
+                       opencl_error(string_printf("OpenCL failed to read cached binary %s.", clbin.c_str()));
                        return false;
                }
 
@@ -229,7 +242,7 @@ public:
                        &size, &bytes, &status, &ciErr);
 
                if(opencl_error(status) || opencl_error(ciErr)) {
-                       fprintf(stderr, "OpenCL failed create program from cached binary %s.\n", clbin.c_str());
+                       opencl_error(string_printf("OpenCL failed create program from cached binary %s.", clbin.c_str()));
                        return false;
                }
 
@@ -253,7 +266,7 @@ public:
                clGetProgramInfo(cpProgram, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL);
 
                if(!path_write_binary(clbin, binary)) {
-                       fprintf(stderr, "OpenCL failed to write cached binary %s.\n", clbin.c_str());
+                       opencl_error(string_printf("OpenCL failed to write cached binary %s.", clbin.c_str()));
                        return false;
                }
 
@@ -293,7 +306,8 @@ public:
                        clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
 
                        build_log[ret_val_size] = '\0';
-                       fprintf(stderr, "OpenCL build failed:\n %s\n", build_log);
+                       opencl_error("OpenCL build failed: errors in console");
+                       fprintf(stderr, "%s\n", build_log);
 
                        delete[] build_log;
 
index 2deb83674cca58ff4be9cf07ceae9555e7ca5b53..73ac033623dd4ba502b16f658da16d751327b3f7 100644 (file)
@@ -203,6 +203,10 @@ void Session::run_gpu()
                if(!no_tiles) {
                        /* update scene */
                        update_scene();
+
+                       if(device->error_message() != "")
+                               progress.set_cancel(device->error_message());
+
                        if(progress.get_cancel())
                                break;
                }
@@ -222,6 +226,9 @@ void Session::run_gpu()
 
                                device->task_wait();
 
+                               if(device->error_message() != "")
+                                       progress.set_cancel(device->error_message());
+
                                if(progress.get_cancel())
                                        break;
                        }
@@ -243,6 +250,9 @@ void Session::run_gpu()
                                }
                        }
 
+                       if(device->error_message() != "")
+                               progress.set_cancel(device->error_message());
+
                        if(progress.get_cancel())
                                break;
                }
@@ -345,6 +355,10 @@ void Session::run_cpu()
 
                        /* update scene */
                        update_scene();
+
+                       if(device->error_message() != "")
+                               progress.set_cancel(device->error_message());
+
                        if(progress.get_cancel())
                                break;
 
@@ -360,6 +374,9 @@ void Session::run_cpu()
 
                        if(!params.background)
                                need_tonemap = true;
+
+                       if(device->error_message() != "")
+                               progress.set_cancel(device->error_message());
                }
 
                device->task_wait();
@@ -379,6 +396,9 @@ void Session::run_cpu()
                                   want to show the result of an incomplete sample*/
                                tonemap();
                        }
+
+                       if(device->error_message() != "")
+                               progress.set_cancel(device->error_message());
                }
 
                progress.set_update();
@@ -391,7 +411,11 @@ void Session::run()
        progress.set_status("Loading render kernels (may take a few minutes the first time)");
 
        if(!device->load_kernels()) {
-               progress.set_status("Failed loading render kernel, see console for errors");
+               string message = device->error_message();
+               if(message == "")
+                       message = "Failed loading render kernel, see console for errors";
+
+               progress.set_status("Error", message);
                progress.set_update();
                return;
        }
@@ -409,7 +433,7 @@ void Session::run()
 
        /* progress update */
        if(progress.get_cancel())
-               progress.set_status(progress.get_cancel_message());
+               progress.set_status("Cancel", progress.get_cancel_message());
        else
                progress.set_update();
 }