Home | History | Annotate | Line # | Download | only in vulkan
      1 /*
      2  * Copyright  2019 Raspberry Pi
      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 (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include "v3dv_private.h"
     25 
     26 /* We don't expect that the packets we use in this file change across hw
     27  * versions, so we just explicitly set the V3D_VERSION and include v3dx_pack
     28  * here
     29  */
     30 #define V3D_VERSION 33
     31 #include "broadcom/common/v3d_macros.h"
     32 #include "broadcom/cle/v3dx_pack.h"
     33 
     34 void
     35 v3dv_cl_init(struct v3dv_job *job, struct v3dv_cl *cl)
     36 {
     37    cl->base = NULL;
     38    cl->next = cl->base;
     39    cl->bo = NULL;
     40    cl->size = 0;
     41    cl->job = job;
     42    list_inithead(&cl->bo_list);
     43 }
     44 
     45 void
     46 v3dv_cl_destroy(struct v3dv_cl *cl)
     47 {
     48    list_for_each_entry_safe(struct v3dv_bo, bo, &cl->bo_list, list_link) {
     49       assert(cl->job);
     50       list_del(&bo->list_link);
     51       v3dv_bo_free(cl->job->device, bo);
     52    }
     53 
     54    /* Leave the CL in a reset state to catch use after destroy instances */
     55    v3dv_cl_init(NULL, cl);
     56 }
     57 
     58 static bool
     59 cl_alloc_bo(struct v3dv_cl *cl, uint32_t space, bool use_branch)
     60 {
     61    struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL", true);
     62    if (!bo) {
     63       fprintf(stderr, "failed to allocate memory for command list\n");
     64       v3dv_flag_oom(NULL, cl->job);
     65       return false;
     66    }
     67 
     68    list_addtail(&bo->list_link, &cl->bo_list);
     69 
     70    bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
     71    if (!ok) {
     72       fprintf(stderr, "failed to map command list buffer\n");
     73       v3dv_flag_oom(NULL, cl->job);
     74       return false;
     75    }
     76 
     77    /* Chain to the new BO from the old one if requested */
     78    if (use_branch && cl->bo) {
     79       cl_emit(cl, BRANCH, branch) {
     80          branch.address = v3dv_cl_address(bo, 0);
     81       }
     82    } else {
     83       v3dv_job_add_bo_unchecked(cl->job, bo);
     84    }
     85 
     86    cl->bo = bo;
     87    cl->base = cl->bo->map;
     88    cl->size = cl->bo->size;
     89    cl->next = cl->base;
     90 
     91    return true;
     92 }
     93 
     94 uint32_t
     95 v3dv_cl_ensure_space(struct v3dv_cl *cl, uint32_t space, uint32_t alignment)
     96 {
     97    uint32_t offset = align(v3dv_cl_offset(cl), alignment);
     98 
     99    if (offset + space <= cl->size) {
    100       cl->next = cl->base + offset;
    101       return offset;
    102    }
    103 
    104    cl_alloc_bo(cl, space, false);
    105    return 0;
    106 }
    107 
    108 void
    109 v3dv_cl_ensure_space_with_branch(struct v3dv_cl *cl, uint32_t space)
    110 {
    111    /* We do not want to emit branches from secondary command lists, instead,
    112     * we will branch to them when we execute them in a primary using
    113     * 'branch to sub list' commands, expecting each linked secondary to
    114     * end with a 'return from sub list' command.
    115     */
    116    bool needs_return_from_sub_list = false;
    117    if (cl->job->type == V3DV_JOB_TYPE_GPU_CL_SECONDARY) {
    118       if (cl->size > 0) {
    119          needs_return_from_sub_list = true;
    120          space += cl_packet_length(RETURN_FROM_SUB_LIST);
    121       }
    122    } else {
    123       space += cl_packet_length(BRANCH);
    124    }
    125 
    126    if (v3dv_cl_offset(cl) + space <= cl->size)
    127       return;
    128 
    129    if (needs_return_from_sub_list)
    130       cl_emit(cl, RETURN_FROM_SUB_LIST, ret);
    131 
    132    cl_alloc_bo(cl, space, !needs_return_from_sub_list);
    133 }
    134