<div dir="ltr">Hi Jason,<br><div class="gmail_extra"><br><div class="gmail_quote">On 13 February 2017 at 16:10, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hey Alex,<br><br></div>Thanks for the patch!  I've made a couple of comments below but otherwise this looks fantastic!  I've thought a few times about how we would implement this and what you've come up with is almost exactly what I would have done. :-)<br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="gmail-h5">On Thu, Feb 9, 2017 at 8:06 AM, Alex Smith <span dir="ltr"><<a href="mailto:asmith@feralinteractive.com" target="_blank">asmith@feralinteractive.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This allows shaders to write to storage images declared with unknown<br>
format if they are decorated with NonReadable ("writeonly" in GLSL).<br>
<br>
Previously an image view would always use a lowered format for its<br>
surface state, however when a shader declares a write-only image, we<br>
should use the real format. Since we don't know at view creation time<br>
whether it will be used with only write-only images in shaders, create<br>
two surface states using both the original format and the lowered<br>
format. When emitting the binding table, choose between the states<br>
based on whether the image is declared write-only in the shader.<br>
<br>
Tested on both Sascha Willems' computeshader sample (with the original<br>
shaders and ones modified to declare images writeonly and omit their<br>
format qualifiers) and on our own shaders for which we need support<br>
for this.<br>
<br>
Signed-off-by: Alex Smith <<a href="mailto:asmith@feralinteractive.com" target="_blank">asmith@feralinteractive.com</a>><br>
---<br>
 src/intel/vulkan/anv_device.<wbr>c                    |  2 +-<br>
 src/intel/vulkan/anv_image.c                     | 31 +++++++++++++++++++++++-<br>
 src/intel/vulkan/anv_nir_appl<wbr>y_pipeline_layout.c | 10 +++++---<br>
 src/intel/vulkan/anv_<wbr>pipeline.c                  |  1 +<br>
 src/intel/vulkan/anv_private.<wbr>h                   | 10 +++++++-<br>
 src/intel/vulkan/genX_cmd_buf<wbr>fer.c               |  4 ++-<br>
 6 files changed, 50 insertions(+), 8 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_device.<wbr>c b/src/intel/vulkan/anv_device.<wbr>c<br>
