Split offline compilation into multiple functions

This commit is contained in:
Stuart Brady
2019-07-18 18:52:45 +01:00
committed by Kévin Petit
parent fe3049a491
commit 9cfca7e69e

View File

@@ -74,6 +74,18 @@ std::vector<char> get_file_content(const std::string &fileName)
return content;
}
static std::string get_kernel_content(unsigned int numKernelLines, const char *const *kernelProgram)
{
std::string kernel;
for (size_t i = 0; i < numKernelLines; ++i)
{
std::string chunk(kernelProgram[i], 0, std::string::npos);
kernel += chunk;
}
return kernel;
}
std::string get_kernel_name(const std::string &source)
{
// Count CRC
@@ -215,6 +227,78 @@ static std::string get_offline_compilation_file_type_str(const CompilationMode c
}
}
static std::string get_offline_compilation_command(const cl_uint device_address_space_size,
const bool openclCXX,
const std::string &bOptions,
const std::string &sourceFilename,
const std::string &outputFilename)
{
// Set compiler options
// Emit SPIR-V
std::string compilerOptions = " -cc1 -emit-spirv";
// <triple>: for 32 bit SPIR-V use spir-unknown-unknown, for 64 bit SPIR-V use spir64-unknown-unknown.
if(device_address_space_size == 32)
{
compilerOptions += " -triple=spir-unknown-unknown";
}
else
{
compilerOptions += " -triple=spir64-unknown-unknown";
}
// Set OpenCL C++ flag required by SPIR-V-ready clang (compiler provided by Khronos)
if(openclCXX)
{
compilerOptions = compilerOptions + " -cl-std=c++";
}
// Set correct includes
if(openclCXX)
{
compilerOptions += " -I ";
compilerOptions += STRINGIFY_VALUE(CL_LIBCLCXX_DIR);
}
else
{
compilerOptions += " -include opencl.h";
}
#ifdef CL_OFFLINE_COMPILER_OPTIONS
compilerOptions += STRINGIFY_VALUE(CL_OFFLINE_COMPILER_OPTIONS);
#endif
// Add build options passed to this function
compilerOptions += " " + bOptions;
compilerOptions +=
" " + sourceFilename +
" -o " + outputFilename;
std::string runString = STRINGIFY_VALUE(CL_OFFLINE_COMPILER) + compilerOptions;
return runString;
}
static int invoke_offline_compiler(cl_context context,
const cl_uint device_address_space_size,
const bool openclCXX,
const std::string &bOptions,
const std::string &sourceFilename,
const std::string &outputFilename)
{
std::string runString =
get_offline_compilation_command(device_address_space_size, openclCXX, bOptions,
sourceFilename, outputFilename);
// execute script
log_info("Executing command: %s\n", runString.c_str());
fflush(stdout);
int returnCode = system(runString.c_str());
if (returnCode != 0)
{
log_error("ERROR: Command finished with error: 0x%x\n", returnCode);
return CL_COMPILE_PROGRAM_FAILURE;
}
return CL_SUCCESS;
}
static cl_int get_first_device_id(const cl_context context, cl_device_id &device)
{
cl_uint numDevices = 0;
@@ -256,56 +340,32 @@ static cl_int get_first_device_address_bits(const cl_context context, cl_uint &d
return CL_SUCCESS;
}
static int create_single_kernel_helper_create_program(cl_context context,
cl_program *outProgram,
unsigned int numKernelLines,
const char **kernelProgram,
const char *buildOptions,
static int get_offline_compiler_output(std::ifstream &ifs,
cl_context context,
const std::string &kernel,
const bool openclCXX,
CompilationMode compilationMode)
const CompilationMode compilationMode,
const std::string &bOptions,
const std::string &kernelName)
{
int error = CL_SUCCESS;
if (compilationMode != kOnline)
{
#ifndef CL_OFFLINE_COMPILER
log_error("Offline compilation is not possible: CL_OFFLINE_COMPILER was not defined.\n");
return -1;
#endif // !CL_OFFLINE_COMPILER
std::string kernel;
for (size_t i = 0; i < numKernelLines; ++i)
{
std::string chunk(kernelProgram[i], 0, std::string::npos);
kernel += chunk;
}
std::string kernelName = get_kernel_name(kernel);
// set build options
std::string bOptions;
bOptions += buildOptions ? std::string(buildOptions) : "";
kernelName = add_build_options(kernelName, buildOptions);
std::string sourceFilename = gCompilationCachePath + slash + kernelName + ".cl";
std::string outputFilename = gCompilationCachePath + slash + kernelName;
// Get device CL_DEVICE_ADDRESS_BITS
cl_uint device_address_space_size = 0;
if (compilationMode == kSpir_v)
{
cl_int error = get_first_device_address_bits(context, device_address_space_size);
int error = get_first_device_address_bits(context, device_address_space_size);
if (error != CL_SUCCESS)
return error;
std::string outputFilename = gCompilationCachePath + slash + kernelName;
if (compilationMode == kSpir_v)
{
std::ostringstream extension;
extension << ".spv" << device_address_space_size;
outputFilename += extension.str();
}
// try to read cached output file when test is run with gCompilationCacheMode != kCacheModeOverwrite
std::ifstream ifs(outputFilename.c_str(), std::ios::binary);
ifs.open(outputFilename.c_str(), std::ios::binary);
if (gCompilationCacheMode == kCacheModeOverwrite || !ifs.good())
{
@@ -335,54 +395,11 @@ static int create_single_kernel_helper_create_program(cl_context context,
ofs.write(kernel.c_str(), kernel.size());
ofs.close();
// Set compiler options
// Emit SPIR-V
std::string compilerOptions = " -cc1 -emit-spirv";
// <triple>: for 32 bit SPIR-V use spir-unknown-unknown, for 64 bit SPIR-V use spir64-unknown-unknown.
if(device_address_space_size == 32)
{
compilerOptions += " -triple=spir-unknown-unknown";
}
else
{
compilerOptions += " -triple=spir64-unknown-unknown";
}
// Set OpenCL C++ flag required by SPIR-V-ready clang (compiler provided by Khronos)
if(openclCXX)
{
compilerOptions = compilerOptions + " -cl-std=c++";
}
// Set correct includes
if(openclCXX)
{
compilerOptions += " -I ";
compilerOptions += STRINGIFY_VALUE(CL_LIBCLCXX_DIR);
}
else
{
compilerOptions += " -include opencl.h";
}
error = invoke_offline_compiler(context, device_address_space_size, openclCXX,
bOptions, sourceFilename, outputFilename);
if (error != CL_SUCCESS)
return error;
#ifdef CL_OFFLINE_COMPILER_OPTIONS
compilerOptions += STRINGIFY_VALUE(CL_OFFLINE_COMPILER_OPTIONS);
#endif
// Add build options passed to this function
compilerOptions += " " + bOptions;
compilerOptions +=
" " + sourceFilename +
" -o " + outputFilename;
std::string runString = STRINGIFY_VALUE(CL_OFFLINE_COMPILER) + compilerOptions;
// execute script
log_info("Executing command: %s\n", runString.c_str());
fflush(stdout);
int returnCode = system(runString.c_str());
if (returnCode != 0)
{
log_error("ERROR: Command finished with error: 0x%x\n", returnCode);
return CL_COMPILE_PROGRAM_FAILURE;
}
// read output file
ifs.open(outputFilename.c_str(), std::ios::binary);
if (!ifs.good())
@@ -393,6 +410,32 @@ static int create_single_kernel_helper_create_program(cl_context context,
}
}
return CL_SUCCESS;
}
static int create_single_kernel_helper_create_program_offline(cl_context context,
cl_program *outProgram,
unsigned int numKernelLines,
const char *const *kernelProgram,
const char *buildOptions,
const bool openclCXX,
CompilationMode compilationMode)
{
int error;
std::string kernel = get_kernel_content(numKernelLines, kernelProgram);
std::string kernelName = get_kernel_name(kernel);
// set build options
std::string bOptions;
bOptions += buildOptions ? std::string(buildOptions) : "";
kernelName = add_build_options(kernelName, buildOptions);
std::ifstream ifs;
error = get_offline_compiler_output(ifs, context, kernel, openclCXX, compilationMode, bOptions, kernelName);
if (error != CL_SUCCESS)
return error;
// -----------------------------------------------------------------------------------
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
// -----------------------------------------------------------------------------------
@@ -450,9 +493,22 @@ static int create_single_kernel_helper_create_program(cl_context context,
return error;
}
}
return CL_SUCCESS;
}
else // compilationMode == kOnline
static int create_single_kernel_helper_create_program(cl_context context,
cl_program *outProgram,
unsigned int numKernelLines,
const char **kernelProgram,
const char *buildOptions,
const bool openclCXX,
CompilationMode compilationMode)
{
if (compilationMode == kOnline)
{
int error = CL_SUCCESS;
/* Create the program object from source */
*outProgram = clCreateProgramWithSource(context, numKernelLines, kernelProgram, NULL, &error);
if (*outProgram == NULL || error != CL_SUCCESS)
@@ -460,8 +516,18 @@ static int create_single_kernel_helper_create_program(cl_context context,
print_error(error, "clCreateProgramWithSource failed");
return error;
}
return CL_SUCCESS;
}
else
{
#ifdef CL_OFFLINE_COMPILER
return create_single_kernel_helper_create_program_offline(context, outProgram, numKernelLines,
kernelProgram, buildOptions,
openclCXX, compilationMode);
#endif
log_error("Offline compilation is not possible: CL_OFFLINE_COMPILER was not defined.\n");
return -1;
}
return 0;
}
int create_single_kernel_helper_create_program(cl_context context,