Cycles: compile opencl kernels in non-blocking thread, and don't crash on
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 2 Sep 2011 00:10:03 +0000 (00:10 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 2 Sep 2011 00:10:03 +0000 (00:10 +0000)
build failure but show error message in status text.

intern/cycles/device/device.h
intern/cycles/device/device_cuda.cpp
intern/cycles/device/device_opencl.cpp
intern/cycles/render/session.cpp
intern/cycles/util/util_math.h
intern/cycles/util/util_string.cpp
intern/cycles/util/util_string.h

index 87683ae47196c48a28c725dd668f2586a136e846..aa9cb9eb8f40361ca7e9b892827f1f1b48f098a0 100644 (file)
@@ -108,6 +108,9 @@ public:
        /* open shading language, only for CPU device */
        virtual void *osl_memory() { return NULL; }
 
+       /* load/compile kernels, must be called before adding tasks */ 
+       virtual bool load_kernels() { return true; }
+
        /* tasks */
        virtual void task_add(DeviceTask& task) = 0;
        virtual void task_wait() = 0;
index cc1c1275bf4e35b2459111a79fca6f0c49a03dcc..a6a66873b92cf4b4c93bdb5f30b1a727c5047d99 100644 (file)
@@ -137,7 +137,6 @@ public:
 
        CUDADevice(bool background_)
        {
-               int major, minor;
                background = background_;
 
                cuDevId = 0;
@@ -153,11 +152,6 @@ public:
                else
                        cuda_assert(cuGLCtxCreate(&cuContext, 0, cuDevice))
 
-               /* open module */
-               cuDeviceComputeCapability(&major, &minor, cuDevId);
-               string cubin = string_printf("lib/kernel_sm_%d%d.cubin", major, minor);
-               cuda_assert(cuModuleLoad(&cuModule, path_get(cubin).c_str()))
-
                cuda_pop_context();
        }
 
@@ -179,6 +173,27 @@ public:
                return string("CUDA ") + deviceName;
        }
 
+
+       bool load_kernels()
+       {
+               CUresult result;
+               int major, minor;
+
+               cuda_push_context();
+
+               /* open module */
+               cuDeviceComputeCapability(&major, &minor, cuDevId);
+               string cubin = path_get(string_printf("lib/kernel_sm_%d%d.cubin", major, minor));
+
+               result = cuModuleLoad(&cuModule, cubin.c_str());
+               if(result != CUDA_SUCCESS)
+                       fprintf(stderr, "Failed loading CUDA kernel %s (%s).\n", cubin.c_str(), cuda_error_string(result));
+
+               cuda_pop_context();
+
+               return (result == CUDA_SUCCESS);
+       }
+
        void mem_alloc(device_memory& mem, MemoryType type)
        {
                cuda_push_context();
@@ -231,7 +246,7 @@ public:
 
                cuda_push_context();
                cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, name))
-               assert(bytes == size);
+               //assert(bytes == size);
                cuda_assert(cuMemcpyHtoD(mem, host, size))
                cuda_pop_context();
        }
index 4020cc87392a91ddeb5e6ad3a6ac3100006840e1..afde8ac4c82609b52eccb692bab716460f8d5ef0 100644 (file)
@@ -136,7 +136,16 @@ public:
 
                cqCommandQueue = clCreateCommandQueue(cxContext, cdDevice, 0, &ciErr);
                opencl_assert(ciErr);
