Home | History | Annotate | Download | only in core
      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 &region,
     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 &region) {
     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 &region) :
    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