Program Listing for File program.cpp¶
↰ Return to documentation for file (/home/runner/work/Legion-Engine/Legion-Engine/legion/engine/core/compute/program.cpp
)
#include <core/compute/program.hpp>
#include <core/logging/logging.hpp>
#include <core/filesystem/resource.hpp>
#include <core/compute/context.hpp>
namespace legion::core::compute {
Program::Program(cl_context ctx, cl_device_id device, filesystem::basic_resource container /* , bool source_is_il */) {
OPTICK_EVENT();
//bind command queue creation to surrogate
this->make_command_queue = std::function([ctx, device]() -> cl_command_queue
{
cl_int ret;
//creates a command queue and checks it for errors
auto* const command_queue = clCreateCommandQueueWithProperties(ctx, device, nullptr, &ret);
if (ret != CL_SUCCESS) {
log::error("clCreateCommandQueueWithProperties failed!");
return nullptr;
}
return command_queue;
});
cl_int ret;
//convert to c-style array
const char* data = reinterpret_cast<const char*>(container.data());
size_t size = container.size();
/*
if (source_is_il)
{
//create program from il
m_program = clCreateProgramWithIL(ctx, data, size, &ret);
}
else { */
//create program from source
m_program = clCreateProgramWithSource(ctx, 1, &data, &size, &ret);
/* } */
if (ret != CL_SUCCESS)
{
log::error("clCreateProgramWithSource/IL failed!");
return;
}
// clBuildProgram parameters guide:
//
// -cl-std=2.0: We want OpenCL Standard 2.0 the driver reports 1.2 but it actually is 2.0 on most devices
// -cl-kernel-arg-info: We want kernel informations built into the binary so that we can query the kernel args by name instead of index
// -DLEGION_LIBRARY this is indicates to your kernel that it was built for use with the ARGS-Engine, it defines the macor LEGION_LIBRARY
// -DDEBUG if the Engine is built in debug mode, the kernel will also receive the DEBUG define
// -DNDEBUG if the Engine is built in release mode, the kernel will receive the NDEBUG define
/*if (!source_is_il) {*/
//check if we are running in debug and adjust build command accordingly
if constexpr (LEGION_CONFIGURATION == LEGION_DEBUG_VALUE) {
//DEBUG
ret = clBuildProgram(m_program, 1, &device, "-cl-std=CL2.0 -cl-kernel-arg-info -DLEGION_LIBRARY -DDEBUG ", nullptr, nullptr);
} else {
//NDEBUG
ret = clBuildProgram(m_program, 1, &device, "-cl-std=CL2.0 -cl-kernel-arg-info -DLEGION_LIBRARY -DNDEBUG", nullptr, nullptr);
}
//check if building was successful
if (ret != CL_SUCCESS)
{
log::error("clBuildProgram failed");
size_t length;
char buffer[8192*4];
clGetProgramBuildInfo(m_program,device,CL_PROGRAM_BUILD_LOG,sizeof(buffer),buffer,&length);
buffer[length] = NULL;
log::warn("BUILD LOG:\n{}",buffer);
}
/*}*/
}
Kernel Program::kernelContext(const std::string& name)
{
OPTICK_EVENT();
// check if we already have the kernel and create a context from it if we do, otherwise initialize it
if (const auto it = m_kernelCache.find(name); it != m_kernelCache.end())
{
return Kernel(this, it->second);
}
else
{
return Kernel(this, prewarm(name));
}
}
cl_kernel Program::prewarm(const std::string& name)
{
OPTICK_EVENT();
// create the kernel and push it into the cache
// do some error checking along the way
cl_int ret;
cl_kernel kernel = clCreateKernel(m_program, name.c_str(), &ret);
if (ret != CL_SUCCESS)
{
log::error("clCreateKernel failed");
}
m_kernelCache[name] = kernel;
return kernel;
}
void Program::from_resource(Program* value, const filesystem::basic_resource& resource)
{
OPTICK_EVENT();
*value = Context::createProgram(resource);
}
}