Home | History | Annotate | Download | only in isl
      1 /*
      2  * Copyright 2015 Intel Corporation
      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 "isl_priv.h"
     25 #include "brw_compiler.h"
     26 
     27 bool
     28 isl_is_storage_image_format(enum isl_format format)
     29 {
     30    /* XXX: Maybe we should put this in the CSV? */
     31 
     32    switch (format) {
     33    case ISL_FORMAT_R32G32B32A32_UINT:
     34    case ISL_FORMAT_R32G32B32A32_SINT:
     35    case ISL_FORMAT_R32G32B32A32_FLOAT:
     36    case ISL_FORMAT_R32_UINT:
     37    case ISL_FORMAT_R32_SINT:
     38    case ISL_FORMAT_R32_FLOAT:
     39    case ISL_FORMAT_R16G16B16A16_UINT:
     40    case ISL_FORMAT_R16G16B16A16_SINT:
     41    case ISL_FORMAT_R16G16B16A16_FLOAT:
     42    case ISL_FORMAT_R32G32_UINT:
     43    case ISL_FORMAT_R32G32_SINT:
     44    case ISL_FORMAT_R32G32_FLOAT:
     45    case ISL_FORMAT_R8G8B8A8_UINT:
     46    case ISL_FORMAT_R8G8B8A8_SINT:
     47    case ISL_FORMAT_R16G16_UINT:
     48    case ISL_FORMAT_R16G16_SINT:
     49    case ISL_FORMAT_R16G16_FLOAT:
     50    case ISL_FORMAT_R8G8_UINT:
     51    case ISL_FORMAT_R8G8_SINT:
     52    case ISL_FORMAT_R16_UINT:
     53    case ISL_FORMAT_R16_FLOAT:
     54    case ISL_FORMAT_R16_SINT:
     55    case ISL_FORMAT_R8_UINT:
     56    case ISL_FORMAT_R8_SINT:
     57    case ISL_FORMAT_R10G10B10A2_UINT:
     58    case ISL_FORMAT_R10G10B10A2_UNORM:
     59    case ISL_FORMAT_R11G11B10_FLOAT:
     60    case ISL_FORMAT_R16G16B16A16_UNORM:
     61    case ISL_FORMAT_R16G16B16A16_SNORM:
     62    case ISL_FORMAT_R8G8B8A8_UNORM:
     63    case ISL_FORMAT_R8G8B8A8_SNORM:
     64    case ISL_FORMAT_R16G16_UNORM:
     65    case ISL_FORMAT_R16G16_SNORM:
     66    case ISL_FORMAT_R8G8_UNORM:
     67    case ISL_FORMAT_R8G8_SNORM:
     68    case ISL_FORMAT_R16_UNORM:
     69    case ISL_FORMAT_R16_SNORM:
     70    case ISL_FORMAT_R8_UNORM:
     71    case ISL_FORMAT_R8_SNORM:
     72       return true;
     73    default:
     74       return false;
     75    }
     76 }
     77 
     78 enum isl_format
     79 isl_lower_storage_image_format(const struct gen_device_info *devinfo,
     80                                enum isl_format format)
     81 {
     82    switch (format) {
     83    /* These are never lowered.  Up to BDW we'll have to fall back to untyped
     84     * surface access for 128bpp formats.
     85     */
     86    case ISL_FORMAT_R32G32B32A32_UINT:
     87    case ISL_FORMAT_R32G32B32A32_SINT:
     88    case ISL_FORMAT_R32G32B32A32_FLOAT:
     89    case ISL_FORMAT_R32_UINT:
     90    case ISL_FORMAT_R32_SINT:
     91    case ISL_FORMAT_R32_FLOAT:
     92       return format;
     93 
     94    /* From HSW to BDW the only 64bpp format supported for typed access is
     95     * RGBA_UINT16.  IVB falls back to untyped.
     96     */
     97    case ISL_FORMAT_R16G16B16A16_UINT:
     98    case ISL_FORMAT_R16G16B16A16_SINT:
     99    case ISL_FORMAT_R16G16B16A16_FLOAT:
    100    case ISL_FORMAT_R32G32_UINT:
    101    case ISL_FORMAT_R32G32_SINT:
    102    case ISL_FORMAT_R32G32_FLOAT:
    103       return (devinfo->gen >= 9 ? format :
    104               devinfo->gen >= 8 || devinfo->is_haswell ?
    105               ISL_FORMAT_R16G16B16A16_UINT :
    106               ISL_FORMAT_R32G32_UINT);
    107 
    108    /* Up to BDW no SINT or FLOAT formats of less than 32 bits per component
    109     * are supported.  IVB doesn't support formats with more than one component
    110     * for typed access.  For 8 and 16 bpp formats IVB relies on the
    111     * undocumented behavior that typed reads from R_UINT8 and R_UINT16
    112     * surfaces actually do a 32-bit misaligned read.  The alternative would be
    113     * to use two surface state entries with different formats for each image,
    114     * one for reading (using R_UINT32) and another one for writing (using
    115     * R_UINT8 or R_UINT16), but that would complicate the shaders we generate
    116     * even more.
    117     */
    118    case ISL_FORMAT_R8G8B8A8_UINT:
    119    case ISL_FORMAT_R8G8B8A8_SINT:
    120       return (devinfo->gen >= 9 ? format :
    121               devinfo->gen >= 8 || devinfo->is_haswell ?
    122               ISL_FORMAT_R8G8B8A8_UINT : ISL_FORMAT_R32_UINT);
    123 
    124    case ISL_FORMAT_R16G16_UINT:
    125    case ISL_FORMAT_R16G16_SINT:
    126    case ISL_FORMAT_R16G16_FLOAT:
    127       return (devinfo->gen >= 9 ? format :
    128               devinfo->gen >= 8 || devinfo->is_haswell ?
    129               ISL_FORMAT_R16G16_UINT : ISL_FORMAT_R32_UINT);
    130 
    131    case ISL_FORMAT_R8G8_UINT:
    132    case ISL_FORMAT_R8G8_SINT:
    133       return (devinfo->gen >= 9 ? format :
    134               devinfo->gen >= 8 || devinfo->is_haswell ?
    135               ISL_FORMAT_R8G8_UINT : ISL_FORMAT_R16_UINT);
    136 
    137    case ISL_FORMAT_R16_UINT:
    138    case ISL_FORMAT_R16_FLOAT:
    139    case ISL_FORMAT_R16_SINT:
    140       return (devinfo->gen >= 9 ? format : ISL_FORMAT_R16_UINT);
    141 
    142    case ISL_FORMAT_R8_UINT:
    143    case ISL_FORMAT_R8_SINT:
    144       return (devinfo->gen >= 9 ? format : ISL_FORMAT_R8_UINT);
    145 
    146    /* Neither the 2/10/10/10 nor the 11/11/10 packed formats are supported
    147     * by the hardware.
    148     */
    149    case ISL_FORMAT_R10G10B10A2_UINT:
    150    case ISL_FORMAT_R10G10B10A2_UNORM:
    151    case ISL_FORMAT_R11G11B10_FLOAT:
    152       return ISL_FORMAT_R32_UINT;
    153 
    154    /* No normalized fixed-point formats are supported by the hardware. */
    155    case ISL_FORMAT_R16G16B16A16_UNORM:
    156    case ISL_FORMAT_R16G16B16A16_SNORM:
    157       return (devinfo->gen >= 8 || devinfo->is_haswell ?
    158               ISL_FORMAT_R16G16B16A16_UINT :
    159               ISL_FORMAT_R32G32_UINT);
    160 
    161    case ISL_FORMAT_R8G8B8A8_UNORM:
    162    case ISL_FORMAT_R8G8B8A8_SNORM:
    163       return (devinfo->gen >= 8 || devinfo->is_haswell ?
    164               ISL_FORMAT_R8G8B8A8_UINT : ISL_FORMAT_R32_UINT);
    165 
    166    case ISL_FORMAT_R16G16_UNORM:
    167    case ISL_FORMAT_R16G16_SNORM:
    168       return (devinfo->gen >= 8 || devinfo->is_haswell ?
    169               ISL_FORMAT_R16G16_UINT : ISL_FORMAT_R32_UINT);
    170 
    171    case ISL_FORMAT_R8G8_UNORM:
    172    case ISL_FORMAT_R8G8_SNORM:
    173       return (devinfo->gen >= 8 || devinfo->is_haswell ?
    174               ISL_FORMAT_R8G8_UINT : ISL_FORMAT_R16_UINT);
    175 
    176    case ISL_FORMAT_R16_UNORM:
    177    case ISL_FORMAT_R16_SNORM:
    178       return ISL_FORMAT_R16_UINT;
    179 
    180    case ISL_FORMAT_R8_UNORM:
    181    case ISL_FORMAT_R8_SNORM:
    182       return ISL_FORMAT_R8_UINT;
    183 
    184    default:
    185       assert(!"Unknown image format");
    186       return ISL_FORMAT_UNSUPPORTED;
    187    }
    188 }
    189 
    190 bool
    191 isl_has_matching_typed_storage_image_format(const struct gen_device_info *devinfo,
    192                                             enum isl_format fmt)
    193 {
    194    if (devinfo->gen >= 9) {
    195       return true;
    196    } else if (devinfo->gen >= 8 || devinfo->is_haswell) {
    197       return isl_format_get_layout(fmt)->bpb <= 64;
    198    } else {
    199       return isl_format_get_layout(fmt)->bpb <= 32;
    200    }
    201 }
    202 
    203 static const struct brw_image_param image_param_defaults = {
    204    /* Set the swizzling shifts to all-ones to effectively disable
    205     * swizzling -- See emit_address_calculation() in
    206     * brw_fs_surface_builder.cpp for a more detailed explanation of
    207     * these parameters.
    208     */
    209    .swizzling = { 0xff, 0xff },
    210 };
    211 
    212 void
    213 isl_surf_fill_image_param(const struct isl_device *dev,
    214                           struct brw_image_param *param,
    215                           const struct isl_surf *surf,
    216                           const struct isl_view *view)
    217 {
    218    *param = image_param_defaults;
    219 
    220    param->size[0] = isl_minify(surf->logical_level0_px.w, view->base_level);
    221    param->size[1] = isl_minify(surf->logical_level0_px.h, view->base_level);
    222    if (surf->dim == ISL_SURF_DIM_3D) {
    223       param->size[2] = isl_minify(surf->logical_level0_px.d, view->base_level);
    224    } else {
    225       param->size[2] = surf->logical_level0_px.array_len -
    226                        view->base_array_layer;
    227    }
    228 
    229    isl_surf_get_image_offset_el(surf, view->base_level, view->base_array_layer,
    230                                 0, &param->offset[0],  &param->offset[1]);
    231 
    232    const int cpp = isl_format_get_layout(surf->format)->bpb / 8;
    233    param->stride[0] = cpp;
    234    param->stride[1] = surf->row_pitch / cpp;
    235 
    236    const struct isl_extent3d image_align_sa =
    237       isl_surf_get_image_alignment_sa(surf);
    238    if (ISL_DEV_GEN(dev) < 9 && surf->dim == ISL_SURF_DIM_3D) {
    239       param->stride[2] = isl_align_npot(param->size[0], image_align_sa.w);
    240       param->stride[3] = isl_align_npot(param->size[1], image_align_sa.h);
    241    } else {
    242       param->stride[2] = 0;
    243       param->stride[3] = isl_surf_get_array_pitch_el_rows(surf);
    244    }
    245 
    246    switch (surf->tiling) {
    247    case ISL_TILING_LINEAR:
    248       /* image_param_defaults is good enough */
    249       break;
    250 
    251    case ISL_TILING_X:
    252       /* An X tile is a rectangular block of 512x8 bytes. */
    253       param->tiling[0] = isl_log2u(512 / cpp);
    254       param->tiling[1] = isl_log2u(8);
    255 
    256       if (dev->has_bit6_swizzling) {
    257          /* Right shifts required to swizzle bits 9 and 10 of the memory
    258           * address with bit 6.
    259           */
    260          param->swizzling[0] = 3;
    261          param->swizzling[1] = 4;
    262       }
    263       break;
    264 
    265    case ISL_TILING_Y0:
    266       /* The layout of a Y-tiled surface in memory isn't really fundamentally
    267        * different to the layout of an X-tiled surface, we simply pretend that
    268        * the surface is broken up in a number of smaller 16Bx32 tiles, each
    269        * one arranged in X-major order just like is the case for X-tiling.
    270        */
    271       param->tiling[0] = isl_log2u(16 / cpp);
    272       param->tiling[1] = isl_log2u(32);
    273 
    274       if (dev->has_bit6_swizzling) {
    275          /* Right shift required to swizzle bit 9 of the memory address with
    276           * bit 6.
    277           */
    278          param->swizzling[0] = 3;
    279          param->swizzling[1] = 0xff;
    280       }
    281       break;
    282 
    283    default:
    284       assert(!"Unhandled storage image tiling");
    285    }
    286 
    287    /* 3D textures are arranged in 2D in memory with 2^lod slices per row.  The
    288     * address calculation algorithm (emit_address_calculation() in
    289     * brw_fs_surface_builder.cpp) handles this as a sort of tiling with
    290     * modulus equal to the LOD.
    291     */
    292    param->tiling[2] = (ISL_DEV_GEN(dev) < 9 && surf->dim == ISL_SURF_DIM_3D ?
    293                        view->base_level : 0);
    294 }
    295 
    296 void
    297 isl_buffer_fill_image_param(const struct isl_device *dev,
    298                             struct brw_image_param *param,
    299                             enum isl_format format,
    300                             uint64_t size)
    301 {
    302    *param = image_param_defaults;
    303 
    304    param->stride[0] = isl_format_layouts[format].bpb / 8;
    305    param->size[0] = size / param->stride[0];
    306 }
    307