[Mesa-dev,07/14] i965: Implement surface state set-up for shader images.

Submitted by Francisco Jerez on Feb. 6, 2015, 5:23 p.m.

Details

Message ID 1423243408-24744-7-git-send-email-currojerez@riseup.net
State New
Headers show

Not browsing as part of any series.

Commit Message

Francisco Jerez Feb. 6, 2015, 5:23 p.m.
---
 src/mesa/drivers/dri/i965/brw_context.h          |   2 +
 src/mesa/drivers/dri/i965/brw_surface_formats.c  | 111 +++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |  77 ++++++++++++++++
 3 files changed, 190 insertions(+)

Patch hide | download patch | download mbox

diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index e6827e0..8cc54ad 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1669,6 +1669,8 @@  bool brw_is_hiz_depth_format(struct brw_context *ctx, mesa_format format);
 bool brw_render_target_supported(struct brw_context *brw,
                                  struct gl_renderbuffer *rb);
 uint32_t brw_depth_format(struct brw_context *brw, mesa_format format);
+mesa_format brw_lower_mesa_image_format(const struct brw_context *brw,
+                                        mesa_format format);
 
 /* brw_performance_monitor.c */
 void brw_init_performance_monitors(struct brw_context *brw);
diff --git a/src/mesa/drivers/dri/i965/brw_surface_formats.c b/src/mesa/drivers/dri/i965/brw_surface_formats.c
index 7261c01..3b9304a 100644
--- a/src/mesa/drivers/dri/i965/brw_surface_formats.c
+++ b/src/mesa/drivers/dri/i965/brw_surface_formats.c
@@ -809,3 +809,114 @@  brw_is_hiz_depth_format(struct brw_context *brw, mesa_format format)
       return false;
    }
 }
+
+mesa_format
+brw_lower_mesa_image_format(const struct brw_context *brw, mesa_format format)
+{
+   switch (format) {
+   case MESA_FORMAT_RGBA_UINT32:
+   case MESA_FORMAT_RGBA_SINT32:
+   case MESA_FORMAT_RGBA_FLOAT32:
+      /* Fail...  We'll have to fall back to untyped surface access for all
+       * 128 bpp formats.
+       */
+      return MESA_FORMAT_RGBA_UINT32;
+
+   case MESA_FORMAT_RGBA_UINT16:
+   case MESA_FORMAT_RGBA_SINT16:
+   case MESA_FORMAT_RGBA_FLOAT16:
+   case MESA_FORMAT_RGBA_UNORM16:
+   case MESA_FORMAT_RGBA_SNORM16:
+   case MESA_FORMAT_RG_UINT32:
+   case MESA_FORMAT_RG_SINT32:
+   case MESA_FORMAT_RG_FLOAT32:
+      /* HSW and later support the RGBA_UINT16 format natively and handle the
+       * pixel packing, unpacking and type conversion in the shader for other
+       * 64 bpp formats.  IVB falls back to untyped.
+       */
+      return (brw->gen >= 8 || brw->is_haswell ? MESA_FORMAT_RGBA_UINT16 :
+              MESA_FORMAT_RG_UINT32);
+
+   case MESA_FORMAT_RGBA_UINT8:
+   case MESA_FORMAT_RGBA_SINT8:
+   case MESA_FORMAT_R8G8B8A8_UNORM:
+   case MESA_FORMAT_R8G8B8A8_SNORM:
+      /* HSW and later support the RGBA_UINT8 format natively, type conversion
+       * to other formats is handled in the shader.  IVB uses R_UINT32 and
+       * handles the pixel packing, unpacking and type conversion in the
+       * shader.
+       */
+      return (brw->gen >= 8 || brw->is_haswell ? MESA_FORMAT_RGBA_UINT8 :
+              MESA_FORMAT_R_UINT32);
+
+   case MESA_FORMAT_RG_UINT16:
+   case MESA_FORMAT_RG_SINT16:
+   case MESA_FORMAT_RG_FLOAT16:
+   case MESA_FORMAT_R16G16_UNORM:
+   case MESA_FORMAT_R16G16_SNORM:
+      /* HSW and later support the RG_UINT16 format natively, type conversion
+       * to other formats is handled in the shader.  IVB uses R_UINT32 and
+       * handles the pixel packing, unpacking and type conversion in the
+       * shader.
+       */
+      return (brw->gen >= 8 || brw->is_haswell ? MESA_FORMAT_RG_UINT16 :
+              MESA_FORMAT_R_UINT32);
+
+   case MESA_FORMAT_R10G10B10A2_UINT:
+   case MESA_FORMAT_R10G10B10A2_UNORM:
+   case MESA_FORMAT_R11G11B10_FLOAT:
+   case MESA_FORMAT_R_UINT32:
+      /* Neither the 2/10/10/10 nor the 11/11/10 packed formats are supported
+       * by the hardware.  Use R_UINT32 and handle the pixel packing,
+       * unpacking, and type conversion in the shader.
+       */
+      return MESA_FORMAT_R_UINT32;
+
+   case MESA_FORMAT_R_SINT32:
+      return MESA_FORMAT_R_SINT32;
+
+   case MESA_FORMAT_R_FLOAT32:
+      return MESA_FORMAT_R_FLOAT32;
+
+   case MESA_FORMAT_RG_UINT8:
+   case MESA_FORMAT_RG_SINT8:
+   case MESA_FORMAT_R8G8_UNORM:
+   case MESA_FORMAT_R8G8_SNORM:
+      /* HSW and later support the RG_UINT8 format natively, type conversion
+       * to other formats is handled in the shader.  IVB uses R_UINT16 and
+       * handles the pixel packing, unpacking and type conversion in the
+       * shader.  Note that this relies on the undocumented behavior that
+       * typed reads from R_UINT16 surfaces actually do a 32-bit misaligned
+       * read on IVB.  The alternative would be to use two surface state
+       * entries with different formats for each image, one for reading (using
+       * R_UINT32) and another one for writing (using RG_UINT8), but that
+       * would complicate the shaders we generate even more.
+       */
+      return (brw->gen >= 8 || brw->is_haswell ? MESA_FORMAT_RG_UINT8 :
+              MESA_FORMAT_R_UINT16);
+
+   case MESA_FORMAT_R_UINT16:
+   case MESA_FORMAT_R_FLOAT16:
+   case MESA_FORMAT_R_SINT16:
+   case MESA_FORMAT_R_UNORM16:
+   case MESA_FORMAT_R_SNORM16:
+      /* HSW and later support the R_UINT16 format natively, type conversion
+       * to other formats is handled in the shader.  IVB relies on the same
+       * undocumented behavior described above.
+       */
+      return MESA_FORMAT_R_UINT16;
+
+   case MESA_FORMAT_R_UINT8:
+   case MESA_FORMAT_R_SINT8:
+   case MESA_FORMAT_R_UNORM8:
+   case MESA_FORMAT_R_SNORM8:
+      /* HSW and later support the R_UINT8 format natively, type conversion to
+       * other formats is handled in the shader.  IVB relies on the same
+       * undocumented behavior described above.
+       */
+      return MESA_FORMAT_R_UINT8;
+
+   default:
+      unreachable("Not reached");
+   }
+}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index b96d3fb..13755aa 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -960,6 +960,83 @@  const struct brw_tracked_state brw_wm_abo_surfaces = {
    .emit = brw_upload_wm_abo_surfaces,
 };
 
