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 image_rd_argument(); 222 223 virtual void set(size_t size, const void *value); 224 virtual void bind(exec_context &ctx, 225 const binary::argument &barg); 226 virtual void unbind(exec_context &ctx); 227 228 private: 229 pipe_sampler_view *st; 230 }; 231 232 class image_wr_argument : public image_argument { 233 public: 234 virtual void set(size_t size, const void *value); 235 virtual void bind(exec_context &ctx, 236 const binary::argument &barg); 237 virtual void unbind(exec_context &ctx); 238 }; 239 240 class sampler_argument : public argument { 241 public: 242 sampler_argument(); 243 244 virtual void set(size_t size, const void *value); 245 virtual void bind(exec_context &ctx, 246 const binary::argument &barg); 247 virtual void unbind(exec_context &ctx); 248 249 private: 250 sampler *s; 251 void *st; 252 }; 253 254 std::vector<std::unique_ptr<argument>> _args; 255 std::map<device *, std::unique_ptr<root_buffer> > _constant_buffers; 256 std::string _name; 257 exec_context exec; 258 const ref_holder program_ref; 259 }; 260 } 261 262 #endif 263