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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 // SOFTWARE. 21 // 22 23 #include "core/resource.hpp" 24 #include "pipe/p_screen.h" 25 #include "util/u_sampler.h" 26 #include "util/u_format.h" 27 28 using namespace clover; 29 30 namespace { 31 class box { 32 public: 33 box(const resource::point &origin, const resource::point &size) : 34 pipe({ (unsigned)origin[0], (unsigned)origin[1], 35 (unsigned)origin[2], (unsigned)size[0], 36 (unsigned)size[1], (unsigned)size[2] }) { 37 } 38 39 operator const pipe_box *() { 40 return &pipe; 41 } 42 43 protected: 44 pipe_box pipe; 45 }; 46 } 47 48 resource::resource(clover::device &dev, clover::memory_obj &obj) : 49 dev(dev), obj(obj), pipe(NULL), offset{0} { 50 } 51 52 resource::~resource() { 53 } 54 55 void 56 resource::copy(command_queue &q, const point &origin, const point ®ion, 57 resource &src_res, const point &src_origin) { 58 point p = offset + origin; 59 60 q.pipe->resource_copy_region(q.pipe, pipe, 0, p[0], p[1], p[2], 61 src_res.pipe, 0, 62 box(src_res.offset + src_origin, region)); 63 } 64 65 void * 66 resource::add_map(command_queue &q, cl_map_flags flags, bool blocking, 67 const point &origin, const point ®ion) { 68 maps.emplace_back(q, *this, flags, blocking, origin, region); 69 return maps.back(); 70 } 71 72 void 73 resource::del_map(void *p) { 74 auto it = std::find(maps.begin(), maps.end(), p); 75 if (it != maps.end()) 76 maps.erase(it); 77 } 78 79 unsigned 80 resource::map_count() const { 81 return maps.size(); 82 } 83 84 pipe_sampler_view * 85 resource::bind_sampler_view(clover::command_queue &q) { 86 pipe_sampler_view info; 87 88 u_sampler_view_default_template(&info, pipe, pipe->format); 89 return q.pipe->create_sampler_view(q.pipe, pipe, &info); 90 } 91 92 void 93 resource::unbind_sampler_view(clover::command_queue &q, 94 pipe_sampler_view *st) { 95 q.pipe->sampler_view_destroy(q.pipe, st); 96 } 97 98 pipe_surface * 99 resource::bind_surface(clover::command_queue &q, bool rw) { 100 pipe_surface info {}; 101 102 info.format = pipe->format; 103 info.usage = pipe->bind; 104 info.writable = rw; 105 106 if (pipe->target == PIPE_BUFFER) 107 info.u.buf.last_element = pipe->width0 - 1; 108 109 return q.pipe->create_surface(q.pipe, pipe, &info); 110 } 111 112 void 113 resource::unbind_surface(clover::command_queue &q, pipe_surface *st) { 114 q.pipe->surface_destroy(q.pipe, st); 115 } 116 117 root_resource::root_resource(clover::device &dev, clover::memory_obj &obj, 118 clover::command_queue &q, 119 const std::string &data) : 120 resource(dev, obj) { 121 pipe_resource info {}; 122 123 if (image *img = dynamic_cast<image *>(&obj)) { 124 info.format = translate_format(img->format()); 125 info.width0 = img->width(); 126 info.height0 = img->height(); 127 info.depth0 = img->depth(); 128 } else { 129 info.width0 = obj.size(); 130 info.height0 = 1; 131 info.depth0 = 1; 132 } 133 134 info.target = translate_target(obj.type()); 135 info.bind = (PIPE_BIND_SAMPLER_VIEW | 136 PIPE_BIND_COMPUTE_RESOURCE | 137 PIPE_BIND_GLOBAL | 138 PIPE_BIND_TRANSFER_READ | 139 PIPE_BIND_TRANSFER_WRITE); 140 141 pipe = dev.pipe->resource_create(dev.pipe, &info); 142 if (!pipe) 143 throw error(CL_OUT_OF_RESOURCES); 144 145 if (!data.empty()) { 146 box rect { { 0, 0, 0 }, { info.width0, info.height0, info.depth0 } }; 147 unsigned cpp = util_format_get_blocksize(info.format); 148 149 q.pipe->transfer_inline_write(q.pipe, pipe, 0, PIPE_TRANSFER_WRITE, 150 rect, data.data(), cpp * info.width0, 151 cpp * info.width0 * info.height0); 152 } 153 } 154 155 root_resource::root_resource(clover::device &dev, clover::memory_obj &obj, 156 clover::root_resource &r) : 157 resource(dev, obj) { 158 assert(0); // XXX -- resource shared among dev and r.dev 159 } 160 161 root_resource::~root_resource() { 162 dev.pipe->resource_destroy(dev.pipe, pipe); 163 } 164 165 sub_resource::sub_resource(clover::resource &r, point offset) : 166 resource(r.dev, r.obj) { 167 pipe = r.pipe; 168 offset = r.offset + offset; 169 } 170 171 mapping::mapping(command_queue &q, resource &r, 172 cl_map_flags flags, bool blocking, 173 const resource::point &origin, 174 const resource::point ®ion) : 175 pctx(q.pipe) { 176 unsigned usage = ((flags & CL_MAP_WRITE ? PIPE_TRANSFER_WRITE : 0 ) | 177 (flags & CL_MAP_READ ? PIPE_TRANSFER_READ : 0 ) | 178 (blocking ? PIPE_TRANSFER_UNSYNCHRONIZED : 0)); 179 180 pxfer = pctx->get_transfer(pctx, r.pipe, 0, usage, 181 box(origin + r.offset, region)); 182 if (!pxfer) 183 throw error(CL_OUT_OF_RESOURCES); 184 185 p = pctx->transfer_map(pctx, pxfer); 186 if (!p) { 187 pctx->transfer_destroy(pctx, pxfer); 188 throw error(CL_OUT_OF_RESOURCES); 189 } 190 } 191 192 mapping::mapping(mapping &&m) : 193 pctx(m.pctx), pxfer(m.pxfer), p(m.p) { 194 m.p = NULL; 195 m.pxfer = NULL; 196 } 197 198 mapping::~mapping() { 199 if (pxfer) { 200 pctx->transfer_unmap(pctx, pxfer); 201 pctx->transfer_destroy(pctx, pxfer); 202 } 203 } 204