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 28using namespace clover; 29 30namespace { 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 48resource::resource(clover::device &dev, clover::memory_obj &obj) : 49 dev(dev), obj(obj), pipe(NULL), offset{0} { 50} 51 52resource::~resource() { 53} 54 55void 56resource::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 65void * 66resource::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 72void 73resource::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 79unsigned 80resource::map_count() const { 81 return maps.size(); 82} 83 84pipe_sampler_view * 85resource::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 92void 93resource::unbind_sampler_view(clover::command_queue &q, 94 pipe_sampler_view *st) { 95 q.pipe->sampler_view_destroy(q.pipe, st); 96} 97 98pipe_surface * 99resource::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 112void 113resource::unbind_surface(clover::command_queue &q, pipe_surface *st) { 114 q.pipe->surface_destroy(q.pipe, st); 115} 116 117root_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 155root_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 161root_resource::~root_resource() { 162 dev.pipe->resource_destroy(dev.pipe, pipe); 163} 164 165sub_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 171mapping::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 192mapping::mapping(mapping &&m) : 193 pctx(m.pctx), pxfer(m.pxfer), p(m.p) { 194 m.p = NULL; 195 m.pxfer = NULL; 196} 197 198mapping::~mapping() { 199 if (pxfer) { 200 pctx->transfer_unmap(pctx, pxfer); 201 pctx->transfer_destroy(pctx, pxfer); 202 } 203} 204