#include #include #include #include #include #include #include namespace smo { namespace compute { void ComputeManager::initialize() { if (initialized) { return; } cl_int err; // Get number of platforms cl_uint numPlatforms = 0; err = clGetPlatformIDs(0, nullptr, &numPlatforms); if (err != CL_SUCCESS) { throw std::runtime_error( std::string(__func__) + ": failed to get OpenCL platforms: " + std::to_string(err)); } if (numPlatforms == 0) { throw std::runtime_error( std::string(__func__) + ": no OpenCL platforms found"); } // Get all platforms std::vector platforms(numPlatforms); err = clGetPlatformIDs(numPlatforms, platforms.data(), nullptr); if (err != CL_SUCCESS) { throw std::runtime_error( std::string(__func__) + ": failed to enumerate OpenCL platforms: " + std::to_string(err)); } // Enumerate devices for each platform for (cl_uint p = 0; p < numPlatforms; ++p) { cl_platform_id platform = platforms[p]; // Check platform version char platformVersion[128]; err = clGetPlatformInfo( platform, CL_PLATFORM_VERSION, sizeof(platformVersion), platformVersion, nullptr); if (err == CL_SUCCESS) { if (!validateOpenClVersion(platformVersion, "platform", 1, 2)) { std::cout << __func__ << ": skipping platform " << p << " with incompatible OpenCL version " << std::string(platformVersion) << std::endl; continue; } } // Get number of devices cl_uint numDevices = 0; err = clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, 0, nullptr, &numDevices); if (err != CL_SUCCESS || numDevices == 0) { std::cout << __func__ << ": skipping platform " << p << " with no devices" << std::endl; continue; } // Get all devices std::vector platformDevices(numDevices); err = clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, numDevices, platformDevices.data(), nullptr); if (err != CL_SUCCESS) { throw std::runtime_error( std::string(__func__) + ": failed to enumerate devices for " "platform " + std::to_string(p) + ": " + std::to_string(err)); } // Create ComputeDevice for each device for (cl_uint d = 0; d < numDevices; ++d) { cl_device_id device = platformDevices[d]; // Check device version char deviceVersion[128]; err = clGetDeviceInfo( device, CL_DEVICE_VERSION, sizeof(deviceVersion), deviceVersion, nullptr); if (err == CL_SUCCESS) { if (!validateOpenClVersion(deviceVersion, "device", 1, 2)) { std::cout << __func__ << ": skipping device " << d << " with incompatible OpenCL version " << std::string(deviceVersion) << std::endl; continue; } } // Create ComputeDevice (constructor creates context and queue) try { auto deviceObj = std::make_shared( platform, device); devices.push_back(deviceObj); } catch (const std::runtime_error& e) { // Re-throw with more context about which device/platform throw std::runtime_error( std::string(__func__) + ": failed to create ComputeDevice " "for device " + std::to_string(d) + " on platform " + std::to_string(p) + ": " + e.what()); } } } if (devices.empty()) { throw std::runtime_error( std::string(__func__) + ": no compatible OpenCL devices found"); } initialized = true; std::cout << __func__ << ": Initialized with " << devices.size() << " compute device(s)" << std::endl; } void ComputeManager::finalize() { if (!initialized) { return; } // Release all devices (their shared_ptrs will clean up contexts/queues) devices.clear(); initialized = false; std::cout << __func__ << ": Finalized" << std::endl; } std::shared_ptr ComputeManager::createUseHostPtrBuffer( void* hostPtr, size_t size, cl_mem_flags flags) { if (!initialized) { std::cerr << __func__ << ": ComputeManager not initialized" << std::endl; throw std::runtime_error( std::string(__func__) + ": ComputeManager not initialized"); } return std::make_shared(hostPtr, size, flags, devices); } void ComputeManager::releaseUseHostPtrBuffer(std::shared_ptr buffer) { // No-op: ClBuffer's destructor handles cleanup automatically // This function exists for API compatibility (void)buffer; } std::shared_ptr ComputeManager::getDevice() { if (!initialized || devices.empty()) { return nullptr; } // Return first available device // In the future, this will filter based on ComputeDeviceConstraints return devices[0]; } void ComputeManager::releaseDevice(std::shared_ptr device) { // Placeholder for future refcounting implementation // Devices are only removed in finalize() (void)device; } } // namespace compute } // namespace smo