Пример #1
0
string path_source_replace_includes(const string& source_, const string& path)
{
	/* our own little c preprocessor that replaces #includes with the file
	   contents, to work around issue of opencl drivers not supporting
	   include paths with spaces in them */
	string source = source_;
	const string include = "#include \"";
	size_t n, pos = 0;

	while((n = source.find(include, pos)) != string::npos) {
		size_t n_start = n + include.size();
		size_t n_end = source.find("\"", n_start);
		string filename = source.substr(n_start, n_end - n_start);

		string text, filepath = path_join(path, filename);

		if(path_read_text(filepath, text)) {
			text = path_source_replace_includes(text, path_dirname(filepath));
			source.replace(n, n_end + 1 - n, "\n" + text + "\n");
		}
		else
			pos = n_end;
	}

	return source;
}
Пример #2
0
	bool compile_kernel(const string& kernel_path, const string& kernel_md5)
	{
		/* we compile kernels consisting of many files. unfortunately opencl
		   kernel caches do not seem to recognize changes in included files.
		   so we force recompile on changes by adding the md5 hash of all files */
		string source = "#include \"kernel.cl\" // " + kernel_md5 + "\n";
		source = path_source_replace_includes(source, kernel_path);

		size_t source_len = source.size();
		const char *source_str = source.c_str();

		cpProgram = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr);

		if(opencl_error(ciErr))
			return false;

		double starttime = time_dt();
		printf("Compiling OpenCL kernel ...\n");

		if(!build_kernel(kernel_path))
			return false;

		printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime);

		return true;
	}
Пример #3
0
string path_source_replace_includes(const string& source,
                                    const string& path,
                                    const string& source_filename)
{
	/* Our own little c preprocessor that replaces #includes with the file
	 * contents, to work around issue of opencl drivers not supporting
	 * include paths with spaces in them.
	 */

	string result = "";
	vector<string> lines;
	string_split(lines, source, "\n", false);

	for(size_t i = 0; i < lines.size(); ++i) {
		string line = lines[i];
		if(line[0] == '#') {
			string token = string_strip(line.substr(1, line.size() - 1));
			if(string_startswith(token, "include")) {
				token = string_strip(token.substr(7, token.size() - 7));
				if(token[0] == '"') {
					size_t n_start = 1;
					size_t n_end = token.find("\"", n_start);
					string filename = token.substr(n_start, n_end - n_start);
					string text, filepath = path_join(path, filename);
					if(path_read_text(filepath, text)) {
						/* Replace include directories with both current path
						 * and path extracted from the include file.
						 * Not totally robust, but works fine for Cycles kernel
						 * and avoids having list of include directories.x
						 */
						text = path_source_replace_includes(
						        text, path_dirname(filepath), filename);
						text = path_source_replace_includes(text, path, filename);
						/* Use line directives for better error messages. */
						line = line_directive(filepath, 1)
						     + token.replace(0, n_end + 1, "\n" + text + "\n")
						     + line_directive(path_join(path, source_filename), i);
					}
				}
			}
		}
		result += line + "\n";
	}

	return result;
}