1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 
23 #ifndef CLOVER_CORE_KERNEL_HPP
24 #define CLOVER_CORE_KERNEL_HPP
25 
26 #include <map>
27 #include <memory>
28 
29 #include "core/object.hpp"
30 #include "core/printf.hpp"
31 #include "core/program.hpp"
32 #include "core/memory.hpp"
33 #include "core/sampler.hpp"
34 #include "pipe/p_state.h"
35 
36 namespace clover {
37    class kernel : public ref_counter, public _cl_kernel {
38    private:
39       ///
40       /// Class containing all the state required to execute a compute
41       /// kernel.
42       ///
43       struct exec_context {
44          exec_context(kernel &kern);
45          ~exec_context();
46 
47          exec_context(const exec_context &) = delete;
48          exec_context &
49          operator=(const exec_context &) = delete;
50 
51          void *bind(intrusive_ptr<command_queue> _q,
52                     const std::vector<size_t> &grid_offset);
53          void unbind();
54 
55          kernel &kern;
56          intrusive_ptr<command_queue> q;
57          std::unique_ptr<printf_handler> print_handler;
58 
59          std::vector<uint8_t> input;
60          std::vector<void *> samplers;
61          std::vector<pipe_sampler_view *> sviews;
62          std::vector<pipe_image_view> iviews;
63          std::vector<pipe_surface *> resources;
64          std::vector<pipe_resource *> g_buffers;
65          std::vector<size_t> g_handles;
66          size_t mem_local;
67 
68       private:
69          void *st;
70          pipe_compute_state cs;
71       };
72 
73    public:
74       class argument {
75       public:
76          static std::unique_ptr<argument>
77          create(const binary::argument &barg);
78 
79          argument(const argument &arg) = delete;
80          argument &
81          operator=(const argument &arg) = delete;
82 
83          /// \a true if the argument has been set.
84          bool set() const;
85 
86          /// Storage space required for the referenced object.
87          virtual size_t storage() const;
88 
89          /// Set this argument to some object.
90          virtual void set(size_t size, const void *value) = 0;
91 
92          /// Set this argument to an SVM pointer.
set_svm(const void * value)93          virtual void set_svm(const void *value) {
94             throw error(CL_INVALID_ARG_INDEX);
95          };
96 
97          /// Allocate the necessary resources to bind the specified
98          /// object to this argument, and update \a ctx accordingly.
99          virtual void bind(exec_context &ctx,
100                            const binary::argument &barg) = 0;
101 
102          /// Free any resources that were allocated in bind().
103          virtual void unbind(exec_context &ctx) = 0;
104 
~argument()105          virtual ~argument() {};
106       protected:
107          argument();
108 
109          bool _set;
110       };
111 
112    private:
113       typedef adaptor_range<
114             derefs, std::vector<std::unique_ptr<argument>> &
115          > argument_range;
116 
117       typedef adaptor_range<
118             derefs, const std::vector<std::unique_ptr<argument>> &
119          > const_argument_range;
120 
121    public:
122       kernel(clover::program &prog, const std::string &name,
123              const std::vector<clover::binary::argument> &bargs);
124 
125       kernel(const kernel &kern) = delete;
126       kernel &
127       operator=(const kernel &kern) = delete;
128 
129       void launch(command_queue &q,
130                   const std::vector<size_t> &grid_offset,
131                   const std::vector<size_t> &grid_size,
132                   const std::vector<size_t> &block_size);
133 
134       size_t mem_local() const;
135       size_t mem_private() const;
136 
137       const std::string &name() const;
138 
139       std::vector<size_t>
140       optimal_block_size(const command_queue &q,
141                          const std::vector<size_t> &grid_size) const;
142       std::vector<size_t>
143       required_block_size() const;
144 
145       argument_range args();
146       const_argument_range args() const;
147       std::vector<clover::binary::arg_info> args_infos();
148 
149       const intrusive_ref<clover::program> program;
150 
151    private:
152       const clover::binary &binary(const command_queue &q) const;
153 
154       class scalar_argument : public argument {
155       public:
156          scalar_argument(size_t size);
157 
158          virtual void set(size_t size, const void *value);
159          virtual void bind(exec_context &ctx,
160                            const binary::argument &barg);
161          virtual void unbind(exec_context &ctx);
162 
163       private:
164          size_t size;
165          std::vector<uint8_t> v;
166       };
167 
168       class global_argument : public argument {
169       public:
170          global_argument();
171 
172          virtual void set(size_t size, const void *value);
173          virtual void set_svm(const void *value);
174          virtual void bind(exec_context &ctx,
175                            const binary::argument &barg);
176          virtual void unbind(exec_context &ctx);
177 
178       private:
179          buffer *buf;
180          const void *svm;
181       };
182 
183       class local_argument : public argument {
184       public:
185          virtual size_t storage() const;
186 
187          virtual void set(size_t size, const void *value);
188          virtual void bind(exec_context &ctx,
189                            const binary::argument &barg);
190          virtual void unbind(exec_context &ctx);
191 
192       private:
193          size_t _storage = 0;
194       };
195 
196       class constant_argument : public argument {
197       public:
198          constant_argument();
199 
200          virtual void set(size_t size, const void *value);
201          virtual void bind(exec_context &ctx,
202                            const binary::argument &barg);
203          virtual void unbind(exec_context &ctx);
204 
205       private:
206          buffer *buf;
207          pipe_surface *st;
208       };
209 
210       class image_argument : public argument {
211       public:
get() const212          const image *get() const {
213             return img;
214          }
215       protected:
216          image *img;
217       };
218 
219       class image_rd_argument : public image_argument {
220       public:
221          virtual void set(size_t size, const void *value);
222          virtual void bind(exec_context &ctx,
223                            const binary::argument &barg);
224          virtual void unbind(exec_context &ctx);
225 
226       private:
227          pipe_sampler_view *st;
228       };
229 
230       class image_wr_argument : public image_argument {
231       public:
232          virtual void set(size_t size, const void *value);
233          virtual void bind(exec_context &ctx,
234                            const binary::argument &barg);
235          virtual void unbind(exec_context &ctx);
236       };
237 
238       class sampler_argument : public argument {
239       public:
240          sampler_argument();
241 
242          virtual void set(size_t size, const void *value);
243          virtual void bind(exec_context &ctx,
244                            const binary::argument &barg);
245          virtual void unbind(exec_context &ctx);
246 
247       private:
248          sampler *s;
249          void *st;
250       };
251 
252       std::vector<std::unique_ptr<argument>> _args;
253       std::map<device *, std::unique_ptr<root_buffer> > _constant_buffers;
254       std::string _name;
255       exec_context exec;
256       const ref_holder program_ref;
257    };
258 }
259 
260 #endif
261