anv: Use bindless handles for images
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 12 Feb 2019 07:02:28 +0000 (01:02 -0600)
committerJason Ekstrand <jason@jlekstrand.net>
Fri, 19 Apr 2019 19:56:42 +0000 (19:56 +0000)
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/intel/compiler/brw_nir.h
src/intel/vulkan/anv_descriptor_set.c
src/intel/vulkan/anv_device.c
src/intel/vulkan/anv_nir_apply_pipeline_layout.c
src/intel/vulkan/anv_private.h

index d5f36c236b39deb66652133cf69bd8892093a72c..ba450209e516cc3e7693518a9c3324b042bb664b 100644 (file)
@@ -121,6 +121,8 @@ bool brw_nir_lower_image_load_store(nir_shader *nir,
                                     const struct gen_device_info *devinfo);
 void brw_nir_rewrite_image_intrinsic(nir_intrinsic_instr *intrin,
                                      nir_ssa_def *index);
+void brw_nir_rewrite_bindless_image_intrinsic(nir_intrinsic_instr *intrin,
+                                              nir_ssa_def *handle);
 
 bool brw_nir_lower_mem_access_bit_sizes(nir_shader *shader);
 
index 6db6021822ad480a40370118886f6e2ed2d5eb58..52e0a233b8460030b72badbab4500cea9d2b8f0f 100644 (file)
@@ -72,6 +72,8 @@ anv_descriptor_data_for_type(const struct anv_physical_device *device,
       data = ANV_DESCRIPTOR_SURFACE_STATE;
       if (device->info.gen < 9)
          data |= ANV_DESCRIPTOR_IMAGE_PARAM;
+      if (device->has_bindless_images)
+         data |= ANV_DESCRIPTOR_STORAGE_IMAGE;
       break;
 
    case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
@@ -112,6 +114,9 @@ anv_descriptor_data_size(enum anv_descriptor_data data)
    if (data & ANV_DESCRIPTOR_SAMPLED_IMAGE)
       size += sizeof(struct anv_sampled_image_descriptor);
 
+   if (data & ANV_DESCRIPTOR_STORAGE_IMAGE)
+      size += sizeof(struct anv_storage_image_descriptor);
+
    if (data & ANV_DESCRIPTOR_IMAGE_PARAM)
       size += BRW_IMAGE_PARAM_SIZE * 4;
 
@@ -178,6 +183,11 @@ anv_descriptor_data_supports_bindless(const struct anv_physical_device *pdevice,
                        pdevice->has_bindless_images;
    }
 
+   if (data & ANV_DESCRIPTOR_STORAGE_IMAGE) {
+      assert(pdevice->has_bindless_images);
+      return true;
+   }
+
    return false;
 }
 
@@ -1135,6 +1145,18 @@ anv_descriptor_set_write_image_view(struct anv_device *device,
              MAX2(1, bind_layout->max_plane_count) * sizeof(desc_data[0]));
    }
 
