[Mesa-dev] [PATCH 2/2] anv: Add support for shaderStorageImageWriteWithoutFormat

Lionel Landwerlin lionel.g.landwerlin at intel.com
Mon Feb 13 17:28:43 UTC 2017


On 09/02/17 16:06, Alex Smith wrote:
> This allows shaders to write to storage images declared with unknown
> format if they are decorated with NonReadable ("writeonly" in GLSL).
>
> Previously an image view would always use a lowered format for its
> surface state, however when a shader declares a write-only image, we
> should use the real format. Since we don't know at view creation time
> whether it will be used with only write-only images in shaders, create
> two surface states using both the original format and the lowered
> format. When emitting the binding table, choose between the states
> based on whether the image is declared write-only in the shader.
>
> Tested on both Sascha Willems' computeshader sample (with the original
> shaders and ones modified to declare images writeonly and omit their
> format qualifiers) and on our own shaders for which we need support
> for this.
>
> Signed-off-by: Alex Smith <asmith at feralinteractive.com>
> ---
>   src/intel/vulkan/anv_device.c                    |  2 +-
>   src/intel/vulkan/anv_image.c                     | 31 +++++++++++++++++++++++-
>   src/intel/vulkan/anv_nir_apply_pipeline_layout.c | 10 +++++---
>   src/intel/vulkan/anv_pipeline.c                  |  1 +
>   src/intel/vulkan/anv_private.h                   | 10 +++++++-
>   src/intel/vulkan/genX_cmd_buffer.c               |  4 ++-
>   6 files changed, 50 insertions(+), 8 deletions(-)
>
> diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
> index 91ee67f..46b83a3 100644
> --- a/src/intel/vulkan/anv_device.c
> +++ b/src/intel/vulkan/anv_device.c
> @@ -484,7 +484,7 @@ void anv_GetPhysicalDeviceFeatures(
>         .shaderStorageImageExtendedFormats        = true,
>         .shaderStorageImageMultisample            = false,
>         .shaderStorageImageReadWithoutFormat      = false,
> -      .shaderStorageImageWriteWithoutFormat     = false,
> +      .shaderStorageImageWriteWithoutFormat     = true,
>         .shaderUniformBufferArrayDynamicIndexing  = true,
>         .shaderSampledImageArrayDynamicIndexing   = true,
>         .shaderStorageBufferArrayDynamicIndexing  = true,
> diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
> index e59ef4d..1aeec44 100644
> --- a/src/intel/vulkan/anv_image.c
> +++ b/src/intel/vulkan/anv_image.c
> @@ -583,13 +583,29 @@ anv_CreateImageView(VkDevice _device,
>      /* NOTE: This one needs to go last since it may stomp isl_view.format */
>      if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
>         iview->storage_surface_state = alloc_surface_state(device);
> +      iview->writeonly_storage_surface_state = alloc_surface_state(device);
>   
>         if (isl_has_matching_typed_storage_image_format(&device->info,
>                                                         format.isl_format)) {
>            struct isl_view view = iview->isl;
>            view.usage |= ISL_SURF_USAGE_STORAGE_BIT;
> +
> +         /* Write-only accesses should use the real format. */
> +         isl_surf_fill_state(&device->isl_dev,
> +                             iview->writeonly_storage_surface_state.map,
> +                             .surf = &surface->isl,
> +                             .view = &view,
> +                             .aux_surf = &image->aux_surface.isl,
> +                             .aux_usage = surf_usage,
> +                             .mocs = device->default_mocs);
> +
> +         /* Typed surface reads support a very limited subset of the shader
> +          * image formats.  Translate it into the closest format the hardware
> +          * supports.
> +          */
>            view.format = isl_lower_storage_image_format(&device->info,
>                                                         format.isl_format);
> +
>            isl_surf_fill_state(&device->isl_dev,
>                                iview->storage_surface_state.map,
>                                .surf = &surface->isl,
> @@ -602,16 +618,24 @@ anv_CreateImageView(VkDevice _device,
>                                          ISL_FORMAT_RAW,
>                                          iview->offset,
>                                          iview->bo->size - iview->offset, 1);
> +         anv_fill_buffer_surface_state(device,
> +                                       iview->writeonly_storage_surface_state,
> +                                       ISL_FORMAT_RAW,
> +                                       iview->offset,
> +                                       iview->bo->size - iview->offset, 1);
>         }
>   
>         isl_surf_fill_image_param(&device->isl_dev,
>                                   &iview->storage_image_param,
>                                   &surface->isl, &iview->isl);
>   
> -      if (!device->info.has_llc)
> +      if (!device->info.has_llc) {
>            anv_state_clflush(iview->storage_surface_state);
> +         anv_state_clflush(iview->writeonly_storage_surface_state);
> +      }
>      } else {
>         iview->storage_surface_state.alloc_size = 0;
> +      iview->writeonly_storage_surface_state.alloc_size = 0;
>      }
>   
>      *pView = anv_image_view_to_handle(iview);
> @@ -639,6 +663,11 @@ anv_DestroyImageView(VkDevice _device, VkImageView _iview,
>                             iview->storage_surface_state);
>      }
>   
> +   if (iview->writeonly_storage_surface_state.alloc_size > 0) {
> +      anv_state_pool_free(&device->surface_state_pool,
> +                          iview->writeonly_storage_surface_state);
> +   }
> +
>      vk_free2(&device->alloc, pAllocator, iview);
>   }
>   
> diff --git a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
> index 8846c2e..296fd05 100644
> --- a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
> +++ b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
> @@ -351,9 +351,6 @@ anv_nir_apply_pipeline_layout(struct anv_pipeline *pipeline,
>            continue;
>   
>         enum glsl_sampler_dim dim = glsl_get_sampler_dim(var->interface_type);
> -      if (dim != GLSL_SAMPLER_DIM_SUBPASS &&
> -          dim != GLSL_SAMPLER_DIM_SUBPASS_MS)
> -         continue;
>   
>         const uint32_t set = var->data.descriptor_set;
>         const uint32_t binding = var->data.binding;
> @@ -369,7 +366,12 @@ anv_nir_apply_pipeline_layout(struct anv_pipeline *pipeline,
>            assert(pipe_binding[i].set == set);
>            assert(pipe_binding[i].binding == binding);
>            assert(pipe_binding[i].index == i);
> -         pipe_binding[i].input_attachment_index = var->data.index + i;
> +
> +         if (dim != GLSL_SAMPLER_DIM_SUBPASS &&
> +             dim != GLSL_SAMPLER_DIM_SUBPASS_MS)

This condition is incorrect, now that you moved it here, it should be

if (dim == GLSL_SAMPLER_DIM_SUBPASS ||
     dim == GLSL_SAMPLER_DIM_SUBPASS_MS)

With that fixed, this patch is :

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>

> +            pipe_binding[i].input_attachment_index = var->data.index + i;
> +
> +         pipe_binding[i].write_only = var->data.image.write_only;
>         }
>      }
>   
> diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
> index ca3823c..4410103 100644
> --- a/src/intel/vulkan/anv_pipeline.c
> +++ b/src/intel/vulkan/anv_pipeline.c
> @@ -128,6 +128,7 @@ anv_shader_compile_to_nir(struct anv_device *device,
>         .float64 = device->instance->physicalDevice.info.gen >= 8,
>         .tessellation = true,
>         .draw_parameters = true,
> +      .image_write_without_format = true,
>      };
>   
>      nir_function *entry_point =
> diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
> index 51e85c7..8db851a 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -953,6 +953,9 @@ struct anv_pipeline_binding {
>   
>      /* Input attachment index (relative to the subpass) */
>      uint8_t input_attachment_index;
> +
> +   /* For a storage image, whether it is write-only */
> +   bool write_only;
>   };
>   
>   struct anv_pipeline_layout {
> @@ -1683,8 +1686,13 @@ struct anv_image_view {
>      /** RENDER_SURFACE_STATE when using image as a sampler surface. */
>      struct anv_state sampler_surface_state;
>   
> -   /** RENDER_SURFACE_STATE when using image as a storage image. */
> +   /**
> +    * RENDER_SURFACE_STATE when using image as a storage image. Separate states
> +    * for write-only and readable, using the real format for write-only and the
> +    * lowered format for readable.
> +    */
>      struct anv_state storage_surface_state;
> +   struct anv_state writeonly_storage_surface_state;
>   
>      struct brw_image_param storage_image_param;
>   };
> diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
> index 8db26e9..b80159b 100644
> --- a/src/intel/vulkan/genX_cmd_buffer.c
> +++ b/src/intel/vulkan/genX_cmd_buffer.c
> @@ -1211,7 +1211,9 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
>            break;
>   
>         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
> -         surface_state = desc->image_view->storage_surface_state;
> +         surface_state = (binding->write_only)
> +            ? desc->image_view->writeonly_storage_surface_state
> +            : desc->image_view->storage_surface_state;
>            assert(surface_state.alloc_size);
>            add_image_view_relocs(cmd_buffer, desc->image_view,
>                                  desc->image_view->image->aux_usage,




More information about the mesa-dev mailing list