Example #1
0
static int
vc4_simulator_pin_bos(struct drm_device *dev, struct vc4_exec_info *exec)
{
        struct drm_vc4_submit_cl *args = exec->args;
        struct vc4_context *vc4 = dev->vc4;
        struct vc4_bo **bos = vc4->bo_pointers.base;

        exec->bo_count = args->bo_handle_count;
        exec->bo = calloc(exec->bo_count, sizeof(void *));
        for (int i = 0; i < exec->bo_count; i++) {
                struct vc4_bo *bo = bos[i];
                struct drm_gem_cma_object *obj = vc4_wrap_bo_with_cma(dev, bo);

                struct drm_vc4_bo *drm_bo = to_vc4_bo(&obj->base);
#if 0
                fprintf(stderr, "bo hindex %d: %s\n", i, bo->name);
#endif

                vc4_bo_map(bo);
                memcpy(obj->vaddr, bo->map, bo->size);

                exec->bo[i] = obj;

                /* The kernel does this validation at shader create ioctl
                 * time.
                 */
                if (strcmp(bo->name, "code") == 0) {
                        drm_bo->validated_shader = vc4_validate_shader(obj);
                        if (!drm_bo->validated_shader)
                                abort();
                }
        }
        return 0;
}
static int
vc4_simulator_pin_bos(struct drm_device *dev, struct exec_info *exec)
{
        struct drm_vc4_submit_cl *args = exec->args;
        struct vc4_context *vc4 = dev->vc4;
        struct vc4_bo **bos = vc4->bo_pointers.base;

        exec->bo_count = args->bo_handle_count;
        exec->bo = calloc(exec->bo_count, sizeof(struct vc4_bo_exec_state));
        for (int i = 0; i < exec->bo_count; i++) {
                struct vc4_bo *bo = bos[i];
                struct drm_gem_cma_object *obj = vc4_wrap_bo_with_cma(dev, bo);

#if 0
                fprintf(stderr, "bo hindex %d: %s\n", i, bo->name);
#endif

                vc4_bo_map(bo);
                memcpy(obj->vaddr, bo->map, bo->size);

                exec->bo[i].bo = obj;
        }
        return 0;
}
static void *
vc4_resource_transfer_map(struct pipe_context *pctx,
                          struct pipe_resource *prsc,
                          unsigned level, unsigned usage,
                          const struct pipe_box *box,
                          struct pipe_transfer **pptrans)
{
    struct vc4_context *vc4 = vc4_context(pctx);
    struct vc4_resource *rsc = vc4_resource(prsc);
    struct vc4_resource_slice *slice = &rsc->slices[level];
    struct vc4_transfer *trans;
    struct pipe_transfer *ptrans;
    enum pipe_format format = prsc->format;
    char *buf;

    if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
        vc4_resource_bo_alloc(rsc);
    } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
        if (vc4_cl_references_bo(pctx, rsc->bo)) {
            if ((usage & PIPE_TRANSFER_DISCARD_RANGE) &&
                    prsc->last_level == 0 &&
                    prsc->width0 == box->width &&
                    prsc->height0 == box->height &&
                    prsc->depth0 == box->depth) {
                vc4_resource_bo_alloc(rsc);
            } else {
                vc4_flush(pctx);
            }
        }
    }

    if (usage & PIPE_TRANSFER_WRITE)
        rsc->writes++;

    trans = util_slab_alloc(&vc4->transfer_pool);
    if (!trans)
        return NULL;

    /* XXX: Handle DONTBLOCK, DISCARD_RANGE, PERSISTENT, COHERENT. */

    /* util_slab_alloc() doesn't zero: */
    memset(trans, 0, sizeof(*trans));
    ptrans = &trans->base;

    pipe_resource_reference(&ptrans->resource, prsc);
    ptrans->level = level;
    ptrans->usage = usage;
    ptrans->box = *box;

    /* Note that the current kernel implementation is synchronous, so no
     * need to do syncing stuff here yet.
     */

    buf = vc4_bo_map(rsc->bo);
    if (!buf) {
        fprintf(stderr, "Failed to map bo\n");
        goto fail;
    }

    *pptrans = ptrans;

    if (rsc->tiled) {
        uint32_t utile_w = vc4_utile_width(rsc->cpp);
        uint32_t utile_h = vc4_utile_height(rsc->cpp);

        /* No direct mappings of tiled, since we need to manually
         * tile/untile.
         */
        if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
            return NULL;

        /* We need to align the box to utile boundaries, since that's
         * what load/store operate on.
         */
        uint32_t box_start_x = ptrans->box.x & (utile_w - 1);
        uint32_t box_start_y = ptrans->box.y & (utile_h - 1);
        ptrans->box.width += box_start_x;
        ptrans->box.x -= box_start_x;
        ptrans->box.height += box_start_y;
        ptrans->box.y -= box_start_y;
        ptrans->box.width = align(ptrans->box.width, utile_w);
        ptrans->box.height = align(ptrans->box.height, utile_h);

        ptrans->stride = ptrans->box.width * rsc->cpp;
        ptrans->layer_stride = ptrans->stride;

        trans->map = malloc(ptrans->stride * ptrans->box.height);
        if (usage & PIPE_TRANSFER_READ) {
            vc4_load_tiled_image(trans->map, ptrans->stride,
                                 buf + slice->offset +
                                 box->z * rsc->cube_map_stride,
                                 slice->stride,
                                 slice->tiling, rsc->cpp,
                                 &ptrans->box);
        }
        return (trans->map +
                box_start_x * rsc->cpp +
                box_start_y * ptrans->stride);
    } else {
        ptrans->stride = slice->stride;
        ptrans->layer_stride = ptrans->stride;

        return buf + slice->offset +
               box->y / util_format_get_blockheight(format) * ptrans->stride +
               box->x / util_format_get_blockwidth(format) * rsc->cpp +
               box->z * rsc->cube_map_stride;
    }


fail:
    vc4_resource_transfer_unmap(pctx, ptrans);
    return NULL;
}