index 91ee67f..46b83a3 100644<br>
--- a/src/intel/vulkan/anv_device.<wbr>c<br>
+++ b/src/intel/vulkan/anv_device.<wbr>c<br>
@@ -484,7 +484,7 @@ void anv_GetPhysicalDeviceFeatures(<br>
       .shaderStorageImageExtendedFo<wbr>rmats        = true,<br>
       .<wbr>shaderStorageImageMultisample            = false,<br>
       .shaderStorageImageReadWithou<wbr>tFormat      = false,<br>
-      .shaderStorageImageWriteWithou<wbr>tFormat     = false,<br>
+      .shaderStorageImageWriteWithou<wbr>tFormat     = true,<br>
       .shaderUniformBufferArrayDyna<wbr>micIndexing  = true,<br>
       .shaderSampledImageArrayDynam<wbr>icIndexing   = true,<br>
       .shaderStorageBufferArrayDyna<wbr>micIndexing  = true,<br>
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c<br>
index e59ef4d..1aeec44 100644<br>
--- a/src/intel/vulkan/anv_image.c<br>
+++ b/src/intel/vulkan/anv_image.c<br>
@@ -583,13 +583,29 @@ anv_CreateImageView(VkDevice _device,<br>
    /* NOTE: This one needs to go last since it may stomp isl_view.format */<br>
    if (image->usage & VK_IMAGE_USAGE_STORAGE_BIT) {<br>
       iview->storage_surface_state = alloc_surface_state(device);<br>
+      iview->writeonly_storage_surfa<wbr>ce_state = alloc_surface_state(device);<br>
<br>
       if (isl_has_matching_typed_storag<wbr>e_image_format(&device->info,<br>
                                                       format.isl_format)) {<br>
          struct isl_view view = iview->isl;<br>
          view.usage |= ISL_SURF_USAGE_STORAGE_BIT;<br>
+<br>
+         /* Write-only accesses should use the real format. */<br>
+         isl_surf_fill_state(&device-><wbr>isl_dev,<br>
+                             iview->writeonly_storage_surf<wbr>ace_state.map,<br>
+                             .surf = &surface->isl,<br>
+                             .view = &view,<br>
+                             .aux_surf = &image->aux_surface.isl,<br>
+                             .aux_usage = surf_usage,<br>
+                             .mocs = device->default_mocs);<br>
+<br>
+         /* Typed surface reads support a very limited subset of the shader<br>
+          * image formats.  Translate it into the closest format the hardware<br>
+          * supports.<br>
+          */<br>
          view.format = isl_lower_storage_image_format<wbr>(&device->info,<br>
                                                       format.isl_format);<br>
+<br>
          isl_surf_fill_state(&device->i<wbr>sl_dev,<br>
                              iview->storage_surface_state.m<wbr>ap,<br>
                              .surf = &surface->isl,<br>
@@ -602,16 +618,24 @@ anv_CreateImageView(VkDevice _device,<br>
                                        ISL_FORMAT_RAW,<br>
                                        iview->offset,<br>
                                        iview->bo->size - iview->offset, 1);<br>
+         anv_fill_buffer_surface_<wbr>state(device,<br>
+                                       iview->writeonly_storage_surf<wbr>ace_state,<br>
+                                       ISL_FORMAT_RAW,<br>
+                                       iview->offset,<br>
+                                       iview->bo->size - iview->offset, 1);<br></blockquote><div><br></div></div></div><div>This isn't quite right.  The isl_has_matching_typed_<wbr>storage_image_format function decides whether it's lowered to a load/store with a different type or if it's lowered to, effectively, an SSBO and all of the tiling calculations are done in the shader.  With write-only, we always use a typed write instruction so that should never get the buffer treatment.  What we really need to do is fill out the write-only surface state outside of the if statement.  Make sense?<br></div></div></div></div></blockquote><div><br></div><div><div>That makes sense, I'll fix that up.</div><div><br></div><div>Thanks for looking at this!</div><div>Alex </div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div class="gmail-h5">
       }<br>
<br>
       isl_surf_fill_image_param(&de<wbr>vice->isl_dev,<br>
                                 &iview->storage_image_param,<br>
                                 &surface->isl, &iview->isl);<br>
<br>
-      if (!device->info.has_llc)<br>
+      if (!device->info.has_llc) {<br>
          anv_state_clflush(iview->stora<wbr>ge_surface_state);<br>
+         anv_state_clflush(iview->writ<wbr>eonly_storage_surface_state);<br>
+      }<br>
    } else {<br>
       iview->storage_surface_state.<wbr>alloc_size = 0;<br>
+      iview->writeonly_storage_surfa<wbr>ce_state.alloc_size = 0;<br>
    }<br>
<br>
    *pView = anv_image_view_to_handle(iview<wbr>);<br>
@@ -639,6 +663,11 @@ anv_DestroyImageView(VkDevice _device, VkImageView _iview,<br>
                           iview->storage_surface_state)<wbr>;<br>
    }<br>
<br>
+   if (iview->writeonly_storage_surf<wbr>ace_state.alloc_size > 0) {<br>
+      anv_state_pool_free(&device->s<wbr>urface_state_pool,<br>
+                          iview->writeonly_storage_surfa<wbr>ce_state);<br>
+   }<br>
+<br>
    vk_free2(&device->alloc, pAllocator, iview);<br>
 }<br>
<br>
diff --git a/src/intel/vulkan/anv_nir_app<wbr>ly_pipeline_layout.c b/src/intel/vulkan/anv_nir_app<wbr>ly_pipeline_layout.c<br>
index 8846c2e..296fd05 100644<br>
--- a/src/intel/vulkan/anv_nir_app<wbr>ly_pipeline_layout.c<br>
+++ b/src/intel/vulkan/anv_nir_app<wbr>ly_pipeline_layout.c<br>
@@ -351,9 +351,6 @@ anv_nir_apply_pipeline_layout(<wbr>struct anv_pipeline *pipeline,<br>
          continue;<br>
<br>
       enum glsl_sampler_dim dim = glsl_get_sampler_dim(var->inte<wbr>rface_type);<br>
-      if (dim != GLSL_SAMPLER_DIM_SUBPASS &&<br>
-          dim != GLSL_SAMPLER_DIM_SUBPASS_MS)<br>
-         continue;<br>
<br>
       const uint32_t set = var->data.descriptor_set;<br>
       const uint32_t binding = var->data.binding;<br>
@@ -369,7 +366,12 @@ anv_nir_apply_pipeline_layout(<wbr>struct anv_pipeline *pipeline,<br>
          assert(pipe_binding[i].set == set);<br>
          assert(pipe_binding[i].binding == binding);<br>
          assert(pipe_binding[i].index == i);<br>
-         pipe_binding[i].input_attachm<wbr>ent_index = var->data.index + i;<br>
+<br>
+         if (dim != GLSL_SAMPLER_DIM_SUBPASS &&<br>
+             dim != GLSL_SAMPLER_DIM_SUBPASS_MS)<br>
+            pipe_binding[i].input_attachme<wbr>nt_index = var->data.index + i;<br>
+<br>
+         pipe_binding[i].write_only = var->data.image.write_only;<br>
       }<br>
    }<br>
<br>
diff --git a/src/intel/vulkan/anv_pipelin<wbr>e.c b/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
index ca3823c..4410103 100644<br>
--- a/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
+++ b/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
@@ -128,6 +128,7 @@ anv_shader_compile_to_nir(stru<wbr>ct anv_device *device,<br>
       .float64 = device->instance->physicalDevi<wbr>ce.info.gen >= 8,<br>
       .tessellation = true,<br>
       .draw_parameters = true,<br>
+      .image_write_without_format = true,<br>
    };<br>
<br>
    nir_function *entry_point =<br>
diff --git a/src/intel/vulkan/anv_private<wbr>.h b/src/intel/vulkan/anv_private<wbr>.h<br>
index 51e85c7..8db851a 100644<br>
--- a/src/intel/vulkan/anv_private<wbr>.h<br>
+++ b/src/intel/vulkan/anv_private<wbr>.h<br>
@@ -953,6 +953,9 @@ struct anv_pipeline_binding {<br>
<br>
    /* Input attachment index (relative to the subpass) */<br>
    uint8_t input_attachment_index;<br>
+<br>
+   /* For a storage image, whether it is write-only */<br>
+   bool write_only;<br>
 };<br>
<br>
 struct anv_pipeline_layout {<br>
@@ -1683,8 +1686,13 @@ struct anv_image_view {<br>
    /** RENDER_SURFACE_STATE when using image as a sampler surface. */<br>
    struct anv_state sampler_surface_state;<br>
<br>
-   /** RENDER_SURFACE_STATE when using image as a storage image. */<br>
+   /**<br>
+    * RENDER_SURFACE_STATE when using image as a storage image. Separate states<br>
+    * for write-only and readable, using the real format for write-only and the<br>
+    * lowered format for readable.<br>
+    */<br>
    struct anv_state storage_surface_state;<br>
+   struct anv_state writeonly_storage_surface_stat<wbr>e;<br>
<br>
    struct brw_image_param storage_image_param;<br>
 };<br>
diff --git a/src/intel/vulkan/genX_cmd_bu<wbr>ffer.c b/src/intel/vulkan/genX_cmd_bu<wbr>ffer.c<br>
index 8db26e9..b80159b 100644<br>
--- a/src/intel/vulkan/genX_cmd_bu<wbr>ffer.c<br>
+++ b/src/intel/vulkan/genX_cmd_bu<wbr>ffer.c<br>
@@ -1211,7 +1211,9 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,<br>
          break;<br>
<br>
       case VK_DESCRIPTOR_TYPE_STORAGE_IMA<wbr>GE: {<br>
-         surface_state = desc->image_view->storage_surf<wbr>ace_state;<br>
+         surface_state = (binding->write_only)<br>
+            ? desc->image_view->writeonly_st<wbr>orage_surface_state<br>
+            : desc->image_view->storage_surf<wbr>ace_state;<br>
          assert(surface_state.alloc_siz<wbr>e);<br>
          add_image_view_relocs(cmd_buff<wbr>er, desc->image_view,<br>
                                desc->image_view->image->aux_u<wbr>sage,<br>
</div></div><span class="gmail-HOEnZb"><font color="#888888"><span class="gmail-m_9017378583655642020HOEnZb"><font color="#888888">--<br>
2.7.4<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></font></span></blockquote></div><br></div></div>
</blockquote></div><br></div></div>