-               
+
+               null_mem = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_ONLY, 1, NULL, &ciErr);
+
+               cpProgram = NULL;
+               ckPathTraceKernel = NULL;
+               ckFilmConvertKernel = NULL;
+       }
+
+       bool load_kernels()
+       {
                /* compile kernel */
                string source = string_printf("#include \"kernel.cl\" // %lf\n", time_dt());
                size_t source_len = source.size();
@@ -152,6 +161,7 @@ public:
                opencl_assert(ciErr);
 
                ciErr = clBuildProgram(cpProgram, 0, NULL, build_options.c_str(), NULL, NULL);
+
                if(ciErr != CL_SUCCESS) {
                        char *build_log;
                        size_t ret_val_size;
@@ -162,13 +172,11 @@ public:
                        clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
 
                        build_log[ret_val_size] = '\0';
-                       printf("OpenCL build failed:\n %s\n", build_log);
+                       fprintf(stderr, "OpenCL build failed:\n %s\n", build_log);
 
                        delete[] build_log;
 
-                       opencl_assert(ciErr);
-
-                       return;
+                       return false;
                }
 
                ckPathTraceKernel = clCreateKernel(cpProgram, "kernel_ocl_path_trace", &ciErr);
@@ -176,13 +184,13 @@ public:
                ckFilmConvertKernel = clCreateKernel(cpProgram, "kernel_ocl_tonemap", &ciErr);
                opencl_assert(ciErr);
 
-               null_mem = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_ONLY, 1, NULL, &ciErr);
+               return true;
        }
 
        ~OpenCLDevice()
        {
-
-               clReleaseMemObject(CL_MEM_PTR(null_mem));
+               if(null_mem)
+                       clReleaseMemObject(CL_MEM_PTR(null_mem));
 
                map<string, device_vector<uchar>*>::iterator mt;
                for(mt = const_mem_map.begin(); mt != const_mem_map.end(); mt++) {
@@ -190,11 +198,16 @@ public:
                        delete mt->second;
                }
 
-               clReleaseKernel(ckPathTraceKernel);  
-               clReleaseKernel(ckFilmConvertKernel);  
-               clReleaseProgram(cpProgram);
-               clReleaseCommandQueue(cqCommandQueue);
-               clReleaseContext(cxContext);
+               if(ckPathTraceKernel)
+                       clReleaseKernel(ckPathTraceKernel);  
+               if(ckFilmConvertKernel)
+                       clReleaseKernel(ckFilmConvertKernel);  
+               if(cpProgram)
+                       clReleaseProgram(cpProgram);
+               if(cqCommandQueue)
+                       clReleaseCommandQueue(cqCommandQueue);
+               if(cxContext)
+                       clReleaseContext(cxContext);
        }
 
        string description()
index 52366f06337b32bc3f3a02042cec4db2d7c30205..daa10ad4f19318733186b4d6eefa89ab78fef233 100644 (file)
@@ -380,6 +380,15 @@ void Session::run_cpu()
 
 void Session::run()
 {
+       /* load kernels */
+       progress.set_status("Loading render kernels");
+
+       if(!device->load_kernels()) {
+               progress.set_status("Failed loading render kernel, see console for errors");
+               progress.set_update();
+               return;
+       }
+
        /* session thread loop */
        progress.set_status("Waiting for render to start");
 
index c435a9e17b8b463a4dd7d235b83bf50a49dc73c4..8e52b98d52bdc71cb24408e0e9ace162818a69cf 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-#ifndef __KERNEL_OPENCL__
-
+#ifndef M_PI_F
 #define M_PI_F         ((float)3.14159265358979323846264338327950288)
+#endif
+#ifndef M_PI_2_F
 #define M_PI_2_F       ((float)1.57079632679489661923132169163975144)
+#endif
+#ifndef M_PI_4_F
 #define M_PI_4_F       ((float)0.785398163397448309615660845819875721)
+#endif
+#ifndef M_1_PI_F
 #define M_1_PI_F       ((float)0.318309886183790671537767526745028724)
+#endif
+#ifndef M_2_PI_F
 #define M_2_PI_F       ((float)0.636619772367581343075535053490057448)
-
 #endif
 
 /* Scalar */
index aaa482eec0df9ee3398cb2d3148a5af66b342295..0dac9a8142ae58ce4a5d36fd16f9b3af8140484d 100644 (file)
@@ -77,11 +77,11 @@ bool string_iequals(const string& a, const string& b)
        return false;
 }
 
-void string_split(vector<string>& tokens, const string& str)
+void string_split(vector<string>& tokens, const string& str, const string& separators)
 {
        vector<string> split;
 
-       boost::split(split, str, boost::is_any_of("\t "), boost::token_compress_on);
+       boost::split(split, str, boost::is_any_of(separators), boost::token_compress_on);
 
        foreach(const string& token, split)
                if(token != "")
index 72b893d2b17adf7edd970079cf7a0097e86aab5a..342edd53658b073bd74995e3f969bb21279bb741 100644 (file)
@@ -41,7 +41,7 @@ using std::istringstream;
 string string_printf(const char *format, ...) PRINTF_ATTRIBUTE;
 
 bool string_iequals(const string& a, const string& b);
-void string_split(vector<string>& tokens, const string& str);
+void string_split(vector<string>& tokens, const string& str, const string& separators = "\t ");
 
 CCL_NAMESPACE_END