summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Steckelmacher <steckdenis@yahoo.fr>2011-08-07 16:52:16 +0200
committerDenis Steckelmacher <steckdenis@yahoo.fr>2011-08-07 16:52:16 +0200
commit09ebb3aa706e0123e912c703e48de995dbe29996 (patch)
tree5a44ab30d6c666cb680e4c8fa83fc4102b749e39
parent1fe65785d632c909a5ee269a9ee33537b760c75d (diff)
Implement samplers (currently untested).
The two previous commits were needed in order to be able to recognize a sampler, because they are simple uint32 in OpenCL, and LLVM only says that a kernel argument is of type "i32".
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/api/api_sampler.cpp51
-rw-r--r--src/core/cpu/kernel.cpp1
-rw-r--r--src/core/kernel.cpp22
-rw-r--r--src/core/kernel.h1
-rw-r--r--src/core/sampler.cpp215
-rw-r--r--src/core/sampler.h55
7 files changed, 342 insertions, 6 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 344f7f2..c1693ab 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -33,7 +33,8 @@ set(COAL_SRC_FILES
core/program.cpp
core/compiler.cpp
core/kernel.cpp
- core/refcounted.cpp
+ core/sampler.cpp
+ core/object.cpp
core/cpu/buffer.cpp
core/cpu/device.cpp
diff --git a/src/api/api_sampler.cpp b/src/api/api_sampler.cpp
index af375b4..c6100f5 100644
--- a/src/api/api_sampler.cpp
+++ b/src/api/api_sampler.cpp
@@ -1,5 +1,8 @@
#include "CL/cl.h"
+#include "core/sampler.h"
+#include "core/context.h"
+
// Sampler APIs
cl_sampler
clCreateSampler(cl_context context,
@@ -8,19 +11,55 @@ clCreateSampler(cl_context context,
cl_filter_mode filter_mode,
cl_int * errcode_ret)
{
- return 0;
+ cl_int dummy_errcode;
+
+ if (!errcode_ret)
+ errcode_ret = &dummy_errcode;
+
+ if (!context->isA(Coal::Object::T_Context))
+ {
+ *errcode_ret = CL_INVALID_CONTEXT;
+ return 0;
+ }
+
+ *errcode_ret = CL_SUCCESS;
+
+ Coal::Sampler *sampler = new Coal::Sampler((Coal::Context *)context,
+ normalized_coords,
+ addressing_mode,
+ filter_mode,
+ errcode_ret);
+
+ if (*errcode_ret != CL_SUCCESS)
+ {
+ delete sampler;
+ return 0;
+ }
+
+ return (cl_sampler)sampler;
}
cl_int
clRetainSampler(cl_sampler sampler)
{
- return 0;
+ if (!sampler->isA(Coal::Object::T_Sampler))
+ return CL_INVALID_SAMPLER;
+
+ sampler->reference();
+
+ return CL_SUCCESS;
}
cl_int
clReleaseSampler(cl_sampler sampler)
{
- return 0;
+ if (!sampler->isA(Coal::Object::T_Sampler))
+ return CL_INVALID_SAMPLER;
+
+ if (sampler->dereference())
+ delete sampler;
+
+ return CL_SUCCESS;
}
cl_int
@@ -30,5 +69,9 @@ clGetSamplerInfo(cl_sampler sampler,
void * param_value,
size_t * param_value_size_ret)
{
- return 0;
+ if (!sampler->isA(Coal::Object::T_Sampler))
+ return CL_INVALID_SAMPLER;
+
+ return sampler->info(param_name, param_value_size, param_value,
+ param_value_size_ret);
}
diff --git a/src/core/cpu/kernel.cpp b/src/core/cpu/kernel.cpp
index 55f2a6a..ca281b2 100644
--- a/src/core/cpu/kernel.cpp
+++ b/src/core/cpu/kernel.cpp
@@ -215,6 +215,7 @@ llvm::Function *CPUKernel::callFunction(std::vector<void *> &freeLocal)
break;
case Kernel::Arg::Int32:
+ case Kernel::Arg::Sampler:
C = llvm::ConstantInt::get(stub->getContext(),
llvm::APInt(32, *(uint32_t *)value));
break;
diff --git a/src/core/kernel.cpp b/src/core/kernel.cpp
index c71264a..2a5a90b 100644
--- a/src/core/kernel.cpp
+++ b/src/core/kernel.cpp
@@ -2,6 +2,7 @@
#include "propertylist.h"
#include "program.h"
#include "memobject.h"
+#include "sampler.h"
#include "deviceinterface.h"
#include <string>
@@ -158,6 +159,7 @@ cl_int Kernel::addFunction(DeviceInterface *device, llvm::Function *function,
}
else if (i_type->getBitWidth() == 32)
{
+ // NOTE: May also be a sampler, check done in setArg
kind = Arg::Int32;
}
else if (i_type->getBitWidth() == 64)
@@ -220,6 +222,19 @@ cl_int Kernel::setArg(cl_uint index, size_t size, const void *value)
// Check that size corresponds to the arg type
size_t arg_size = arg.valueSize();
+ // Special case for samplers (pointers in C++, uint32 in OpenCL).
+ if (size == sizeof(cl_sampler) && arg_size == 4 &&
+ (*(Object **)value)->isA(T_Sampler))
+ {
+ unsigned int bitfield = (*(Sampler **)value)->bitfield();
+
+ arg.refineKind(Arg::Sampler);
+ arg.alloc();
+ arg.loadData(&bitfield);
+
+ return CL_SUCCESS;
+ }
+
if (size != arg_size)
return CL_INVALID_ARG_SIZE;
@@ -236,7 +251,6 @@ cl_int Kernel::setArg(cl_uint index, size_t size, const void *value)
// Special case buffers : value can be 0 (or point to 0)
value = &null_mem;
- // TODO samplers
default:
return CL_INVALID_ARG_VALUE;
}
@@ -428,6 +442,11 @@ void Kernel::Arg::setAllocAtKernelRuntime(size_t size)
p_defined = true;
}
+void Kernel::Arg::refineKind (Kernel::Arg::Kind kind)
+{
+ p_kind = kind;
+}
+
bool Kernel::Arg::operator!=(const Arg &b)
{
bool same = (p_vec_dim == b.p_vec_dim) &&
@@ -448,6 +467,7 @@ size_t Kernel::Arg::valueSize() const
case Int16:
return 2;
case Int32:
+ case Sampler:
return 4;
case Int64:
return 8;
diff --git a/src/core/kernel.h b/src/core/kernel.h
index 9d4375b..5bb8988 100644
--- a/src/core/kernel.h
+++ b/src/core/kernel.h
@@ -58,6 +58,7 @@ class Kernel : public Object
void alloc();
void loadData(const void *data);
void setAllocAtKernelRuntime(size_t size);
+ void refineKind(Kind kind);
bool operator !=(const Arg &b);
diff --git a/src/core/sampler.cpp b/src/core/sampler.cpp
new file mode 100644
index 0000000..aae8b89
--- /dev/null
+++ b/src/core/sampler.cpp
@@ -0,0 +1,215 @@
+#include "sampler.h"
+#include "context.h"
+#include "deviceinterface.h"
+#include "propertylist.h"
+
+#include <cstring>
+#include <cstdlib>
+
+using namespace Coal;
+
+Sampler::Sampler(Context *ctx,
+ cl_bool normalized_coords,
+ cl_addressing_mode addressing_mode,
+ cl_filter_mode filter_mode,
+ cl_int *errcode_ret)
+: Object(Object::T_Sampler), p_bitfield(0)
+{
+ if (normalized_coords)
+ p_bitfield |= CLK_NORMALIZED_COORDS_TRUE;
+ else
+ p_bitfield |= CLK_NORMALIZED_COORDS_FALSE;
+
+ switch (addressing_mode)
+ {
+ case CL_ADDRESS_NONE:
+ p_bitfield |= CLK_ADDRESS_NONE;
+ break;
+
+ case CL_ADDRESS_MIRRORED_REPEAT:
+ p_bitfield |= CLK_ADDRESS_MIRRORED_REPEAT;
+ break;
+
+ case CL_ADDRESS_REPEAT:
+ p_bitfield |= CLK_ADDRESS_REPEAT;
+ break;
+
+ case CL_ADDRESS_CLAMP_TO_EDGE:
+ p_bitfield |= CLK_ADDRESS_CLAMP_TO_EDGE;
+ break;
+
+ case CL_ADDRESS_CLAMP:
+ p_bitfield |= CLK_ADDRESS_CLAMP;
+ break;
+
+ default:
+ *errcode_ret = CL_INVALID_VALUE;
+ return;
+ }
+
+ switch (filter_mode)
+ {
+ case CL_FILTER_NEAREST:
+ p_bitfield |= CLK_FILTER_NEAREST;
+ break;
+
+ case CL_FILTER_LINEAR:
+ p_bitfield |= CLK_FILTER_LINEAR;
+ break;
+
+ default:
+ *errcode_ret = CL_INVALID_VALUE;
+ return;
+ }
+
+ // Check that images are available on all the devices
+ *errcode_ret = checkImageAvailability();
+}
+
+Sampler::Sampler(Context *ctx, unsigned int bitfield)
+: Object(Object::T_Sampler, ctx), p_bitfield(bitfield)
+{
+ checkImageAvailability();
+}
+
+cl_int Sampler::checkImageAvailability() const
+{
+ cl_uint num_devices;
+ DeviceInterface **devices;
+ cl_int rs;
+
+ rs = ((Context *)parent())->info(CL_CONTEXT_NUM_DEVICES,
+ sizeof(unsigned int),
+ &num_devices, 0);
+
+ if (rs != CL_SUCCESS)
+ return rs;
+
+ devices = (DeviceInterface **)std::malloc(num_devices *
+ sizeof(DeviceInterface *));
+
+ if (!devices)
+ {
+ return CL_OUT_OF_HOST_MEMORY;
+ }
+
+ rs = ((Context *)parent())->info(CL_CONTEXT_DEVICES,
+ num_devices * sizeof(DeviceInterface *),
+ devices, 0);
+
+ if (rs != CL_SUCCESS)
+ {
+ std::free((void *)devices);
+ return rs;
+ }
+
+ for (unsigned int i=0; i<num_devices; ++i)
+ {
+ cl_bool image_support;
+
+ rs = devices[i]->info(CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool),
+ &image_support, 0);
+
+ if (rs != CL_SUCCESS)
+ {
+ std::free((void *)devices);
+ return rs;
+ }
+
+ if (!image_support)
+ {
+ std:free((void *)devices);
+ return CL_INVALID_OPERATION;
+ }
+ }
+
+ std::free((void *)devices);
+
+ return CL_SUCCESS;
+}
+
+unsigned int Sampler::bitfield() const
+{
+ return p_bitfield;
+}
+
+cl_int Sampler::info(cl_sampler_info param_name,
+ size_t param_value_size,
+ void *param_value,
+ size_t *param_value_size_ret) const
+{
+ void *value = 0;
+ size_t value_length = 0;
+
+ union {
+ cl_uint cl_uint_var;
+ cl_context cl_context_var;
+ cl_bool cl_bool_var;
+ cl_addressing_mode cl_addressing_mode_var;
+ cl_filter_mode cl_filter_mode_var;
+ };
+
+ switch (param_name)
+ {
+ case CL_SAMPLER_REFERENCE_COUNT:
+ SIMPLE_ASSIGN(cl_uint, references());
+ break;
+
+ case CL_SAMPLER_CONTEXT:
+ SIMPLE_ASSIGN(cl_context, parent());
+ break;
+
+ case CL_SAMPLER_NORMALIZED_COORDS:
+ if (p_bitfield & CLK_NORMALIZED_COORDS_MASK)
+ SIMPLE_ASSIGN(cl_bool, true)
+ else
+ SIMPLE_ASSIGN(cl_bool, false);
+ break;
+
+ case CL_SAMPLER_ADDRESSING_MODE:
+ switch (p_bitfield & CLK_ADDRESS_MODE_MASK)
+ {
+ case CLK_ADDRESS_CLAMP:
+ SIMPLE_ASSIGN(cl_addressing_mode, CL_ADDRESS_CLAMP);
+ break;
+ case CLK_ADDRESS_CLAMP_TO_EDGE:
+ SIMPLE_ASSIGN(cl_addressing_mode, CL_ADDRESS_CLAMP_TO_EDGE);
+ break;
+ case CLK_ADDRESS_MIRRORED_REPEAT:
+ SIMPLE_ASSIGN(cl_addressing_mode, CL_ADDRESS_MIRRORED_REPEAT);
+ break;
+ case CLK_ADDRESS_REPEAT:
+ SIMPLE_ASSIGN(cl_addressing_mode, CL_ADDRESS_REPEAT);
+ break;
+ case CLK_ADDRESS_NONE:
+ SIMPLE_ASSIGN(cl_addressing_mode, CL_ADDRESS_NONE);
+ break;
+ }
+ break;
+
+ case CL_SAMPLER_FILTER_MODE:
+ switch (p_bitfield & CLK_FILTER_MASK)
+ {
+ case CLK_FILTER_LINEAR:
+ SIMPLE_ASSIGN(cl_filter_mode, CL_FILTER_LINEAR);
+ break;
+ case CLK_FILTER_NEAREST:
+ SIMPLE_ASSIGN(cl_filter_mode, CL_FILTER_NEAREST);
+ break;
+ }
+
+ default:
+ return CL_INVALID_VALUE;
+ }
+
+ if (param_value && param_value_size < value_length)
+ return CL_INVALID_VALUE;
+
+ if (param_value_size_ret)
+ *param_value_size_ret = value_length;
+
+ if (param_value)
+ std::memcpy(param_value, value, value_length);
+
+ return CL_SUCCESS;
+}
diff --git a/src/core/sampler.h b/src/core/sampler.h
new file mode 100644
index 0000000..515a0c6
--- /dev/null
+++ b/src/core/sampler.h
@@ -0,0 +1,55 @@
+#ifndef __SAMPLER_H__
+#define __SAMPLER_H__
+
+#include <CL/cl.h>
+#include "object.h"
+
+#define CLK_NORMALIZED_COORDS_FALSE 0x00000000
+#define CLK_NORMALIZED_COORDS_TRUE 0x00000001
+#define CLK_ADDRESS_NONE 0x00000000
+#define CLK_ADDRESS_MIRRORED_REPEAT 0x00000010
+#define CLK_ADDRESS_REPEAT 0x00000020
+#define CLK_ADDRESS_CLAMP_TO_EDGE 0x00000030
+#define CLK_ADDRESS_CLAMP 0x00000040
+#define CLK_FILTER_NEAREST 0x00000000
+#define CLK_FILTER_LINEAR 0x00000100
+
+#define CLK_NORMALIZED_COORDS_MASK 0x0000000f
+#define CLK_ADDRESS_MODE_MASK 0x000000f0
+#define CLK_FILTER_MASK 0x00000f00
+
+namespace Coal
+{
+
+class Context;
+
+class Sampler : public Object
+{
+ public:
+ Sampler(Context *ctx,
+ cl_bool normalized_coords,
+ cl_addressing_mode addressing_mode,
+ cl_filter_mode filter_mode,
+ cl_int *errcode_ret);
+ Sampler(Context *ctx,
+ unsigned int bitfield);
+
+ unsigned int bitfield() const;
+
+ cl_int info(cl_sampler_info param_name,
+ size_t param_value_size,
+ void *param_value,
+ size_t *param_value_size_ret) const;
+
+ private:
+ unsigned int p_bitfield;
+
+ cl_int checkImageAvailability() const;
+};
+
+}
+
+struct _cl_sampler : public Coal::Sampler
+{};
+
+#endif