Files
UnrealEngine/Engine/Source/ThirdParty/Intel/ISPC/ispc-1.17.0/ispcrt/ispcrt.cpp
2025-05-18 13:04:45 +08:00

348 lines
13 KiB
C++

// Copyright 2020-2021 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
#include "ispcrt.h"
// std
#include <exception>
#include <iostream>
// ispcrt
#include "detail/Exception.h"
#include "detail/Module.h"
#include "detail/TaskQueue.h"
#ifdef ISPCRT_BUILD_CPU
#include "detail/cpu/CPUDevice.h"
#endif
#ifdef ISPCRT_BUILD_GPU
#include "detail/gpu/GPUDevice.h"
#endif
static void defaultErrorFcn(ISPCRTError e, const char *msg) {
std::cerr << "ISPCRT Error (" << e << "): " << msg << std::endl;
exit(-1);
}
static ISPCRTErrorFunc g_errorFcn = &defaultErrorFcn;
// Helper functions ///////////////////////////////////////////////////////////
static void handleError(ISPCRTError e, const char *msg) {
if (g_errorFcn)
g_errorFcn(e, msg);
}
template <typename OBJECT_T = ispcrt::RefCounted, typename HANDLE_T = ISPCRTGenericHandle>
static OBJECT_T &referenceFromHandle(HANDLE_T handle) {
return *((OBJECT_T *)handle);
}
#define ISPCRT_CATCH_BEGIN try {
#define ISPCRT_CATCH_END(a) \
} \
catch (const ispcrt::base::ispcrt_runtime_error &e) { \
handleError(e.e, e.what()); \
return a; \
} \
catch (const std::logic_error &e) { \
handleError(ISPCRT_INVALID_OPERATION, e.what()); \
return a; \
} \
catch (const std::exception &e) { \
handleError(ISPCRT_UNKNOWN_ERROR, e.what()); \
return a; \
} \
catch (...) { \
handleError(ISPCRT_UNKNOWN_ERROR, "an unrecognized exception was caught"); \
return a; \
}
///////////////////////////////////////////////////////////////////////////////
////////////////////////// API DEFINITIONS ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
extern "C" {
void ispcrtSetErrorFunc(ISPCRTErrorFunc fcn) { g_errorFcn = fcn; }
///////////////////////////////////////////////////////////////////////////////
// Object lifetime ////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ispcrtRelease(ISPCRTGenericHandle h) ISPCRT_CATCH_BEGIN {
auto &obj = referenceFromHandle(h);
obj.refDec();
}
ISPCRT_CATCH_END()
void ispcrtRetain(ISPCRTGenericHandle h) ISPCRT_CATCH_BEGIN {
auto &obj = referenceFromHandle(h);
obj.refInc();
}
ISPCRT_CATCH_END()
///////////////////////////////////////////////////////////////////////////////
// Device initialization //////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ISPCRTDevice ispcrtGetDevice(ISPCRTDeviceType type, uint32_t deviceIdx) ISPCRT_CATCH_BEGIN {
ispcrt::base::Device *device = nullptr;
switch (type) {
case ISPCRT_DEVICE_TYPE_AUTO: {
#if defined(ISPCRT_BUILD_GPU) && defined(ISPCRT_BUILD_CPU)
try {
device = new ispcrt::GPUDevice;
} catch (...) {
if (device)
delete device;
device = new ispcrt::CPUDevice;
}
#elif defined(ISPCRT_BUILD_CPU)
device = new ispcrt::CPUDevice;
break;
#elif defined(ISPCRT_BUILD_GPU)
device = new ispcrt::GPUDevice;
break;
#endif
}
case ISPCRT_DEVICE_TYPE_GPU:
#ifdef ISPCRT_BUILD_GPU
device = new ispcrt::GPUDevice(deviceIdx);
#else
throw std::runtime_error("GPU support not enabled");
#endif
break;
case ISPCRT_DEVICE_TYPE_CPU:
#ifdef ISPCRT_BUILD_CPU
device = new ispcrt::CPUDevice;
#else
throw std::runtime_error("CPU support not enabled");
#endif
break;
default:
throw std::runtime_error("Unknown device type queried!");
}
return (ISPCRTDevice)device;
}
ISPCRT_CATCH_END(nullptr)
uint32_t ispcrtGetDeviceCount(ISPCRTDeviceType type) ISPCRT_CATCH_BEGIN {
uint32_t devices = 0;
switch (type) {
case ISPCRT_DEVICE_TYPE_AUTO:
throw std::runtime_error("Device type must be specified");
break;
case ISPCRT_DEVICE_TYPE_GPU:
#ifdef ISPCRT_BUILD_GPU
devices = ispcrt::gpu::deviceCount();
#else
throw std::runtime_error("GPU support not enabled");
#endif
break;
case ISPCRT_DEVICE_TYPE_CPU:
#ifdef ISPCRT_BUILD_CPU
devices = ispcrt::cpu::deviceCount();
#else
throw std::runtime_error("CPU support not enabled");
#endif
break;
default:
throw std::runtime_error("Unknown device type queried!");
}
return devices;
} ISPCRT_CATCH_END(0)
void ispcrtGetDeviceInfo(ISPCRTDeviceType type, uint32_t deviceIdx, ISPCRTDeviceInfo *info) ISPCRT_CATCH_BEGIN {
if (info == nullptr)
throw std::runtime_error("info cannot be null!");
switch (type) {
case ISPCRT_DEVICE_TYPE_AUTO:
throw std::runtime_error("Device type must be specified");
break;
case ISPCRT_DEVICE_TYPE_GPU:
#ifdef ISPCRT_BUILD_GPU
*info = ispcrt::gpu::deviceInfo(deviceIdx);
#else
throw std::runtime_error("GPU support not enabled");
#endif
break;
case ISPCRT_DEVICE_TYPE_CPU:
#ifdef ISPCRT_BUILD_CPU
*info = ispcrt::cpu::deviceInfo(deviceIdx);
#else
throw std::runtime_error("CPU support not enabled");
#endif
break;
default:
throw std::runtime_error("Unknown device type queried!");
}
} ISPCRT_CATCH_END()
///////////////////////////////////////////////////////////////////////////////
// MemoryViews ////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ISPCRTMemoryView ispcrtNewMemoryView(ISPCRTDevice d, void *appMemory, size_t numBytes,
ISPCRTNewMemoryViewFlags *flags) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
return (ISPCRTMemoryView)device.newMemoryView(appMemory, numBytes, flags->allocType == ISPCRT_ALLOC_TYPE_SHARED);
}
ISPCRT_CATCH_END(nullptr)
void *ispcrtHostPtr(ISPCRTMemoryView h) ISPCRT_CATCH_BEGIN {
auto &mv = referenceFromHandle<ispcrt::base::MemoryView>(h);
return mv.hostPtr();
}
ISPCRT_CATCH_END(nullptr)
void *ispcrtDevicePtr(ISPCRTMemoryView h) ISPCRT_CATCH_BEGIN {
auto &mv = referenceFromHandle<ispcrt::base::MemoryView>(h);
return mv.devicePtr();
}
ISPCRT_CATCH_END(nullptr)
size_t ispcrtSize(ISPCRTMemoryView h) ISPCRT_CATCH_BEGIN {
auto &mv = referenceFromHandle<ispcrt::base::MemoryView>(h);
return mv.numBytes();
}
ISPCRT_CATCH_END(0)
void *ispcrtSharedPtr(ISPCRTMemoryView h) ISPCRT_CATCH_BEGIN {
auto &mv = referenceFromHandle<ispcrt::base::MemoryView>(h);
return mv.devicePtr();
}
ISPCRT_CATCH_END(nullptr)
///////////////////////////////////////////////////////////////////////////////
// Kernels ////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ISPCRTModule ispcrtLoadModule(ISPCRTDevice d, const char *moduleFile, ISPCRTModuleOptions moduleOpts) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
return (ISPCRTModule)device.newModule(moduleFile, moduleOpts);
}
ISPCRT_CATCH_END(nullptr)
ISPCRTKernel ispcrtNewKernel(ISPCRTDevice d, ISPCRTModule m, const char *name) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
const auto &module = referenceFromHandle<ispcrt::base::Module>(m);
return (ISPCRTKernel)device.newKernel(module, name);
}
ISPCRT_CATCH_END(nullptr)
///////////////////////////////////////////////////////////////////////////////
// Task queues ////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ISPCRTTaskQueue ispcrtNewTaskQueue(ISPCRTDevice d) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
return (ISPCRTTaskQueue)device.newTaskQueue();
}
ISPCRT_CATCH_END(nullptr)
void ispcrtDeviceBarrier(ISPCRTTaskQueue q) ISPCRT_CATCH_BEGIN {
auto &queue = referenceFromHandle<ispcrt::base::TaskQueue>(q);
queue.barrier();
}
ISPCRT_CATCH_END()
void ispcrtCopyToDevice(ISPCRTTaskQueue q, ISPCRTMemoryView mv) ISPCRT_CATCH_BEGIN {
auto &queue = referenceFromHandle<ispcrt::base::TaskQueue>(q);
auto &view = referenceFromHandle<ispcrt::base::MemoryView>(mv);
queue.copyToDevice(view);
}
ISPCRT_CATCH_END()
void ispcrtCopyToHost(ISPCRTTaskQueue q, ISPCRTMemoryView mv) ISPCRT_CATCH_BEGIN {
auto &queue = referenceFromHandle<ispcrt::base::TaskQueue>(q);
auto &view = referenceFromHandle<ispcrt::base::MemoryView>(mv);
queue.copyToHost(view);
}
ISPCRT_CATCH_END()
ISPCRTFuture ispcrtLaunch1D(ISPCRTTaskQueue q, ISPCRTKernel k, ISPCRTMemoryView p, size_t dim0) ISPCRT_CATCH_BEGIN {
return ispcrtLaunch3D(q, k, p, dim0, 1, 1);
}
ISPCRT_CATCH_END(nullptr)
ISPCRTFuture ispcrtLaunch2D(ISPCRTTaskQueue q, ISPCRTKernel k, ISPCRTMemoryView p, size_t dim0,
size_t dim1) ISPCRT_CATCH_BEGIN {
return ispcrtLaunch3D(q, k, p, dim0, dim1, 1);
}
ISPCRT_CATCH_END(nullptr)
ISPCRTFuture ispcrtLaunch3D(ISPCRTTaskQueue q, ISPCRTKernel k, ISPCRTMemoryView p, size_t dim0, size_t dim1,
size_t dim2) ISPCRT_CATCH_BEGIN {
auto &queue = referenceFromHandle<ispcrt::base::TaskQueue>(q);
auto &kernel = referenceFromHandle<ispcrt::base::Kernel>(k);
ispcrt::base::MemoryView *params = nullptr;
if (p)
params = &referenceFromHandle<ispcrt::base::MemoryView>(p);
return (ISPCRTFuture)queue.launch(kernel, params, dim0, dim1, dim2);
}
ISPCRT_CATCH_END(nullptr)
void ispcrtSync(ISPCRTTaskQueue q) ISPCRT_CATCH_BEGIN {
auto &queue = referenceFromHandle<ispcrt::base::TaskQueue>(q);
queue.sync();
}
ISPCRT_CATCH_END()
uint64_t ispcrtFutureGetTimeNs(ISPCRTFuture f) ISPCRT_CATCH_BEGIN {
if (!f)
return -1;
auto &future = referenceFromHandle<ispcrt::base::Future>(f);
if (!future.valid())
return -1;
return future.time();
}
ISPCRT_CATCH_END(-1)
bool ispcrtFutureIsValid(ISPCRTFuture f) ISPCRT_CATCH_BEGIN {
auto &future = referenceFromHandle<ispcrt::base::Future>(f);
return future.valid();
}
ISPCRT_CATCH_END(false)
///////////////////////////////////////////////////////////////////////////////
// Native handles//////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ISPCRTGenericHandle ispcrtPlatformNativeHandle(ISPCRTDevice d) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
return device.platformNativeHandle();
}
ISPCRT_CATCH_END(nullptr)
ISPCRTGenericHandle ispcrtDeviceNativeHandle(ISPCRTDevice d) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
return device.deviceNativeHandle();
}
ISPCRT_CATCH_END(nullptr)
ISPCRTGenericHandle ispcrtContextNativeHandle(ISPCRTDevice d) ISPCRT_CATCH_BEGIN {
const auto &device = referenceFromHandle<ispcrt::base::Device>(d);
return device.contextNativeHandle();
}
ISPCRT_CATCH_END(nullptr)
ISPCRTGenericHandle ispcrtTaskQueueNativeHandle(ISPCRTTaskQueue q) ISPCRT_CATCH_BEGIN {
const auto &queue = referenceFromHandle<ispcrt::base::TaskQueue>(q);
return queue.taskQueueNativeHandle();
}
ISPCRT_CATCH_END(nullptr)
} // extern "C"