+static uint32_t
+get_image_format(struct brw_context *brw, mesa_format format, GLenum access)
+{
+   if (access == GL_WRITE_ONLY) {
+      return brw_format_for_mesa_format(format);
+   } else {
+      /* Typed surface reads support a very limited subset of the shader
+       * image formats.  Translate it into the closest format the
+       * hardware supports.
+       */
+      if (_mesa_get_format_bytes(format) >= 16 ||
+          (_mesa_get_format_bytes(format) >= 8 &&
+           (brw->gen == 7 && !brw->is_haswell)))
+         return BRW_SURFACEFORMAT_RAW;
+      else
+         return brw_format_for_mesa_format(
+            brw_lower_mesa_image_format(brw, format));
+   }
+}
+
+static void
+update_image_surface(struct brw_context *brw,
+                     struct gl_image_unit *u,
+                     GLenum access,
+                     unsigned surface_idx,
+                     uint32_t *surf_offset,
+                     struct brw_image_param *param)
+{
+   if (u->_Valid) {
+      struct gl_texture_object *obj = u->TexObj;
+      const unsigned format = get_image_format(brw, u->_ActualFormat, access);
+
+      if (obj->Target == GL_TEXTURE_BUFFER) {
+         struct intel_buffer_object *intel_obj =
+            intel_buffer_object(obj->BufferObject);
+         const unsigned texel_size = (format == BRW_SURFACEFORMAT_RAW ? 1 :
+                                      _mesa_get_format_bytes(u->_ActualFormat));
+
+         brw->vtbl.emit_buffer_surface_state(
+            brw, surf_offset, intel_obj->buffer, obj->BufferOffset,
+            format, intel_obj->Base.Size / texel_size, texel_size,
+            access != GL_READ_ONLY);
+
+      } else {
+         struct intel_texture_object *intel_obj = intel_texture_object(obj);
+         struct intel_mipmap_tree *mt = intel_obj->mt;
+
+         if (format == BRW_SURFACEFORMAT_RAW) {
+            brw->vtbl.emit_buffer_surface_state(
+               brw, surf_offset, mt->bo, mt->offset,
+               format, mt->bo->size - mt->offset, 1 /* pitch */,
+               access != GL_READ_ONLY);
+
+         } else {
+            const unsigned min_layer = obj->MinLayer + u->Layer;
+            const unsigned min_level = obj->MinLevel + u->Level;
+            const unsigned num_layers = (!u->Layered ? 1 :
+                                         obj->Target == GL_TEXTURE_CUBE_MAP ? 6 :
+                                         mt->logical_depth0);
+            const GLenum target = (obj->Target == GL_TEXTURE_CUBE_MAP ||
+                                   obj->Target == GL_TEXTURE_CUBE_MAP_ARRAY ?
+                                   GL_TEXTURE_2D_ARRAY : obj->Target);
+
+            brw->vtbl.emit_texture_surface_state(
+               brw, mt, target,
+               min_layer, min_layer + num_layers,
+               min_level, min_level + 1,
+               format, SWIZZLE_XYZW,
+               surf_offset, access != GL_READ_ONLY, false);
+         }
+      }
+
+   } else {
+      brw->vtbl.emit_null_surface_state(brw, 1, 1, 1, surf_offset);
+   }
+}
+
 void
 gen4_init_vtable_surface_functions(struct brw_context *brw)
 {