1 /* OpenCL runtime library: clSetKernelArg()
2
3 Copyright (c) 2011 Universidad Rey Juan Carlos
4 2013 Pekka Jääskeläinen / Tampere University of Technology
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24
25 #include "config.h"
26 #include "pocl_cl.h"
27 #include "pocl_debug.h"
28 #include "pocl_util.h"
29 #include <assert.h>
30 #include <stdbool.h>
31 #include <string.h>
32
33 static char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
34 '9', 'A', 'B', 'C', 'D', 'E', 'F', 'X', 'Y' };
35
36 static void
dump_hex(const char * data,size_t size,char * buffer)37 dump_hex (const char *data, size_t size, char *buffer)
38 {
39 size_t j = 0;
40 for (size_t i = 0; i < size; ++i)
41 {
42 if (i % 4 == 0)
43 buffer[j++] = ' ';
44 char c = data[i];
45 buffer[j] = hex[(c & 0xF0) >> 4];
46 buffer[j + 1] = hex[c & 0x0F];
47 j += 2;
48 }
49 buffer[j] = 0;
50 }
51
52 CL_API_ENTRY cl_int CL_API_CALL
POname(clSetKernelArg)53 POname(clSetKernelArg)(cl_kernel kernel,
54 cl_uint arg_index,
55 size_t arg_size,
56 const void *arg_value) CL_API_SUFFIX__VERSION_1_0
57 {
58 size_t arg_alignment, arg_alloc_size;
59 struct pocl_argument *p;
60 struct pocl_argument_info *pi;
61
62 POCL_RETURN_ERROR_COND ((!IS_CL_OBJECT_VALID (kernel)), CL_INVALID_KERNEL);
63
64 POCL_RETURN_ERROR_ON ((arg_index >= kernel->meta->num_args),
65 CL_INVALID_ARG_INDEX,
66 "This kernel has %u args, cannot set arg %u\n",
67 (unsigned)kernel->meta->num_args, (unsigned)arg_index);
68
69 POCL_RETURN_ERROR_ON((kernel->dyn_arguments == NULL), CL_INVALID_KERNEL,
70 "This kernel has no arguments that could be set\n");
71
72 pi = &(kernel->meta->arg_info[arg_index]);
73 int is_local = ARGP_IS_LOCAL (pi);
74
75 const void *ptr_value = NULL;
76 if (((pi->type == POCL_ARG_TYPE_POINTER)
77 || (pi->type == POCL_ARG_TYPE_IMAGE))
78 && arg_value)
79 ptr_value = *(const void **)arg_value;
80
81 if (POCL_DEBUGGING_ON)
82 {
83 const void *ptr_value = NULL;
84 uint32_t uint32_value = 0;
85 uint64_t uint64_value = 0;
86 if (((pi->type == POCL_ARG_TYPE_POINTER)
87 || (pi->type == POCL_ARG_TYPE_IMAGE))
88 && arg_value)
89 {
90 ptr_value = *(const void **)arg_value;
91 }
92 else
93 {
94 if (arg_value && (arg_size == 4))
95 uint32_value = *(uint32_t *)arg_value;
96 if (arg_value && (arg_size == 8))
97 uint64_value = *(uint64_t *)arg_value;
98 }
99
100 char *hexval = NULL;
101 if (arg_value && (arg_size < 1024))
102 {
103 hexval = (char *)alloca ((arg_size * 2) + (arg_size / 4) + 8);
104 dump_hex (arg_value, arg_size, hexval);
105 }
106
107 POCL_MSG_PRINT_GENERAL ("Kernel %15s || SetArg idx %3u || %8s || "
108 "Local %1i || Size %6zu || Value %p || "
109 "Pointer %p || *(uint32*)Value: %8u || "
110 "*(uint64*)Value: %8lu ||\nHex Value: %s\n",
111 kernel->name, arg_index, pi->type_name, is_local,
112 arg_size, arg_value, ptr_value, uint32_value,
113 uint64_value, hexval);
114 }
115
116 POCL_RETURN_ERROR_ON (
117 ((arg_value != NULL) && is_local), CL_INVALID_ARG_VALUE,
118 "arg_value != NULL and arg %u is in local address space\n", arg_index);
119
120 /* Trigger CL_INVALID_ARG_VALUE if arg_value specified is NULL
121 * for an argument that is not declared with the __local qualifier. */
122 POCL_RETURN_ERROR_ON (
123 ((arg_value == NULL) && (!is_local)
124 && (pi->type != POCL_ARG_TYPE_POINTER)),
125 CL_INVALID_ARG_VALUE,
126 "arg_value == NULL and arg %u is not in local address space\n",
127 arg_index);
128
129 /* Trigger CL_INVALID_ARG_SIZE if arg_size is zero
130 * and the argument is declared with the __local qualifier. */
131 POCL_RETURN_ERROR_ON (((arg_size == 0) && is_local), CL_INVALID_ARG_SIZE,
132 "arg_size == 0 and arg %u is in local address space\n",
133 arg_index);
134
135 POCL_RETURN_ERROR_ON (
136 ((pi->type == POCL_ARG_TYPE_SAMPLER) && (arg_value == NULL)),
137 CL_INVALID_SAMPLER, "arg_value == NULL and arg is a cl_sampler\n");
138
139 if (pi->type == POCL_ARG_TYPE_POINTER || pi->type == POCL_ARG_TYPE_IMAGE
140 || pi->type == POCL_ARG_TYPE_SAMPLER)
141 {
142 POCL_RETURN_ERROR_ON (((!is_local) && (arg_size != sizeof (cl_mem))),
143 CL_INVALID_ARG_SIZE,
144 "Arg %u is pointer/buffer/image, but arg_size is "
145 "not sizeof(cl_mem)\n",
146 arg_index);
147 if (ptr_value)
148 {
149 POCL_RETURN_ERROR_ON (
150 !IS_CL_OBJECT_VALID ((const cl_mem)ptr_value),
151 CL_INVALID_ARG_VALUE,
152 "Arg %u is not a valid CL object\n", arg_index);
153 }
154 }
155 else if (pi->type_size)
156 {
157 size_t as = arg_size;
158 /* handle <type>3 vectors, we accept both <type>3 and <type>4 sizes */
159 if (as % 3 == 0)
160 as = (as / 3) * 4;
161 POCL_RETURN_ERROR_ON (
162 (pi->type_size != as), CL_INVALID_ARG_SIZE,
163 "Arg %u is %s, but arg_size is not sizeof(%s) == %u\n", arg_index,
164 pi->type_name, pi->type_name, pi->type_size);
165 }
166
167 p = &(kernel->dyn_arguments[arg_index]);
168 if (kernel->dyn_argument_storage == NULL)
169 pocl_aligned_free (p->value);
170 p->value = NULL;
171 p->is_set = 0;
172 p->is_readonly = 0;
173 p->is_svm = 0;
174
175 /* Even if the buffer/image is read-write, the kernel might be using it as
176 * read-only */
177 if ((kernel->meta->has_arg_metadata & POCL_HAS_KERNEL_ARG_ACCESS_QUALIFIER)
178 && (pi->address_qualifier == CL_KERNEL_ARG_ADDRESS_GLOBAL))
179 {
180 if (pi->type == POCL_ARG_TYPE_IMAGE)
181 {
182 p->is_readonly
183 = (pi->access_qualifier & CL_KERNEL_ARG_ACCESS_READ_ONLY ? 1
184 : 0);
185 }
186 if (pi->type == POCL_ARG_TYPE_POINTER)
187 {
188 p->is_readonly
189 = (pi->type_qualifier & CL_KERNEL_ARG_TYPE_CONST ? 1 : 0);
190 }
191 }
192
193 if (arg_value != NULL
194 && !(pi->type == POCL_ARG_TYPE_POINTER
195 && *(const intptr_t *)arg_value == 0))
196 {
197 void *value;
198 if (kernel->dyn_argument_storage != NULL)
199 value = kernel->dyn_argument_offsets[arg_index];
200 else
201 {
202 /* FIXME: this is a cludge to determine an acceptable alignment,
203 * we should probably extract the argument alignment from the
204 * LLVM bytecode during kernel header generation. */
205 arg_alignment = pocl_size_ceil2 (arg_size);
206 if (arg_alignment >= MAX_EXTENDED_ALIGNMENT)
207 arg_alignment = MAX_EXTENDED_ALIGNMENT;
208
209 arg_alloc_size = arg_size;
210 if (arg_alloc_size < arg_alignment)
211 arg_alloc_size = arg_alignment;
212
213 value = pocl_aligned_malloc (arg_alignment, arg_alloc_size);
214 if (value == NULL)
215 {
216 return CL_OUT_OF_HOST_MEMORY;
217 }
218 }
219
220 if ((pi->type == POCL_ARG_TYPE_POINTER) && (arg_value != NULL))
221 {
222 cl_mem buf = *(const cl_mem *)arg_value;
223 if (buf->parent != NULL)
224 {
225 p->offset = buf->origin;
226 buf = buf->parent;
227 }
228 else
229 {
230 p->offset = 0;
231 }
232 memcpy (value, &buf, arg_size);
233 }
234 else
235 memcpy (value, arg_value, arg_size);
236 p->value = value;
237 }
238
239 #if 0
240 printf(
241 "### clSetKernelArg for %s arg %d (size %u) set to %x points to %x\n",
242 kernel->name, arg_index, arg_size, p->value, *(int*)arg_value);
243 #endif
244
245 p->size = arg_size;
246 p->is_set = 1;
247
248 return CL_SUCCESS;
249 }
250 POsym(clSetKernelArg)
251