Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 6fc7338d authored by schultezub's avatar schultezub
Browse files

KissCL:

 * Command queue properties are global per CLRuntime
 * Simplified Kernel::setArgument() and added templated Kernel::setArguments()
 * cleaned up BUffer, Image and SharedTexture/GLTexture

* some work on CLRaycaster

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@247 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 576bad56
......@@ -27,6 +27,7 @@ namespace kisscl {
CLRuntime::CLRuntime()
: tgt::ResourceManager<Program>(false)
, _commandQueueProperties(0)
{
initPlatforms();
}
......@@ -64,11 +65,11 @@ namespace kisscl {
}
}
const std::vector<Device*> CLRuntime::getCPUDevices() const {
const std::vector<Device*>& CLRuntime::getCPUDevices() const {
return _cpuDevices;
}
const std::vector<Device*> CLRuntime::getGPUDevices() const {
const std::vector<Device*>& CLRuntime::getGPUDevices() const {
return _gpuDevices;
}
......@@ -125,16 +126,18 @@ namespace kisscl {
_globalHeader = header;
}
CommandQueue* CLRuntime::getCommandQueue(Context* context, cl_command_queue_properties properties /*= 0*/) {
return getCommandQueue(context, context->getDevices().front());
}
CommandQueue* CLRuntime::getCommandQueue(Context* context, Device* device, cl_command_queue_properties properties /*= 0*/) {
CommandQueue* CLRuntime::getCommandQueue(Context* context, Device* device /*= 0*/) {
tgtAssert(context != 0, "Context may not be 0.");
if (device == 0)
device = context->getDevices().front();
std::pair<Context*, Device*> p = std::make_pair(context, device);
auto lb = _commandQueues.lower_bound(p);
if (lb == _commandQueues.end() || lb ->first != p) {
CommandQueue* queue = new CommandQueue(context, device, properties);
CommandQueue* queue = new CommandQueue(context, device, _commandQueueProperties);
_commandQueues.insert(lb, std::make_pair(p, queue));
return queue;
}
......@@ -143,4 +146,12 @@ namespace kisscl {
}
}
cl_command_queue_properties CLRuntime::getCommandQueueProperties() const {
return _commandQueueProperties;
}
void CLRuntime::setCommandQueueProperties(cl_command_queue_properties cqp) {
_commandQueueProperties = cqp;
}
}
\ No newline at end of file
......@@ -66,13 +66,13 @@ namespace kisscl {
* Gets the list of all available OpenCL CPU devices.
* \return _cpuDevices
*/
const std::vector<Device*> getCPUDevices() const;
const std::vector<Device*>& getCPUDevices() const;
/**
* Gets the list of all available OpenCL GPU devices.
* \return _gpuDevices
*/
const std::vector<Device*> getGPUDevices() const;
const std::vector<Device*>& getGPUDevices() const;
/**
* Creates a new OpenCL program from the given context from the file specified by \a filename.
......@@ -103,23 +103,26 @@ namespace kisscl {
void setGlobalHeader(const std::string& header);
/**
* Gets the command queue for the given OpenCL context and its first device.
* If no such command queue has yet been requested, a new one will be created.
* \param context OpenCL context to create the command queue for.
* \param properties Command queue properties bitfield.
* \return The command queue for the given context and its first device.
* Gets the Command queue properties bitfield for all newly created command queues.
* \return _commandQueueProperties
*/
cl_command_queue_properties getCommandQueueProperties() const;
/**
* Sets the Command queue properties bitfield for all newly created command queues.
* \param cqp The new Command queue properties bitfield for all newly created command queues.
*/
CommandQueue* getCommandQueue(Context* context, cl_command_queue_properties properties = 0);
void setCommandQueueProperties(cl_command_queue_properties cqp);
/**
* Gets the command queue for the given OpenCL context-device pair.
* If no such command queue has yet been requested, a new one will be created.
* \param context OpenCL context to create the command queue for.
* \param device OpenCL device to create the command queue for.
* \param device OpenCL device to create the command queue for, if 0 the first device of the given context will be taken (default).
* \param properties Command queue properties bitfield.
* \return The command queue for the given context-device pair.
*/
CommandQueue* getCommandQueue(Context* context, Device* device, cl_command_queue_properties properties = 0);
CommandQueue* getCommandQueue(Context* context, Device* device = 0);
private:
/**
......@@ -133,6 +136,7 @@ namespace kisscl {
std::vector<Device*> _gpuDevices; ///< List of all OpenCL GPU devices (just a shortcut to the corresponding devices in _platforms)
std::map< std::pair<Context*, Device*>, CommandQueue*> _commandQueues;
cl_command_queue_properties _commandQueueProperties; ///< Command queue properties bitfield for all newly created command queues.
std::string _globalHeader; ///< The global header for OpenCL programs.
......
......@@ -189,14 +189,14 @@ namespace kisscl {
return Event(e);
}
Event CommandQueue::enqueueAcquireGLObject(const SharedTexture* texture, const EventList& eventsToWaitFor /*= EventList()*/) {
Event CommandQueue::enqueueAcquireGLObject(const GLTexture* texture, const EventList& eventsToWaitFor /*= EventList()*/) {
cl_event e;
cl_mem mem = texture->getId();
LCL_ERROR(clEnqueueAcquireGLObjects(_id, 1, &mem, eventsToWaitFor._size, eventsToWaitFor._events, &e));
return Event(e);
}
Event CommandQueue::enqueueReleaseGLObject(const SharedTexture* texture, const EventList& eventsToWaitFor /*= EventList()*/) {
Event CommandQueue::enqueueReleaseGLObject(const GLTexture* texture, const EventList& eventsToWaitFor /*= EventList()*/) {
cl_event e;
cl_mem mem = texture->getId();
LCL_ERROR(clEnqueueReleaseGLObjects(_id, 1, &mem, eventsToWaitFor._size, eventsToWaitFor._events, &e));
......
......@@ -32,7 +32,7 @@ namespace kisscl {
class Context;
class Device;
class Kernel;
class SharedTexture;
class GLTexture;
/**
* Wrapper class for an OpenCL command queue.
......@@ -183,9 +183,9 @@ namespace kisscl {
// TODO: buffers, images, etc.
Event enqueueAcquireGLObject(const SharedTexture* texture, const EventList& eventsToWaitFor = EventList());
Event enqueueAcquireGLObject(const GLTexture* texture, const EventList& eventsToWaitFor = EventList());
Event enqueueReleaseGLObject(const SharedTexture* texture, const EventList& eventsToWaitFor = EventList());
Event enqueueReleaseGLObject(const GLTexture* texture, const EventList& eventsToWaitFor = EventList());
private:
......
......@@ -36,8 +36,25 @@ namespace kisscl {
return getInfo<cl_uint>(CL_KERNEL_NUM_ARGS);
}
void Kernel::setMemoryArgument(cl_uint index, const MemoryObject* memoryObject) {
cl_mem mem = memoryObject->getId();
// void Kernel::setMemoryArgument(cl_uint index, const MemoryObject* memoryObject) {
// cl_mem mem = memoryObject->getId();
// LCL_ERROR(clSetKernelArg(_id, index, sizeof(cl_mem), &mem));
// }
template<>
void Kernel::setArgument(cl_uint index, const Buffer& data) {
cl_mem mem = data.getId();
LCL_ERROR(clSetKernelArg(_id, index, sizeof(cl_mem), &mem));
}
template<>
void Kernel::setArgument(cl_uint index, const Image& data) {
cl_mem mem = data.getId();
LCL_ERROR(clSetKernelArg(_id, index, sizeof(cl_mem), &mem));
}
template<>
void Kernel::setArgument(cl_uint index, const GLTexture& data) {
cl_mem mem = data.getId();
LCL_ERROR(clSetKernelArg(_id, index, sizeof(cl_mem), &mem));
}
......
......@@ -103,7 +103,7 @@ namespace kisscl {
*/
Kernel(cl_kernel id);
/**
/**
* Sets the kernel argument with index \a index to \a data.
* \param index Argument index
* \param data Data
......@@ -111,13 +111,132 @@ namespace kisscl {
template<class T>
void setArgument(cl_uint index, const T& data);
// TODO: samplers, buffers, etc.
// Note: If the number of arguments is not enough, have a look at the handy Python script generating the templates.
/**
* Set the 1 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
*/
template<class C0>
void setArguments(C0 co);
/**
* Set the 2 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
*/
template<class C0, class C1>
void setArguments(C0 co, C1 c1);
/**
* Set the 3 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
*/
template<class C0, class C1, class C2>
void setArguments(C0 co, C1 c1, C2 c2);
/**
* Set the 4 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
*/
template<class C0, class C1, class C2, class C3>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3);
/**
* Set the 5 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
* \param c4 Argument 5
*/
template<class C0, class C1, class C2, class C3, class C4>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3, C4 c4);
/**
* Sets the kernel argument with index \a index to the given MemoryObject
* \param index Argument index
* \param memoryObject Memory object to set as kernel argument
* Set the 6 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
* \param c4 Argument 5
* \param c5 Argument 6
*/
void setMemoryArgument(cl_uint index, const MemoryObject* memoryObject);
template<class C0, class C1, class C2, class C3, class C4, class C5>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5);
/**
* Set the 7 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
* \param c4 Argument 5
* \param c5 Argument 6
* \param c6 Argument 7
*/
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6);
/**
* Set the 8 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
* \param c4 Argument 5
* \param c5 Argument 6
* \param c6 Argument 7
* \param c7 Argument 8
*/
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6, class C7>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7);
/**
* Set the 9 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
* \param c4 Argument 5
* \param c5 Argument 6
* \param c6 Argument 7
* \param c7 Argument 8
* \param c8 Argument 9
*/
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6, class C7, class C8>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8);
/**
* Set the 10 arguments of the kernel.
* \note The number of arguments must match to the kernel.
* \param c0 Argument 1
* \param c1 Argument 2
* \param c2 Argument 3
* \param c3 Argument 4
* \param c4 Argument 5
* \param c5 Argument 6
* \param c6 Argument 7
* \param c7 Argument 8
* \param c8 Argument 9
* \param c9 Argument 10
*/
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6, class C7, class C8, class C9>
void setArguments(C0 co, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8, C9 c9);
private:
/**
......@@ -129,12 +248,141 @@ namespace kisscl {
static const std::string loggerCat_;
};
// ================================================================================================
template<class T>
void kisscl::Kernel::setArgument(cl_uint index, const T& data) {
LCL_ERROR(clSetKernelArg(_id, index, KernelArgumentTypeTraits<T>::size(), KernelArgumentTypeTraits<T>::pointer(data)));
}
template<>
void Kernel::setArgument(cl_uint index, const Buffer& data);
template<>
void Kernel::setArgument(cl_uint index, const Image& data);
template<>
void Kernel::setArgument(cl_uint index, const GLTexture& data);
// ================================================================================================
template<class C0>
void Kernel::setArguments(C0 c0) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 1, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
}
template<class C0, class C1>
void Kernel::setArguments(C0 c0, C1 c1) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 2, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
}
template<class C0, class C1, class C2>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 3, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
}
template<class C0, class C1, class C2, class C3>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 4, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
}
template<class C0, class C1, class C2, class C3, class C4>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3, C4 c4) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 5, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
setArgument<C4>(4, c4);
}
template<class C0, class C1, class C2, class C3, class C4, class C5>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 6, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
setArgument<C4>(4, c4);
setArgument<C5>(5, c5);
}
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 7, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
setArgument<C4>(4, c4);
setArgument<C5>(5, c5);
setArgument<C6>(6, c6);
}
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6, class C7>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 8, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
setArgument<C4>(4, c4);
setArgument<C5>(5, c5);
setArgument<C6>(6, c6);
setArgument<C7>(7, c7);
}
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6, class C7, class C8>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 9, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
setArgument<C4>(4, c4);
setArgument<C5>(5, c5);
setArgument<C6>(6, c6);
setArgument<C7>(7, c7);
setArgument<C8>(8, c8);
}
template<class C0, class C1, class C2, class C3, class C4, class C5, class C6, class C7, class C8, class C9>
void Kernel::setArguments(C0 c0, C1 c1, C2 c2, C3 c3, C4 c4, C5 c5, C6 c6, C7 c7, C8 c8, C9 c9) {
tgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == 10, "Numer of arguments does not match the kernel's number of arguments.");
setArgument<C0>(0, c0);
setArgument<C1>(1, c1);
setArgument<C2>(2, c2);
setArgument<C3>(3, c3);
setArgument<C4>(4, c4);
setArgument<C5>(5, c5);
setArgument<C6>(6, c6);
setArgument<C7>(7, c7);
setArgument<C8>(8, c8);
setArgument<C9>(9, c9);
}
}
#endif // KISSCL_KERNEL_H__
# Just a really simple script to automatically create the setArgument templates...
import string
def createTemplateDef(numArgs):
toReturn = """/**
* Set the """ + str(numArgs) + """ arguments of the kernel.
* \\note The number of arguments must match to the kernel.\n"""
for i in range(0, numArgs):
toReturn += ' * \\param c' + str(i) + ' Argument ' + str(i+1) + '\n'
toReturn += ' */\ntemplate<class C0'
for i in range(1, numArgs):
toReturn += ', class C' + str(i)
toReturn += '>\n'
toReturn += 'void setArguments(C0 co'
for i in range(1, numArgs):
toReturn += ', C' + str(i) + ' c' + str(i)
toReturn += ');\n'
return toReturn
def createTemplateDecl(numArgs):
toReturn = 'template<class C0'
for i in range(1, numArgs):
toReturn += ', class C' + str(i)
toReturn += '>\n'
toReturn += 'void Kernel::setArguments(C0 c0'
for i in range(1, numArgs):
toReturn += ', C' + str(i) + ' c' + str(i)
toReturn += ') {\n'
toReturn += '\ttgtAssert(getInfo<cl_uint>(CL_KERNEL_NUM_ARGS) == ' + str(numArgs) + ', "Numer of arguments does not match the kernel\'s number of arguments.");\n\n'
for i in range(0, numArgs):
toReturn += '\tsetArgument<C' + str(i) + '>(' + str(i) + ', c' + str(i) + ');\n'
toReturn += '}\n'
return toReturn
def create(numArgs):
toReturn = ''
for i in range(1, numArgs+1):
toReturn += createTemplateDef(i) + '\n'
toReturn += '\n\n'
for i in range(1, numArgs+1):
toReturn += createTemplateDecl(i) + '\n'
return toReturn
print(create(10))
......@@ -229,6 +229,7 @@ namespace kisscl {
};
}
/**
* Helper function to transform an OpenCL error code to a string.
* \param err OpenCL error code.
......
......@@ -196,8 +196,9 @@ namespace kisscl {
}
// ================================================================================================
SharedTexture::SharedTexture(const Context* context, cl_mem_flags flags, const tgt::Texture* texture)
GLTexture::GLTexture(const Context* context, cl_mem_flags flags, const tgt::Texture* texture)
: MemoryObject(context)
, _texture(texture)
{
......@@ -225,13 +226,13 @@ namespace kisscl {
LCL_ERROR(err);
break;
default:
LERRORC("kisscl.SharedTexture", "Unknown texture type!");
LERRORC("kisscl.GLTexture", "Unknown texture type!");
#endif // defined(CL_VERSION_1_2)
}
}
SharedTexture::~SharedTexture() {
GLTexture::~GLTexture() {
}
......
......@@ -58,6 +58,9 @@ namespace kisscl {
// ================================================================================================
/**
* Simple wrapper around an OpenCL buffer.
*/
class Buffer : public MemoryObject {
public:
/**
......@@ -86,25 +89,55 @@ namespace kisscl {
// ================================================================================================
/**
* Wrapper around an OpenCL image that can be accessed in kernels via read/write_image.
*/
class Image : public MemoryObject {
public:
/**
* Creates an OpenCL image from a tgt::Texture.
* \param context Context where this image object resides.
* \param flags Flags specifying allocation and usage information for this buffer.
* \param texture Pointer to the texture used for initalization, must have valid pixel data in host memory.
*/
Image(const Context* context, cl_mem_flags flags, const tgt::Texture* texture);
/**
* Creates an OpenCL image from scratch.
* \param context Context where this image object resides.