Home | History | Annotate | Download | only in ilo
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2012-2013 LunarG, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Chia-I Wu <olv (at) lunarg.com>
     26  */
     27 
     28 #include "core/ilo_state_vf.h"
     29 #include "core/ilo_state_sol.h"
     30 #include "core/ilo_state_surface.h"
     31 
     32 #include "ilo_screen.h"
     33 #include "ilo_format.h"
     34 #include "ilo_resource.h"
     35 
     36 /*
     37  * From the Ivy Bridge PRM, volume 1 part 1, page 105:
     38  *
     39  *     "In addition to restrictions on maximum height, width, and depth,
     40  *      surfaces are also restricted to a maximum size in bytes. This
     41  *      maximum is 2 GB for all products and all surface types."
     42  */
     43 static const size_t ilo_max_resource_size = 1u << 31;
     44 
     45 static const char *
     46 resource_get_bo_name(const struct pipe_resource *templ)
     47 {
     48    static const char *target_names[PIPE_MAX_TEXTURE_TYPES] = {
     49       [PIPE_BUFFER] = "buf",
     50       [PIPE_TEXTURE_1D] = "tex-1d",
     51       [PIPE_TEXTURE_2D] = "tex-2d",
     52       [PIPE_TEXTURE_3D] = "tex-3d",
     53       [PIPE_TEXTURE_CUBE] = "tex-cube",
     54       [PIPE_TEXTURE_RECT] = "tex-rect",
     55       [PIPE_TEXTURE_1D_ARRAY] = "tex-1d-array",
     56       [PIPE_TEXTURE_2D_ARRAY] = "tex-2d-array",
     57       [PIPE_TEXTURE_CUBE_ARRAY] = "tex-cube-array",
     58    };
     59    const char *name = target_names[templ->target];
     60 
     61    if (templ->target == PIPE_BUFFER) {
     62       switch (templ->bind) {
     63       case PIPE_BIND_VERTEX_BUFFER:
     64          name = "buf-vb";
     65          break;
     66       case PIPE_BIND_INDEX_BUFFER:
     67          name = "buf-ib";
     68          break;
     69       case PIPE_BIND_CONSTANT_BUFFER:
     70          name = "buf-cb";
     71          break;
     72       case PIPE_BIND_STREAM_OUTPUT:
     73          name = "buf-so";
     74          break;
     75       default:
     76          break;
     77       }
     78    }
     79 
     80    return name;
     81 }
     82 
     83 static bool
     84 resource_get_cpu_init(const struct pipe_resource *templ)
     85 {
     86    return (templ->bind & (PIPE_BIND_DEPTH_STENCIL |
     87                           PIPE_BIND_RENDER_TARGET |
     88                           PIPE_BIND_STREAM_OUTPUT)) ? false : true;
     89 }
     90 
     91 static enum gen_surface_type
     92 get_surface_type(enum pipe_texture_target target)
     93 {
     94    switch (target) {
     95    case PIPE_TEXTURE_1D:
     96    case PIPE_TEXTURE_1D_ARRAY:
     97       return GEN6_SURFTYPE_1D;
     98    case PIPE_TEXTURE_2D:
     99    case PIPE_TEXTURE_RECT:
    100    case PIPE_TEXTURE_2D_ARRAY:
    101       return GEN6_SURFTYPE_2D;
    102    case PIPE_TEXTURE_3D:
    103       return GEN6_SURFTYPE_3D;
    104    case PIPE_TEXTURE_CUBE:
    105    case PIPE_TEXTURE_CUBE_ARRAY:
    106       return GEN6_SURFTYPE_CUBE;
    107    default:
    108       assert(!"unknown texture target");
    109       return GEN6_SURFTYPE_NULL;
    110    }
    111 }
    112 
    113 static enum pipe_format
    114 resource_get_image_format(const struct pipe_resource *templ,
    115                           const struct ilo_dev *dev,
    116                           bool *separate_stencil_ret)
    117 {
    118    enum pipe_format format = templ->format;
    119    bool separate_stencil;
    120 
    121    /* silently promote ETC1 */
    122    if (templ->format == PIPE_FORMAT_ETC1_RGB8)
    123       format = PIPE_FORMAT_R8G8B8X8_UNORM;
    124 
    125    /* separate stencil buffers */
    126    separate_stencil = false;
    127    if ((templ->bind & PIPE_BIND_DEPTH_STENCIL) &&
    128        util_format_is_depth_and_stencil(templ->format)) {
    129       switch (templ->format) {
    130       case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
    131          /* Gen6 requires HiZ to be available for all levels */
    132          if (ilo_dev_gen(dev) >= ILO_GEN(7) || templ->last_level == 0) {
    133             format = PIPE_FORMAT_Z32_FLOAT;
    134             separate_stencil = true;
    135          }
    136          break;
    137       case PIPE_FORMAT_Z24_UNORM_S8_UINT:
    138          format = PIPE_FORMAT_Z24X8_UNORM;
    139          separate_stencil = true;
    140          break;
    141       default:
    142          break;
    143       }
    144    }
    145 
    146    if (separate_stencil_ret)
    147       *separate_stencil_ret = separate_stencil;
    148 
    149    return format;
    150 }
    151 
    152 static inline enum gen_surface_format
    153 pipe_to_surface_format(const struct ilo_dev *dev, enum pipe_format format)
    154 {
    155    switch (format) {
    156    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
    157       return GEN6_FORMAT_R32_FLOAT_X8X24_TYPELESS;
    158    case PIPE_FORMAT_Z32_FLOAT:
    159       return GEN6_FORMAT_R32_FLOAT;
    160    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
    161    case PIPE_FORMAT_Z24X8_UNORM:
    162       return GEN6_FORMAT_R24_UNORM_X8_TYPELESS;
    163    case PIPE_FORMAT_Z16_UNORM:
    164       return GEN6_FORMAT_R16_UNORM;
    165    case PIPE_FORMAT_S8_UINT:
    166       return GEN6_FORMAT_R8_UINT;
    167    default:
    168       return ilo_format_translate_color(dev, format);
    169    }
    170 }
    171 
    172 static void
    173 resource_get_image_info(const struct pipe_resource *templ,
    174                         const struct ilo_dev *dev,
    175                         enum pipe_format image_format,
    176                         struct ilo_image_info *info)
    177 {
    178    memset(info, 0, sizeof(*info));
    179 
    180    info->type = get_surface_type(templ->target);
    181 
    182    info->format = pipe_to_surface_format(dev, image_format);
    183    info->interleaved_stencil = util_format_is_depth_and_stencil(image_format);
    184    info->is_integer = util_format_is_pure_integer(image_format);
    185    info->compressed = util_format_is_compressed(image_format);
    186    info->block_width = util_format_get_blockwidth(image_format);
    187    info->block_height = util_format_get_blockheight(image_format);
    188    info->block_size = util_format_get_blocksize(image_format);
    189 
    190    info->width = templ->width0;
    191    info->height = templ->height0;
    192    info->depth = templ->depth0;
    193    info->array_size = templ->array_size;
    194    info->level_count = templ->last_level + 1;
    195    info->sample_count = (templ->nr_samples) ? templ->nr_samples : 1;
    196 
    197    info->aux_disable = (templ->usage == PIPE_USAGE_STAGING);
    198 
    199    if (templ->bind & PIPE_BIND_LINEAR)
    200       info->valid_tilings = 1 << GEN6_TILING_NONE;
    201 
    202    /*
    203     * Tiled images must be mapped via GTT to get a linear view.  Prefer linear
    204     * images when the image size is greater than one-fourth of the mappable
    205     * aperture.
    206     */
    207    if (templ->usage == PIPE_USAGE_STAGING)
    208       info->prefer_linear_threshold = dev->aperture_mappable / 4;
    209 
    210    info->bind_surface_sampler = (templ->bind & PIPE_BIND_SAMPLER_VIEW);
    211    info->bind_surface_dp_render = (templ->bind & PIPE_BIND_RENDER_TARGET);
    212    info->bind_surface_dp_typed = (templ->bind &
    213          (PIPE_BIND_SHADER_IMAGE | PIPE_BIND_COMPUTE_RESOURCE));
    214    info->bind_zs = (templ->bind & PIPE_BIND_DEPTH_STENCIL);
    215    info->bind_scanout = (templ->bind & PIPE_BIND_SCANOUT);
    216    info->bind_cursor = (templ->bind & PIPE_BIND_CURSOR);
    217 }
    218 
    219 static enum gen_surface_tiling
    220 winsys_to_surface_tiling(enum intel_tiling_mode tiling)
    221 {
    222    switch (tiling) {
    223    case INTEL_TILING_NONE:
    224       return GEN6_TILING_NONE;
    225    case INTEL_TILING_X:
    226       return GEN6_TILING_X;
    227    case INTEL_TILING_Y:
    228       return GEN6_TILING_Y;
    229    default:
    230       assert(!"unknown tiling");
    231       return GEN6_TILING_NONE;
    232    }
    233 }
    234 
    235 static inline enum intel_tiling_mode
    236 surface_to_winsys_tiling(enum gen_surface_tiling tiling)
    237 {
    238    switch (tiling) {
    239    case GEN6_TILING_NONE:
    240       return INTEL_TILING_NONE;
    241    case GEN6_TILING_X:
    242       return INTEL_TILING_X;
    243    case GEN6_TILING_Y:
    244       return INTEL_TILING_Y;
    245    default:
    246       assert(!"unknown tiling");
    247       return GEN6_TILING_NONE;
    248    }
    249 }
    250 
    251 static void
    252 tex_free_slices(struct ilo_texture *tex)
    253 {
    254    FREE(tex->slices[0]);
    255 }
    256 
    257 static bool
    258 tex_alloc_slices(struct ilo_texture *tex)
    259 {
    260    const struct pipe_resource *templ = &tex->base;
    261    struct ilo_texture_slice *slices;
    262    int depth, lv;
    263 
    264    /* sum the depths of all levels */
    265    depth = 0;
    266    for (lv = 0; lv <= templ->last_level; lv++)
    267       depth += u_minify(templ->depth0, lv);
    268 
    269    /*
    270     * There are (depth * tex->base.array_size) slices in total.  Either depth
    271     * is one (non-3D) or templ->array_size is one (non-array), but it does
    272     * not matter.
    273     */
    274    slices = CALLOC(depth * templ->array_size, sizeof(*slices));
    275    if (!slices)
    276       return false;
    277 
    278    tex->slices[0] = slices;
    279 
    280    /* point to the respective positions in the buffer */
    281    for (lv = 1; lv <= templ->last_level; lv++) {
    282       tex->slices[lv] = tex->slices[lv - 1] +
    283          u_minify(templ->depth0, lv - 1) * templ->array_size;
    284    }
    285 
    286    return true;
    287 }
    288 
    289 static bool
    290 tex_create_bo(struct ilo_texture *tex)
    291 {
    292    struct ilo_screen *is = ilo_screen(tex->base.screen);
    293    const char *name = resource_get_bo_name(&tex->base);
    294    const bool cpu_init = resource_get_cpu_init(&tex->base);
    295    struct intel_bo *bo;
    296 
    297    bo = intel_winsys_alloc_bo(is->dev.winsys, name,
    298          tex->image.bo_stride * tex->image.bo_height, cpu_init);
    299 
    300    /* set the tiling for transfer and export */
    301    if (bo && (tex->image.tiling == GEN6_TILING_X ||
    302               tex->image.tiling == GEN6_TILING_Y)) {
    303       const enum intel_tiling_mode tiling =
    304          surface_to_winsys_tiling(tex->image.tiling);
    305 
    306       if (intel_bo_set_tiling(bo, tiling, tex->image.bo_stride)) {
    307          intel_bo_unref(bo);
    308          bo = NULL;
    309       }
    310    }
    311    if (!bo)
    312       return false;
    313 
    314    intel_bo_unref(tex->vma.bo);
    315    ilo_vma_set_bo(&tex->vma, &is->dev, bo, 0);
    316 
    317    return true;
    318 }
    319 
    320 static bool
    321 tex_create_separate_stencil(struct ilo_texture *tex)
    322 {
    323    struct pipe_resource templ = tex->base;
    324    struct pipe_resource *s8;
    325 
    326    /*
    327     * Unless PIPE_BIND_DEPTH_STENCIL is set, the resource may have other
    328     * tilings.  But that should be fine since it will never be bound as the
    329     * stencil buffer, and our transfer code can handle all tilings.
    330     */
    331    templ.format = PIPE_FORMAT_S8_UINT;
    332 
    333    /* no stencil texturing */
    334    templ.bind &= ~PIPE_BIND_SAMPLER_VIEW;
    335 
    336    s8 = tex->base.screen->resource_create(tex->base.screen, &templ);
    337    if (!s8)
    338       return false;
    339 
    340    tex->separate_s8 = ilo_texture(s8);
    341 
    342    assert(tex->separate_s8->image_format == PIPE_FORMAT_S8_UINT);
    343 
    344    return true;
    345 }
    346 
    347 static bool
    348 tex_create_hiz(struct ilo_texture *tex)
    349 {
    350    const struct pipe_resource *templ = &tex->base;
    351    const uint32_t size = tex->image.aux.bo_stride * tex->image.aux.bo_height;
    352    struct ilo_screen *is = ilo_screen(tex->base.screen);
    353    struct intel_bo *bo;
    354 
    355    bo = intel_winsys_alloc_bo(is->dev.winsys, "hiz texture", size, false);
    356    if (!bo)
    357       return false;
    358 
    359    ilo_vma_init(&tex->aux_vma, &is->dev, size, 4096);
    360    ilo_vma_set_bo(&tex->aux_vma, &is->dev, bo, 0);
    361 
    362    if (tex->imported) {
    363       unsigned lv;
    364 
    365       for (lv = 0; lv <= templ->last_level; lv++) {
    366          if (tex->image.aux.enables & (1 << lv)) {
    367             const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ?
    368                u_minify(templ->depth0, lv) : templ->array_size;
    369             /* this will trigger HiZ resolves */
    370             const unsigned flags = ILO_TEXTURE_CPU_WRITE;
    371 
    372             ilo_texture_set_slice_flags(tex, lv, 0, num_slices, flags, flags);
    373          }
    374       }
    375    }
    376 
    377    return true;
    378 }
    379 
    380 static bool
    381 tex_create_mcs(struct ilo_texture *tex)
    382 {
    383    const uint32_t size = tex->image.aux.bo_stride * tex->image.aux.bo_height;
    384    struct ilo_screen *is = ilo_screen(tex->base.screen);
    385    struct intel_bo *bo;
    386 
    387    assert(tex->image.aux.enables == (1 << (tex->base.last_level + 1)) - 1);
    388 
    389    bo = intel_winsys_alloc_bo(is->dev.winsys, "mcs texture", size, false);
    390    if (!bo)
    391       return false;
    392 
    393    ilo_vma_init(&tex->aux_vma, &is->dev, size, 4096);
    394    ilo_vma_set_bo(&tex->aux_vma, &is->dev, bo, 0);
    395 
    396    return true;
    397 }
    398 
    399 static void
    400 tex_destroy(struct ilo_texture *tex)
    401 {
    402    if (tex->separate_s8)
    403       tex_destroy(tex->separate_s8);
    404 
    405    intel_bo_unref(tex->vma.bo);
    406    intel_bo_unref(tex->aux_vma.bo);
    407 
    408    tex_free_slices(tex);
    409    FREE(tex);
    410 }
    411 
    412 static bool
    413 tex_alloc_bos(struct ilo_texture *tex)
    414 {
    415    if (!tex->imported && !tex_create_bo(tex))
    416       return false;
    417 
    418    switch (tex->image.aux.type) {
    419    case ILO_IMAGE_AUX_HIZ:
    420       if (!tex_create_hiz(tex))
    421          return false;
    422       break;
    423    case ILO_IMAGE_AUX_MCS:
    424       if (!tex_create_mcs(tex))
    425          return false;
    426       break;
    427    default:
    428       break;
    429    }
    430 
    431    return true;
    432 }
    433 
    434 static struct intel_bo *
    435 tex_import_handle(struct ilo_texture *tex,
    436                   const struct winsys_handle *handle,
    437                   struct ilo_image_info *info)
    438 {
    439    struct ilo_screen *is = ilo_screen(tex->base.screen);
    440    const struct pipe_resource *templ = &tex->base;
    441    const char *name = resource_get_bo_name(&tex->base);
    442    enum intel_tiling_mode tiling;
    443    unsigned long pitch;
    444    struct intel_bo *bo;
    445 
    446    bo = intel_winsys_import_handle(is->dev.winsys, name, handle,
    447          tex->image.bo_height, &tiling, &pitch);
    448    /* modify image info */
    449    if (bo) {
    450       const uint8_t valid_tilings = 1 << winsys_to_surface_tiling(tiling);
    451 
    452       if (info->valid_tilings && !(info->valid_tilings & valid_tilings)) {
    453          intel_bo_unref(bo);
    454          return NULL;
    455       }
    456 
    457       info->valid_tilings = valid_tilings;
    458       info->force_bo_stride = pitch;
    459 
    460       /* assume imported RTs are also scanouts */
    461       if (!info->bind_scanout)
    462          info->bind_scanout = (templ->usage & PIPE_BIND_RENDER_TARGET);
    463    }
    464 
    465    return bo;
    466 }
    467 
    468 static bool
    469 tex_init_image(struct ilo_texture *tex,
    470                const struct winsys_handle *handle,
    471                bool *separate_stencil)
    472 {
    473    struct ilo_screen *is = ilo_screen(tex->base.screen);
    474    const struct pipe_resource *templ = &tex->base;
    475    struct ilo_image *img = &tex->image;
    476    struct intel_bo *imported_bo = NULL;
    477    struct ilo_image_info info;
    478 
    479    tex->image_format = resource_get_image_format(templ,
    480          &is->dev, separate_stencil);
    481    resource_get_image_info(templ, &is->dev, tex->image_format, &info);
    482 
    483    if (handle) {
    484       imported_bo = tex_import_handle(tex, handle, &info);
    485       if (!imported_bo)
    486          return false;
    487    }
    488 
    489    if (!ilo_image_init(img, &is->dev, &info)) {
    490       intel_bo_unref(imported_bo);
    491       return false;
    492    }
    493 
    494    /*
    495     * HiZ requires 8x4 alignment and some levels might need HiZ disabled.  It
    496     * is generally fine except on Gen6, where HiZ and separate stencil must be
    497     * enabled together.  For PIPE_FORMAT_Z24X8_UNORM with separate stencil, we
    498     * can live with stencil values being interleaved for levels where HiZ is
    499     * disabled.  But it is not the case for PIPE_FORMAT_Z32_FLOAT with
    500     * separate stencil.  If HiZ was disabled for a level, we had to change the
    501     * format to PIPE_FORMAT_Z32_FLOAT_S8X24_UINT for the level and that format
    502     * had a different bpp.  In other words, HiZ has to be available for all
    503     * levels.
    504     */
    505    if (ilo_dev_gen(&is->dev) == ILO_GEN(6) &&
    506        templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT &&
    507        tex->image_format == PIPE_FORMAT_Z32_FLOAT &&
    508        img->aux.enables != (1 << templ->last_level)) {
    509       tex->image_format = templ->format;
    510       info.format = pipe_to_surface_format(&is->dev, tex->image_format);
    511       info.interleaved_stencil = true;
    512 
    513       memset(img, 0, sizeof(*img));
    514       if (!ilo_image_init(img, &is->dev, &info)) {
    515          intel_bo_unref(imported_bo);
    516          return false;
    517       }
    518    }
    519 
    520    if (img->bo_height > ilo_max_resource_size / img->bo_stride ||
    521        !ilo_vma_init(&tex->vma, &is->dev, img->bo_stride * img->bo_height,
    522           4096)) {
    523       intel_bo_unref(imported_bo);
    524       return false;
    525    }
    526 
    527    if (imported_bo) {
    528       ilo_vma_set_bo(&tex->vma, &is->dev, imported_bo, 0);
    529       tex->imported = true;
    530    }
    531 
    532    if (templ->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) {
    533       /* require on-the-fly tiling/untiling or format conversion */
    534       if (img->tiling == GEN8_TILING_W || *separate_stencil ||
    535           tex->image_format != templ->format)
    536          return false;
    537    }
    538 
    539    if (!tex_alloc_slices(tex))
    540       return false;
    541 
    542    return true;
    543 }
    544 
    545 static struct pipe_resource *
    546 tex_create(struct pipe_screen *screen,
    547            const struct pipe_resource *templ,
    548            const struct winsys_handle *handle)
    549 {
    550    struct ilo_texture *tex;
    551    bool separate_stencil;
    552 
    553    tex = CALLOC_STRUCT(ilo_texture);
    554    if (!tex)
    555       return NULL;
    556 
    557    tex->base = *templ;
    558    tex->base.screen = screen;
    559    pipe_reference_init(&tex->base.reference, 1);
    560 
    561    if (!tex_init_image(tex, handle, &separate_stencil)) {
    562       FREE(tex);
    563       return NULL;
    564    }
    565 
    566    if (!tex_alloc_bos(tex) ||
    567        (separate_stencil && !tex_create_separate_stencil(tex))) {
    568       tex_destroy(tex);
    569       return NULL;
    570    }
    571 
    572    return &tex->base;
    573 }
    574 
    575 static bool
    576 tex_get_handle(struct ilo_texture *tex, struct winsys_handle *handle)
    577 {
    578    struct ilo_screen *is = ilo_screen(tex->base.screen);
    579    enum intel_tiling_mode tiling;
    580    int err;
    581 
    582    /* must match what tex_create_bo() sets */
    583    if (tex->image.tiling == GEN8_TILING_W)
    584       tiling = INTEL_TILING_NONE;
    585    else
    586       tiling = surface_to_winsys_tiling(tex->image.tiling);
    587 
    588    err = intel_winsys_export_handle(is->dev.winsys, tex->vma.bo, tiling,
    589          tex->image.bo_stride, tex->image.bo_height, handle);
    590 
    591    return !err;
    592 }
    593 
    594 static bool
    595 buf_create_bo(struct ilo_buffer_resource *buf)
    596 {
    597    struct ilo_screen *is = ilo_screen(buf->base.screen);
    598    const char *name = resource_get_bo_name(&buf->base);
    599    const bool cpu_init = resource_get_cpu_init(&buf->base);
    600    struct intel_bo *bo;
    601 
    602    bo = intel_winsys_alloc_bo(is->dev.winsys, name, buf->bo_size, cpu_init);
    603    if (!bo)
    604       return false;
    605 
    606    intel_bo_unref(buf->vma.bo);
    607    ilo_vma_set_bo(&buf->vma, &is->dev, bo, 0);
    608 
    609    return true;
    610 }
    611 
    612 static void
    613 buf_destroy(struct ilo_buffer_resource *buf)
    614 {
    615    intel_bo_unref(buf->vma.bo);
    616    FREE(buf);
    617 }
    618 
    619 static struct pipe_resource *
    620 buf_create(struct pipe_screen *screen, const struct pipe_resource *templ)
    621 {
    622    const struct ilo_screen *is = ilo_screen(screen);
    623    struct ilo_buffer_resource *buf;
    624    uint32_t alignment;
    625    unsigned size;
    626 
    627    buf = CALLOC_STRUCT(ilo_buffer_resource);
    628    if (!buf)
    629       return NULL;
    630 
    631    buf->base = *templ;
    632    buf->base.screen = screen;
    633    pipe_reference_init(&buf->base.reference, 1);
    634 
    635    size = templ->width0;
    636 
    637    /*
    638     * As noted in ilo_format_translate(), we treat some 3-component formats as
    639     * 4-component formats to work around hardware limitations.  Imagine the
    640     * case where the vertex buffer holds a single PIPE_FORMAT_R16G16B16_FLOAT
    641     * vertex, and buf->bo_size is 6.  The hardware would fail to fetch it at
    642     * boundary check because the vertex buffer is expected to hold a
    643     * PIPE_FORMAT_R16G16B16A16_FLOAT vertex and that takes at least 8 bytes.
    644     *
    645     * For the workaround to work, we should add 2 to the bo size.  But that
    646     * would waste a page when the bo size is already page aligned.  Let's
    647     * round it to page size for now and revisit this when needed.
    648     */
    649    if ((templ->bind & PIPE_BIND_VERTEX_BUFFER) &&
    650        ilo_dev_gen(&is->dev) < ILO_GEN(7.5))
    651       size = align(size, 4096);
    652 
    653    if (templ->bind & PIPE_BIND_VERTEX_BUFFER)
    654       size = ilo_state_vertex_buffer_size(&is->dev, size, &alignment);
    655    if (templ->bind & PIPE_BIND_INDEX_BUFFER)
    656       size = ilo_state_index_buffer_size(&is->dev, size, &alignment);
    657    if (templ->bind & PIPE_BIND_STREAM_OUTPUT)
    658       size = ilo_state_sol_buffer_size(&is->dev, size, &alignment);
    659 
    660    buf->bo_size = size;
    661    ilo_vma_init(&buf->vma, &is->dev, buf->bo_size, 4096);
    662 
    663    if (buf->bo_size < templ->width0 || buf->bo_size > ilo_max_resource_size ||
    664        !buf_create_bo(buf)) {
    665       FREE(buf);
    666       return NULL;
    667    }
    668 
    669    return &buf->base;
    670 }
    671 
    672 static boolean
    673 ilo_can_create_resource(struct pipe_screen *screen,
    674                         const struct pipe_resource *templ)
    675 {
    676    struct ilo_screen *is = ilo_screen(screen);
    677    enum pipe_format image_format;
    678    struct ilo_image_info info;
    679    struct ilo_image img;
    680 
    681    if (templ->target == PIPE_BUFFER)
    682       return (templ->width0 <= ilo_max_resource_size);
    683 
    684    image_format = resource_get_image_format(templ, &is->dev, NULL);
    685    resource_get_image_info(templ, &is->dev, image_format, &info);
    686 
    687    memset(&img, 0, sizeof(img));
    688    ilo_image_init(&img, &ilo_screen(screen)->dev, &info);
    689 
    690    /* as in tex_init_image() */
    691    if (ilo_dev_gen(&is->dev) == ILO_GEN(6) &&
    692        templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT &&
    693        image_format == PIPE_FORMAT_Z32_FLOAT &&
    694        img.aux.enables != (1 << templ->last_level)) {
    695       info.format = pipe_to_surface_format(&is->dev, templ->format);
    696       info.interleaved_stencil = true;
    697       memset(&img, 0, sizeof(img));
    698       ilo_image_init(&img, &ilo_screen(screen)->dev, &info);
    699    }
    700 
    701    return (img.bo_height <= ilo_max_resource_size / img.bo_stride);
    702 }
    703 
    704 static struct pipe_resource *
    705 ilo_resource_create(struct pipe_screen *screen,
    706                     const struct pipe_resource *templ)
    707 {
    708    if (templ->target == PIPE_BUFFER)
    709       return buf_create(screen, templ);
    710    else
    711       return tex_create(screen, templ, NULL);
    712 }
    713 
    714 static struct pipe_resource *
    715 ilo_resource_from_handle(struct pipe_screen *screen,
    716                          const struct pipe_resource *templ,
    717                          struct winsys_handle *handle,
    718                          unsigned usage)
    719 {
    720    if (templ->target == PIPE_BUFFER)
    721       return NULL;
    722    else
    723       return tex_create(screen, templ, handle);
    724 }
    725 
    726 static boolean
    727 ilo_resource_get_handle(struct pipe_screen *screen,
    728                         struct pipe_context *ctx,
    729                         struct pipe_resource *res,
    730                         struct winsys_handle *handle,
    731                         unsigned usage)
    732 {
    733    if (res->target == PIPE_BUFFER)
    734       return false;
    735    else
    736       return tex_get_handle(ilo_texture(res), handle);
    737 
    738 }
    739 
    740 static void
    741 ilo_resource_destroy(struct pipe_screen *screen,
    742                      struct pipe_resource *res)
    743 {
    744    if (res->target == PIPE_BUFFER)
    745       buf_destroy((struct ilo_buffer_resource *) res);
    746    else
    747       tex_destroy(ilo_texture(res));
    748 }
    749 
    750 /**
    751  * Initialize resource-related functions.
    752  */
    753 void
    754 ilo_init_resource_functions(struct ilo_screen *is)
    755 {
    756    is->base.can_create_resource = ilo_can_create_resource;
    757    is->base.resource_create = ilo_resource_create;
    758    is->base.resource_from_handle = ilo_resource_from_handle;
    759    is->base.resource_get_handle = ilo_resource_get_handle;
    760    is->base.resource_destroy = ilo_resource_destroy;
    761 }
    762 
    763 bool
    764 ilo_resource_rename_bo(struct pipe_resource *res)
    765 {
    766    if (res->target == PIPE_BUFFER) {
    767       return buf_create_bo((struct ilo_buffer_resource *) res);
    768    } else {
    769       struct ilo_texture *tex = ilo_texture(res);
    770 
    771       /* an imported texture cannot be renamed */
    772       if (tex->imported)
    773          return false;
    774 
    775       return tex_create_bo(tex);
    776    }
    777 }
    778