diff options
author | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-08-07 16:52:16 +0200 |
---|---|---|
committer | Denis Steckelmacher <steckdenis@yahoo.fr> | 2011-08-07 16:52:16 +0200 |
commit | 09ebb3aa706e0123e912c703e48de995dbe29996 (patch) | |
tree | 5a44ab30d6c666cb680e4c8fa83fc4102b749e39 | |
parent | 1fe65785d632c909a5ee269a9ee33537b760c75d (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.txt | 3 | ||||
-rw-r--r-- | src/api/api_sampler.cpp | 51 | ||||
-rw-r--r-- | src/core/cpu/kernel.cpp | 1 | ||||
-rw-r--r-- | src/core/kernel.cpp | 22 | ||||
-rw-r--r-- | src/core/kernel.h | 1 | ||||
-rw-r--r-- | src/core/sampler.cpp | 215 | ||||
-rw-r--r-- | src/core/sampler.h | 55 |
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 |