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

Francisco Jerez currojerez at riseup.net
Tue Aug 11 03:00:59 PDT 2015


Jason Ekstrand <jason at jlekstrand.net> writes:

> On Sat, Aug 8, 2015 at 4:04 AM, Francisco Jerez <currojerez at riseup.net> wrote:
>> Jason Ekstrand <jason at jlekstrand.net> writes:
>>
>>> On Wed, May 13, 2015 at 9:43 AM, Francisco Jerez <currojerez at riseup.net> wrote:
>>>> v2: Add SKL support.
>>>> ---
>>>>  src/mesa/drivers/dri/i965/brw_context.h          |   2 +
>>>>  src/mesa/drivers/dri/i965/brw_surface_formats.c  | 109 +++++++++++++++++++++++
>>>>  src/mesa/drivers/dri/i965/brw_wm_surface_state.c |  77 ++++++++++++++++
>>>>  3 files changed, 188 insertions(+)
>>>>
>>>> diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
>>>> index 2dcc23c..c55dcec 100644
>>>> --- a/src/mesa/drivers/dri/i965/brw_context.h
>>>> +++ b/src/mesa/drivers/dri/i965/brw_context.h
>>>> @@ -1741,6 +1741,8 @@ void brw_upload_abo_surfaces(struct brw_context *brw,
>>>>  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_device_info *devinfo,
>>>> +                                        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 016f87a..e0e7fb6 100644
>>>> --- a/src/mesa/drivers/dri/i965/brw_surface_formats.c
>>>> +++ b/src/mesa/drivers/dri/i965/brw_surface_formats.c
>>>> @@ -805,3 +805,112 @@ brw_depth_format(struct brw_context *brw, mesa_format format)
>>>>        unreachable("Unexpected depth format.");
>>>>     }
>>>>  }
>>>> +
>>>> +mesa_format
>>>> +brw_lower_mesa_image_format(const struct brw_device_info *devinfo,
>>>> +                            mesa_format format)
>>>> +{
>>>> +   switch (format) {
>>>> +   /* These are never lowered.  Up to BDW we'll have to fall back to untyped
>>>> +    * surface access for 128bpp formats.
>>>> +    */
>>>> +   case MESA_FORMAT_RGBA_UINT32:
>>>> +   case MESA_FORMAT_RGBA_SINT32:
>>>> +   case MESA_FORMAT_RGBA_FLOAT32:
>>>> +   case MESA_FORMAT_R_UINT32:
>>>> +   case MESA_FORMAT_R_SINT32:
>>>> +   case MESA_FORMAT_R_FLOAT32:
>>>> +      return format;
>>>
>>> If it's an unsupported format, why not use MESA_FORMAT_NONE?  That
>>> would make it easier for functions that call this function to know
>>> that it's just not supported and they shouldn't bother trying.
>>>
>> Because they are all supported.  As the comment says these formats are
>> always accessed unlowered, the catch is that the shader may have to use
>> a different (much more painful) mechanism to access them depending on
>> the hardware generation -- But this function simply implements the
>> mapping between API image formats and what the 3D pipeline will see,
>> which is R(GBA)_*32 in this case regardless of whether untyped or typed
>> messages can be used.
>
> Ok, I failed to read.  Sorry for the noise.
>
>>>> +
>>>> +   /* From HSW to BDW the only 64bpp format supported for typed access is
>>>> +    * RGBA_UINT16.  IVB falls back to untyped.
>>>> +    */
>>>> +   case MESA_FORMAT_RGBA_UINT16:
>>>> +   case MESA_FORMAT_RGBA_SINT16:
>>>> +   case MESA_FORMAT_RGBA_FLOAT16:
>>>> +   case MESA_FORMAT_RG_UINT32:
>>>> +   case MESA_FORMAT_RG_SINT32:
>>>> +   case MESA_FORMAT_RG_FLOAT32:
>>>> +      return (devinfo->gen >= 9 ? format :
>>>> +              devinfo->gen >= 8 || devinfo->is_haswell ?
>>>> +              MESA_FORMAT_RGBA_UINT16 : MESA_FORMAT_RG_UINT32);
>>>> +
>>>> +   /* Up to BDW no SINT or FLOAT formats of less than 32 bits per component
>>>> +    * are supported.  IVB doesn't support formats with more than one component
>>>> +    * for typed access.  For 8 and 16 bpp formats IVB relies on the
>>>> +    * undocumented behavior that typed reads from R_UINT8 and R_UINT16
>>>> +    * surfaces actually do a 32-bit misaligned read.  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
>>>> +    * R_UINT8 or R_UINT16), but that would complicate the shaders we generate
>>>> +    * even more.
>>>> +    */
>>>
>>> Let's make sure I'm understanding this correctly.  On BDW and HSW, we
>>> can just use the UINT format for SINT and FLOAT.  On IVB, we set the
>>> surface state to UINT32 and unpack the components in the shader?  What
>>> happens with writes on IVB to 16-bpp images?
>>>
>> Heh, not exactly.  On IVB we disobey the hardware spec and bind 16-bpp
>> formats as R16_UINT and 8-bpp formats as R8_UINT, which aren't
>> documented to work for typed reads.  Writes work just fine and update
>> the right 8- or 16-bit word on the image.  Reads *almost* do what one
>> would expect: The LSBs of the values returned from the data port will
>> contain the texel we asked for, but the MSBs will be filled with garbage
>> which we simply mask out
>> (c.f. image_format_info::has_undefined_high_bits).
>>
>>>> +   case MESA_FORMAT_RGBA_UINT8:
>>>> +   case MESA_FORMAT_RGBA_SINT8:
>>>> +      return (devinfo->gen >= 9 ? format :
>>>> +              devinfo->gen >= 8 || devinfo->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:
>>>> +      return (devinfo->gen >= 9 ? format :
>>>> +              devinfo->gen >= 8 || devinfo->is_haswell ?
>>>> +              MESA_FORMAT_RG_UINT16 : MESA_FORMAT_R_UINT32);
>>>> +
>>>> +   case MESA_FORMAT_RG_UINT8:
>>>> +   case MESA_FORMAT_RG_SINT8:
>>>> +      return (devinfo->gen >= 9 ? format :
>>>> +              devinfo->gen >= 8 || devinfo->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:
>>>> +      return (devinfo->gen >= 9 ? format : MESA_FORMAT_R_UINT16);
>>>> +
>>>> +   case MESA_FORMAT_R_UINT8:
>>>> +   case MESA_FORMAT_R_SINT8:
>>>> +      return (devinfo->gen >= 9 ? format : MESA_FORMAT_R_UINT8);
>>>> +
>>>> +   /* Neither the 2/10/10/10 nor the 11/11/10 packed formats are supported
>>>> +    * by the hardware.
>>>> +    */
>>>> +   case MESA_FORMAT_R10G10B10A2_UINT:
>>>> +   case MESA_FORMAT_R10G10B10A2_UNORM:
>>>> +   case MESA_FORMAT_R11G11B10_FLOAT:
>>>> +      return MESA_FORMAT_R_UINT32;
>>>> +
>>>> +   /* No normalized fixed-point formats are supported by the hardware. */
>>>> +   case MESA_FORMAT_RGBA_UNORM16:
>>>> +   case MESA_FORMAT_RGBA_SNORM16:
>>>> +      return (devinfo->gen >= 8 || devinfo->is_haswell ?
>>>> +              MESA_FORMAT_RGBA_UINT16 : MESA_FORMAT_RG_UINT32);
>>>> +
>>>> +   case MESA_FORMAT_R8G8B8A8_UNORM:
>>>> +   case MESA_FORMAT_R8G8B8A8_SNORM:
>>>> +      return (devinfo->gen >= 8 || devinfo->is_haswell ?
>>>> +              MESA_FORMAT_RGBA_UINT8 : MESA_FORMAT_R_UINT32);
>>>> +
>>>> +   case MESA_FORMAT_R16G16_UNORM:
>>>> +   case MESA_FORMAT_R16G16_SNORM:
>>>> +      return (devinfo->gen >= 8 || devinfo->is_haswell ?
>>>> +              MESA_FORMAT_RG_UINT16 : MESA_FORMAT_R_UINT32);
>>>> +
>>>> +   case MESA_FORMAT_R8G8_UNORM:
>>>> +   case MESA_FORMAT_R8G8_SNORM:
>>>> +      return (devinfo->gen >= 8 || devinfo->is_haswell ?
>>>> +              MESA_FORMAT_RG_UINT8 : MESA_FORMAT_R_UINT16);
>>>> +
>>>> +   case MESA_FORMAT_R_UNORM16:
>>>> +   case MESA_FORMAT_R_SNORM16:
>>>> +      return MESA_FORMAT_R_UINT16;
>>>> +
>>>> +   case MESA_FORMAT_R_UNORM8:
>>>> +   case MESA_FORMAT_R_SNORM8:
>>>> +      return MESA_FORMAT_R_UINT8;
>>>> +
>>>> +   default:
>>>> +      unreachable("Not reached");
>>>
>>> Please be more descriptive.
>>>
>> Changed to "Unknown image format" locally.
>>
>>>> +   }
>>>> +}
>>>> 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 160dd2f..f8cb143 100644
>>>> --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
>>>> +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
>>>> @@ -1022,6 +1022,83 @@ const struct brw_tracked_state brw_cs_abo_surfaces = {
>>>>     .emit = brw_upload_cs_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 && brw->gen <= 8) ||
>>>> +          (_mesa_get_format_bytes(format) >= 8 &&
>>>> +           (brw->gen == 7 && !brw->is_haswell)))
>>>
>>> It's tricky to verify, but this list of conditions doesn't look much
>>> like the switch above.  Maybe I'm missing something.
>>>
>>
>> This check is equivalent to the one in
>> image_format_info::has_matching_typed_format (I considered re-using the
>> same function but then noticed that this file is C so I'd have to change
>> a number of things of the image_format_info helpers in order to be able
>> to include them here, what I didn't quite feel like doing and didn't
>> seem worth the effort in order to save 2 LOC).  The check is orthogonal
>> to format lowering -- In cases where the lowered format can be accessed
>> using typed messages we just go ahead and bind it, otherwise I set the
>> format in the surface state structure to RAW in the expectation that the
>> shader will want access them using untyped messages, because it's a
>> requirement for them to work.
>>
>>>> +         return BRW_SURFACEFORMAT_RAW;
>>>> +      else
>>>> +         return brw_format_for_mesa_format(
>>>> +            brw_lower_mesa_image_format(brw->intelScreen->devinfo, format));
>>>> +   }
>>>> +}
>>>
>>> Why are get_image_format and lower_mesa_image_format separate
>>> functions?  Again, it seems like we have decisions being made two
>>> different places.  brw_lower_mesa_image_format lowers it to the format
>>> as if it were write_only and then we do more switching here based on
>>> gen.  Maybe this is truly easier, but it seems odd.
>>>
>> brw_lower_mesa_image_format() implements the mapping between API formats
>> and the format the shader will see.  This function translates the
>> lowered shader-format into the format that will be set in the surface
>> state structure.  None of these conditions directly apply to the format
>> translation that will be done in the compiler, which is why it's kept
>> separate from brw_lower_mesa_image_format() (which is also called from
>> the compiler back-end).  One condition relates to setting the surface
>> state format to RAW (which forgets useful format information so we don't
>> want to return that to the compiler back-end), and the other is about
>> the additional optimization done in cases where we know that the image
>> is only ever written to by the shader -- In those cases we just bind the
>> original unlowered format and expect the shader to skip format
>> conversion completely.  You could argue that this could be handled in
>> brw_lower_mesa_image_format() by adding a "GLenum access" parameter,
>> however almost none of the callers of brw_lower_mesa_image_format() have
>> the image access mode readily available, and passing it down from
>> brw_fs_nir.cpp would uglify a number of interfaces, so it seemed easier
>> to keep the access mode-dependent translation orthogonal from the actual
>> format lowering.
>
> Ok, this is all making a lot more sense.  I guess I probably should
> have read/understood this code before/during trying to read/understand
> the lowering in surface_builder.  I think I would like to see both
> this code and the has_undefined_high_bits-type helpers put into a
> single file with all of these interactions documented.  However, that
> can be done as a follow-on and doesn't need to block the extension.
>
> Reviewed-by: Jason Ekstrand <jason.ekstrand at intel.com>
>
> You can also consider most of my reservations about the
> emit_typed_read() patch rescinded pending the above cleanup.
>

Thanks!

> --Jason
>
>>>> +
>>>> +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)
>>>>  {
>>>> --
>>>> 2.3.5
>>>>
>>>> _______________________________________________
>>>> mesa-dev mailing list
>>>> mesa-dev at lists.freedesktop.org
>>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 212 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150811/28a24f9b/attachment.sig>


More information about the mesa-dev mailing list