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

Jason Ekstrand jason at jlekstrand.net
Mon Feb 13 18:09:09 UTC 2017


On Mon, Feb 13, 2017 at 9:40 AM, Alex Smith <asmith at feralinteractive.com>
wrote:

> Hi Lionel,
>
> On 13 February 2017 at 17:28, Lionel Landwerlin <
> lionel.g.landwerlin at intel.com> wrote:
>
>> 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_surf
>>> ace_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_surf
>>> ace_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->inte
>>> rface_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>
>
>
> Oops, thanks for that, I'll fix that as well.
>

It would be good to run the CTS with at least dEQP-VK.image.load_store.* to
make sure you didn't break anything before you re-send.  If you're not
familiar with running dEQP, it's just

./deqp-vk -n 'dEQP-VK.image.load_store.*'

The quotes matter because dEQP needs to see the "*" not your shell.

--Jason


> Alex
>
>
>>
>>
>> +            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,
>>>
>>
>>
>>
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170213/92c90b12/attachment-0001.html>


More information about the mesa-dev mailing list