+   if (bind_layout->data & ANV_DESCRIPTOR_STORAGE_IMAGE) {
+      assert(!(bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM));
+      assert(image_view->n_planes == 1);
+      struct anv_storage_image_descriptor desc_data = {
+         .read_write = anv_surface_state_to_handle(
+                           image_view->planes[0].storage_surface_state.state),
+         .write_only = anv_surface_state_to_handle(
+                           image_view->planes[0].writeonly_storage_surface_state.state),
+      };
+      memcpy(desc_map, &desc_data, sizeof(desc_data));
+   }
+
    if (bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM) {
       /* Storage images can only ever have one plane */
       assert(image_view->n_planes == 1);
@@ -1175,6 +1197,17 @@ anv_descriptor_set_write_buffer_view(struct anv_device *device,
       memcpy(desc_map, &desc_data, sizeof(desc_data));
    }
 
+   if (bind_layout->data & ANV_DESCRIPTOR_STORAGE_IMAGE) {
+      assert(!(bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM));
+      struct anv_storage_image_descriptor desc_data = {
+         .read_write = anv_surface_state_to_handle(
+                           buffer_view->storage_surface_state),
+         .write_only = anv_surface_state_to_handle(
+                           buffer_view->writeonly_storage_surface_state),
+      };
+      memcpy(desc_map, &desc_data, sizeof(desc_data));
+   }
+
    if (bind_layout->data & ANV_DESCRIPTOR_IMAGE_PARAM) {
       anv_descriptor_set_write_image_param(desc_map,
                                            &buffer_view->storage_image_param);
index 44fea839f5215aa6f84cfa698f0a9be542766e15..e7793f1170fdcedc22fc9e724d6206aaf60d4454 100644 (file)
@@ -1136,6 +1136,8 @@ void anv_GetPhysicalDeviceProperties(
    const uint32_t max_samplers =
       pdevice->has_bindless_samplers ? UINT16_MAX :
       (devinfo->gen >= 8 || devinfo->is_haswell) ? 128 : 16;
+   const uint32_t max_images =
+      pdevice->has_bindless_images ? UINT16_MAX : MAX_IMAGES;
 
    /* The moment we have anything bindless, claim a high per-stage limit */
    const uint32_t max_per_stage =
@@ -1165,7 +1167,7 @@ void anv_GetPhysicalDeviceProperties(
       .maxPerStageDescriptorUniformBuffers      = 64,
       .maxPerStageDescriptorStorageBuffers      = max_ssbos,
       .maxPerStageDescriptorSampledImages       = max_textures,
-      .maxPerStageDescriptorStorageImages       = MAX_IMAGES,
+      .maxPerStageDescriptorStorageImages       = max_images,
       .maxPerStageDescriptorInputAttachments    = 64,
       .maxPerStageResources                     = max_per_stage,
       .maxDescriptorSetSamplers                 = 6 * max_samplers, /* number of stages * maxPerStageDescriptorSamplers */
@@ -1174,7 +1176,7 @@ void anv_GetPhysicalDeviceProperties(
       .maxDescriptorSetStorageBuffers           = 6 * max_ssbos,    /* number of stages * maxPerStageDescriptorStorageBuffers */
       .maxDescriptorSetStorageBuffersDynamic    = MAX_DYNAMIC_BUFFERS / 2,
       .maxDescriptorSetSampledImages            = 6 * max_textures, /* number of stages * maxPerStageDescriptorSampledImages */
-      .maxDescriptorSetStorageImages            = 6 * MAX_IMAGES,   /* number of stages * maxPerStageDescriptorStorageImages */
+      .maxDescriptorSetStorageImages            = 6 * max_images,   /* number of stages * maxPerStageDescriptorStorageImages */
       .maxDescriptorSetInputAttachments         = 256,
       .maxVertexInputAttributes                 = MAX_VBS,
       .maxVertexInputBindings                   = MAX_VBS,
index 800ed2ef3e24b2d7739f2fa5e36e093b84c21bff..846964b04e789b6ea278332a802f3fd270c93ba5 100644 (file)
@@ -677,13 +677,17 @@ lower_image_intrinsic(nir_intrinsic_instr *intrin,
                       struct apply_pipeline_layout_state *state)
 {
    nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
+   nir_variable *var = nir_deref_instr_get_variable(deref);
 
    nir_builder *b = &state->builder;
    b->cursor = nir_before_instr(&intrin->instr);
 
+   const bool use_bindless = state->pdevice->has_bindless_images;
+
    if (intrin->intrinsic == nir_intrinsic_image_deref_load_param_intel) {
       b->cursor = nir_instr_remove(&intrin->instr);
 
+      assert(!use_bindless); /* Otherwise our offsets would be wrong */
       const unsigned param = nir_intrinsic_base(intrin);
 
       nir_ssa_def *desc =
@@ -692,9 +696,14 @@ lower_image_intrinsic(nir_intrinsic_instr *intrin,
                                intrin->dest.ssa.bit_size, state);
 
       nir_ssa_def_rewrite_uses(&intrin->dest.ssa, nir_src_for_ssa(desc));
+   } else if (use_bindless) {
+      const bool write_only =
+         (var->data.image.access & ACCESS_NON_READABLE) != 0;
+      nir_ssa_def *desc =
+         build_descriptor_load(deref, 0, 2, 32, state);
+      nir_ssa_def *handle = nir_channel(b, desc, write_only ? 1 : 0);
+      nir_rewrite_image_intrinsic(intrin, handle, true);
    } else {
-      nir_variable *var = nir_deref_instr_get_variable(deref);
-
       unsigned set = var->data.descriptor_set;
       unsigned binding = var->data.binding;
       unsigned binding_offset = state->set[set].surface_offsets[binding];
index 9f525d1e21af59d0f2416b3bc1fa969520a24b3c..cb00d8c87319100cd81c5b840765d4c2958b96a3 100644 (file)
@@ -1546,6 +1546,17 @@ struct anv_sampled_image_descriptor {
    uint32_t sampler;
 };
 
+/** Struct representing a storage image descriptor */
+struct anv_storage_image_descriptor {
+   /** Bindless image handles
+    *
+    * These are expected to already be shifted such that the 20-bit
+    * SURFACE_STATE table index is in the top 20 bits.
+    */
+   uint32_t read_write;
+   uint32_t write_only;
+};
+
 /** Struct representing a address/range descriptor
  *
  * The fields of this struct correspond directly to the data layout of
@@ -1574,6 +1585,8 @@ enum anv_descriptor_data {
    ANV_DESCRIPTOR_ADDRESS_RANGE  = (1 << 5),
    /** Bindless surface handle */
    ANV_DESCRIPTOR_SAMPLED_IMAGE  = (1 << 6),
+   /** Storage image handles */
+   ANV_DESCRIPTOR_STORAGE_IMAGE  = (1 << 7),
 };
 
 struct anv_descriptor_set_binding_layout {