intel/fs: Add support for a new load_reloc_const intrinsic
[mesa.git] / src / intel / isl / isl_storage_image.c
index 773160432b9bd5c86b311fbbdb3032928f9a80fa..f8bb527535869ac733cef13c05ed06943571533c 100644 (file)
@@ -21,8 +21,8 @@
  * IN THE SOFTWARE.
  */
 
-#include "isl.h"
-#include "brw_compiler.h"
+#include "isl_priv.h"
+#include "compiler/brw_compiler.h"
 
 bool
 isl_is_storage_image_format(enum isl_format format)
@@ -76,7 +76,7 @@ isl_is_storage_image_format(enum isl_format format)
 }
 
 enum isl_format
-isl_lower_storage_image_format(const struct isl_device *dev,
+isl_lower_storage_image_format(const struct gen_device_info *devinfo,
                                enum isl_format format)
 {
    switch (format) {
@@ -88,9 +88,16 @@ isl_lower_storage_image_format(const struct isl_device *dev,
    case ISL_FORMAT_R32G32B32A32_FLOAT:
    case ISL_FORMAT_R32_UINT:
    case ISL_FORMAT_R32_SINT:
-   case ISL_FORMAT_R32_FLOAT:
       return format;
 
+   /* The Skylake PRM's "Surface Formats" section says:
+    *
+    *   "The surface format for the typed atomic integer operations must
+    *    be R32_UINT or R32_SINT."
+    */
+   case ISL_FORMAT_R32_FLOAT:
+      return ISL_FORMAT_R32_UINT;
+
    /* From HSW to BDW the only 64bpp format supported for typed access is
     * RGBA_UINT16.  IVB falls back to untyped.
     */
@@ -100,8 +107,8 @@ isl_lower_storage_image_format(const struct isl_device *dev,
    case ISL_FORMAT_R32G32_UINT:
    case ISL_FORMAT_R32G32_SINT:
    case ISL_FORMAT_R32G32_FLOAT:
-      return (ISL_DEV_GEN(dev) >= 9 ? format :
-              ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 9 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R16G16B16A16_UINT :
               ISL_FORMAT_R32G32_UINT);
 
@@ -117,31 +124,31 @@ isl_lower_storage_image_format(const struct isl_device *dev,
     */
    case ISL_FORMAT_R8G8B8A8_UINT:
    case ISL_FORMAT_R8G8B8A8_SINT:
-      return (ISL_DEV_GEN(dev) >= 9 ? format :
-              ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 9 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R8G8B8A8_UINT : ISL_FORMAT_R32_UINT);
 
    case ISL_FORMAT_R16G16_UINT:
    case ISL_FORMAT_R16G16_SINT:
    case ISL_FORMAT_R16G16_FLOAT:
-      return (ISL_DEV_GEN(dev) >= 9 ? format :
-              ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 9 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R16G16_UINT : ISL_FORMAT_R32_UINT);
 
    case ISL_FORMAT_R8G8_UINT:
    case ISL_FORMAT_R8G8_SINT:
-      return (ISL_DEV_GEN(dev) >= 9 ? format :
-              ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 9 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R8G8_UINT : ISL_FORMAT_R16_UINT);
 
    case ISL_FORMAT_R16_UINT:
    case ISL_FORMAT_R16_FLOAT:
    case ISL_FORMAT_R16_SINT:
-      return (ISL_DEV_GEN(dev) >= 9 ? format : ISL_FORMAT_R16_UINT);
+      return (devinfo->gen >= 9 ? format : ISL_FORMAT_R16_UINT);
 
    case ISL_FORMAT_R8_UINT:
    case ISL_FORMAT_R8_SINT:
-      return (ISL_DEV_GEN(dev) >= 9 ? format : ISL_FORMAT_R8_UINT);
+      return (devinfo->gen >= 9 ? format : ISL_FORMAT_R8_UINT);
 
    /* Neither the 2/10/10/10 nor the 11/11/10 packed formats are supported
     * by the hardware.
@@ -154,35 +161,164 @@ isl_lower_storage_image_format(const struct isl_device *dev,
    /* No normalized fixed-point formats are supported by the hardware. */
    case ISL_FORMAT_R16G16B16A16_UNORM:
    case ISL_FORMAT_R16G16B16A16_SNORM:
-      return (ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 11 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R16G16B16A16_UINT :
               ISL_FORMAT_R32G32_UINT);
 
    case ISL_FORMAT_R8G8B8A8_UNORM:
    case ISL_FORMAT_R8G8B8A8_SNORM:
-      return (ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 11 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R8G8B8A8_UINT : ISL_FORMAT_R32_UINT);
 
    case ISL_FORMAT_R16G16_UNORM:
    case ISL_FORMAT_R16G16_SNORM:
-      return (ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 11 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R16G16_UINT : ISL_FORMAT_R32_UINT);
 
    case ISL_FORMAT_R8G8_UNORM:
    case ISL_FORMAT_R8G8_SNORM:
-      return (ISL_DEV_GEN(dev) >= 8 || dev->info->is_haswell ?
+      return (devinfo->gen >= 11 ? format :
+              devinfo->gen >= 8 || devinfo->is_haswell ?
               ISL_FORMAT_R8G8_UINT : ISL_FORMAT_R16_UINT);
 
    case ISL_FORMAT_R16_UNORM:
    case ISL_FORMAT_R16_SNORM:
-      return ISL_FORMAT_R16_UINT;
+      return (devinfo->gen >= 11 ? format : ISL_FORMAT_R16_UINT);
 
    case ISL_FORMAT_R8_UNORM:
    case ISL_FORMAT_R8_SNORM:
-      return ISL_FORMAT_R8_UINT;
+      return (devinfo->gen >= 11 ? format : ISL_FORMAT_R8_UINT);
 
    default:
       assert(!"Unknown image format");
       return ISL_FORMAT_UNSUPPORTED;
    }
 }
+
+bool
+isl_has_matching_typed_storage_image_format(const struct gen_device_info *devinfo,
+                                            enum isl_format fmt)
+{
+   if (devinfo->gen >= 9) {
+      return true;
+   } else if (devinfo->gen >= 8 || devinfo->is_haswell) {
+      return isl_format_get_layout(fmt)->bpb <= 64;
+   } else {
+      return isl_format_get_layout(fmt)->bpb <= 32;
+   }
+}
+
+static const struct brw_image_param image_param_defaults = {
+   /* Set the swizzling shifts to all-ones to effectively disable
+    * swizzling -- See emit_address_calculation() in
+    * brw_fs_surface_builder.cpp for a more detailed explanation of
+    * these parameters.
+    */
+   .swizzling = { 0xff, 0xff },
+};
+
+void
+isl_surf_fill_image_param(const struct isl_device *dev,
+                          struct brw_image_param *param,
+                          const struct isl_surf *surf,
+                          const struct isl_view *view)
+{
+   *param = image_param_defaults;
+
+   if (surf->dim != ISL_SURF_DIM_3D) {
+      assert(view->base_array_layer + view->array_len <=
+             surf->logical_level0_px.array_len);
+   }
+   param->size[0] = isl_minify(surf->logical_level0_px.w, view->base_level);
+   param->size[1] = surf->dim == ISL_SURF_DIM_1D ?
+                    view->array_len :
+                    isl_minify(surf->logical_level0_px.h, view->base_level);
+   param->size[2] = surf->dim == ISL_SURF_DIM_2D ?
+                    view->array_len :
+                    isl_minify(surf->logical_level0_px.d, view->base_level);
+
+   isl_surf_get_image_offset_el(surf, view->base_level,
+                                surf->dim == ISL_SURF_DIM_3D ?
+                                   0 : view->base_array_layer,
+                                surf->dim == ISL_SURF_DIM_3D ?
+                                   view->base_array_layer : 0,
+                                &param->offset[0],  &param->offset[1]);
+
+   const int cpp = isl_format_get_layout(surf->format)->bpb / 8;
+   param->stride[0] = cpp;
+   param->stride[1] = surf->row_pitch_B / cpp;
+
+   const struct isl_extent3d image_align_sa =
+      isl_surf_get_image_alignment_sa(surf);
+   if (ISL_DEV_GEN(dev) < 9 && surf->dim == ISL_SURF_DIM_3D) {
+      param->stride[2] = isl_align_npot(param->size[0], image_align_sa.w);
+      param->stride[3] = isl_align_npot(param->size[1], image_align_sa.h);
+   } else {
+      param->stride[2] = 0;
+      param->stride[3] = isl_surf_get_array_pitch_el_rows(surf);
+   }
+
+   switch (surf->tiling) {
+   case ISL_TILING_LINEAR:
+      /* image_param_defaults is good enough */
+      break;
+
+   case ISL_TILING_X:
+      /* An X tile is a rectangular block of 512x8 bytes. */
+      param->tiling[0] = isl_log2u(512 / cpp);
+      param->tiling[1] = isl_log2u(8);
+
+      if (dev->has_bit6_swizzling) {
+         /* Right shifts required to swizzle bits 9 and 10 of the memory
+          * address with bit 6.
+          */
+         param->swizzling[0] = 3;
+         param->swizzling[1] = 4;
+      }
+      break;
+
+   case ISL_TILING_Y0:
+      /* The layout of a Y-tiled surface in memory isn't really fundamentally
+       * different to the layout of an X-tiled surface, we simply pretend that
+       * the surface is broken up in a number of smaller 16Bx32 tiles, each
+       * one arranged in X-major order just like is the case for X-tiling.
+       */
+      param->tiling[0] = isl_log2u(16 / cpp);
+      param->tiling[1] = isl_log2u(32);
+
+      if (dev->has_bit6_swizzling) {
+         /* Right shift required to swizzle bit 9 of the memory address with
+          * bit 6.
+          */
+         param->swizzling[0] = 3;
+         param->swizzling[1] = 0xff;
+      }
+      break;
+
+   default:
+      assert(!"Unhandled storage image tiling");
+   }
+
+   /* 3D textures are arranged in 2D in memory with 2^lod slices per row.  The
+    * address calculation algorithm (emit_address_calculation() in
+    * brw_fs_surface_builder.cpp) handles this as a sort of tiling with
+    * modulus equal to the LOD.
+    */
+   param->tiling[2] = (ISL_DEV_GEN(dev) < 9 && surf->dim == ISL_SURF_DIM_3D ?
+                       view->base_level : 0);
+}
+
+void
+isl_buffer_fill_image_param(const struct isl_device *dev,
+                            struct brw_image_param *param,
+                            enum isl_format format,
+                            uint64_t size)
+{
+   *param = image_param_defaults;
+
+   param->stride[0] = isl_format_get_layout(format)->bpb / 8;
+   param->size[0] = size / param->stride[0];
+}