[Mesa-dev] [PATCH 1/3] gallivm: handle cube map arrays for texture sampling

Jose Fonseca jfonseca at vmware.com
Fri Aug 29 03:35:30 PDT 2014


On 28/08/14 17:25, Roland Scheidegger wrote:
> Am 28.08.2014 18:19, schrieb Jose Fonseca:
>> On 28/08/14 04:15, sroland at vmware.com wrote:
>>> From: Roland Scheidegger <sroland at vmware.com>
>>>
>>> Pretty easy, just make sure that all paths testing for PIPE_TEXTURE_CUBE
>>> also recognize PIPE_TEXTURE_CUBE_ARRAY, and add the layer * 6 calculation
>>> to the calculated face.
>>> Also handle it for texture size query, looks like OpenGL wants the number
>>> of cubes, not layers (so need division by 6).
>>>
>>> No piglit regressions.
>>> ---
>>>    src/gallium/auxiliary/gallivm/lp_bld_sample.c     |  5 +-
>>>    src/gallium/auxiliary/gallivm/lp_bld_sample.h     | 17 ++++++-
>>>    src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c | 16 ++----
>>>    src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c | 59
>>> ++++++++++++++++-------
>>>    src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |  2 +-
>>>    5 files changed, 62 insertions(+), 37 deletions(-)
>>>
>>> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
>>> b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
>>> index f1bf285..85c0d4e 100644
>>> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
>>> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
>>> @@ -1313,10 +1313,7 @@ lp_build_mipmap_level_sizes(struct
>>> lp_build_sample_context *bld,
>>>
>>> bld->row_stride_array,
>>>                                                          ilevel);
>>>       }
>>> -   if (dims == 3 ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +   if (dims == 3 ||
>>> has_layer_coord(bld->static_texture_state->target)) {
>>>          *img_stride_vec = lp_build_get_level_stride_vec(bld,
>>>
>>> bld->img_stride_array,
>>>                                                          ilevel);
>>> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
>>> b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
>>> index fd4e053..be05b13 100644
>>> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
>>> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
>>> @@ -356,9 +356,7 @@ texture_dims(enum pipe_texture_target tex)
>>>       case PIPE_TEXTURE_2D_ARRAY:
>>>       case PIPE_TEXTURE_RECT:
>>>       case PIPE_TEXTURE_CUBE:
>>> -      return 2;
>>>       case PIPE_TEXTURE_CUBE_ARRAY:
>>> -      assert(0);
>>>          return 2;
>>>       case PIPE_TEXTURE_3D:
>>>          return 3;
>>> @@ -368,6 +366,21 @@ texture_dims(enum pipe_texture_target tex)
>>>       }
>>>    }
>>>
>>> +static INLINE boolean
>>> +has_layer_coord(enum pipe_texture_target tex)
>>> +{
>>> +   switch (tex) {
>>> +   case PIPE_TEXTURE_1D_ARRAY:
>>> +   case PIPE_TEXTURE_2D_ARRAY:
>>> +   /* cube is not layered but 3rd coord (after cube mapping) behaves
>>> the same */
>>> +   case PIPE_TEXTURE_CUBE:
>>> +   case PIPE_TEXTURE_CUBE_ARRAY:
>>> +      return TRUE;
>>> +   default:
>>> +      return FALSE;
>>> +   }
>>> +}
>>> +
>>>
>>>    boolean
>>>    lp_sampler_wrap_mode_uses_border_color(unsigned mode,
>>> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
>>> b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
>>> index 2f02606..394521d 100644
>>> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
>>> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
>>> @@ -704,9 +704,7 @@ lp_build_sample_image_nearest(struct
>>> lp_build_sample_context *bld,
>>>             offset = lp_build_add(&bld->int_coord_bld, offset, z_offset);
>>>          }
>>>       }
>>> -   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +   if (has_layer_coord(bld->static_texture_state->target)) {
>>>          LLVMValueRef z_offset;
>>>          /* The r coord is the cube face in [0,5] or array layer */
>>>          z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
>>> @@ -781,9 +779,7 @@ lp_build_sample_image_nearest_afloat(struct
>>> lp_build_sample_context *bld,
>>>                                                &z_icoord);
>>>          }
>>>       }
>>> -   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +   if (has_layer_coord(bld->static_texture_state->target)) {
>>>          z_icoord = r;
>>>       }
>>>
>>> @@ -1130,9 +1126,7 @@ lp_build_sample_image_linear(struct
>>> lp_build_sample_context *bld,
>>>                                       &x_subcoord[0], &x_subcoord[1]);
>>>
>>>       /* add potential cube/array/mip offsets now as they are constant
>>> per pixel */
>>> -   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +   if (has_layer_coord(bld->static_texture_state->target)) {
>>>          LLVMValueRef z_offset;
>>>          z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
>>>          /* The r coord is the cube face in [0,5] or array layer */
>>> @@ -1301,9 +1295,7 @@ lp_build_sample_image_linear_afloat(struct
>>> lp_build_sample_context *bld,
>>>                                      &x_offset1, &x_subcoord[1]);
>>>
>>>       /* add potential cube/array/mip offsets now as they are constant
>>> per pixel */
>>> -   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +   if (has_layer_coord(bld->static_texture_state->target)) {
>>>          LLVMValueRef z_offset;
>>>          z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
>>>          /* The r coord is the cube face in [0,5] or array layer */
>>> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
>>> b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
>>> index e29f503..ec9f851 100644
>>> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
>>> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
>>> @@ -752,9 +752,7 @@ lp_build_sample_image_nearest(struct
>>> lp_build_sample_context *bld,
>>>             lp_build_name(z, "tex.z.wrapped");
>>>          }
>>>       }
>>> -   if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -       bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +   if (has_layer_coord(bld->static_texture_state->target)) {
>>>          z = coords[2];
>>>          lp_build_name(z, "tex.z.layer");
>>>       }
>>> @@ -868,7 +866,8 @@ lp_build_sample_image_linear(struct
>>> lp_build_sample_context *bld,
>>>       int chan, texel_index;
>>>       boolean seamless_cube_filter, accurate_cube_corners;
>>>
>>> -   seamless_cube_filter = bld->static_texture_state->target ==
>>> PIPE_TEXTURE_CUBE &&
>>> +   seamless_cube_filter = (bld->static_texture_state->target ==
>>> PIPE_TEXTURE_CUBE ||
>>> +                           bld->static_texture_state->target ==
>>> PIPE_TEXTURE_CUBE_ARRAY) &&
>>>                              bld->static_sampler_state->seamless_cube_map;
>>>       accurate_cube_corners = ACCURATE_CUBE_CORNERS &&
>>> seamless_cube_filter;
>>>
>>> @@ -923,9 +922,7 @@ lp_build_sample_image_linear(struct
>>> lp_build_sample_context *bld,
>>>                lp_build_name(z1, "tex.z1.wrapped");
>>>             }
>>>          }
>>> -      if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> -          bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
>>> -          bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
>>> +      if (has_layer_coord(bld->static_texture_state->target)) {
>>>             z00 = z01 = z10 = z11 = z1 = coords[2];  /* cube face or
>>> layer */
>>>             lp_build_name(z00, "tex.z0.layer");
>>>             lp_build_name(z1, "tex.z1.layer");
>>> @@ -1644,6 +1641,7 @@ lp_build_sample_mipmap_both(struct
>>> lp_build_sample_context *bld,
>>>    static LLVMValueRef
>>>    lp_build_layer_coord(struct lp_build_sample_context *bld,
>>>                         unsigned texture_unit,
>>> +                     boolean is_cube_array,
>>>                         LLVMValueRef layer,
>>>                         LLVMValueRef *out_of_bounds)
>>>    {
>>> @@ -1655,6 +1653,7 @@ lp_build_layer_coord(struct
>>> lp_build_sample_context *bld,
>>>
>>>       if (out_of_bounds) {
>>>          LLVMValueRef out1, out;
>>> +      assert(!is_cube_array);
>>>          num_layers = lp_build_broadcast_scalar(int_coord_bld,
>>> num_layers);
>>>          out = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, layer,
>>> int_coord_bld->zero);
>>>          out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, layer,
>>> num_layers);
>>> @@ -1663,7 +1662,9 @@ lp_build_layer_coord(struct
>>> lp_build_sample_context *bld,
>>>       }
>>>       else {
>>>          LLVMValueRef maxlayer;
>>> -      maxlayer = lp_build_sub(&bld->int_bld, num_layers,
>>> bld->int_bld.one);
>>> +      LLVMValueRef s = is_cube_array ?
>>> lp_build_const_int32(bld->gallivm, 6) :
>>> +                                       bld->int_bld.one;
>>> +      maxlayer = lp_build_sub(&bld->int_bld, num_layers, s);
>>>          maxlayer = lp_build_broadcast_scalar(int_coord_bld, maxlayer);
>>>          return lp_build_clamp(int_coord_bld, layer,
>>> int_coord_bld->zero, maxlayer);
>>>       }
>>> @@ -1703,7 +1704,7 @@ lp_build_sample_common(struct
>>> lp_build_sample_context *bld,
>>>        * Choose cube face, recompute texcoords for the chosen face and
>>>        * compute rho here too (as it requires transform of derivatives).
>>>        */
>>> -   if (target == PIPE_TEXTURE_CUBE) {
>>> +   if (target == PIPE_TEXTURE_CUBE || target ==
>>> PIPE_TEXTURE_CUBE_ARRAY) {
>>>          boolean need_derivs;
>>>          need_derivs = ((min_filter != mag_filter ||
>>>                          mip_filter != PIPE_TEX_MIPFILTER_NONE) &&
>>> @@ -1711,11 +1712,19 @@ lp_build_sample_common(struct
>>> lp_build_sample_context *bld,
>>>                          !explicit_lod);
>>>          lp_build_cube_lookup(bld, coords, derivs, &cube_rho,
>>> &cube_derivs, need_derivs);
>>>          derivs = &cube_derivs;
>>> +      if (target == PIPE_TEXTURE_CUBE_ARRAY) {
>>> +         /* just add effective layer to face coord now */
>>> +         LLVMValueRef layer = lp_build_iround(&bld->coord_bld,
>>> coords[3]);
>>> +         LLVMValueRef six = lp_build_const_int_vec(bld->gallivm,
>>> bld->int_coord_type, 6);
>>> +         layer = lp_build_mul(&bld->int_coord_bld, layer, six);
>>> +         layer = lp_build_layer_coord(bld, texture_index, TRUE,
>>> layer, NULL);
>>> +         coords[2] = lp_build_add(&bld->int_coord_bld, coords[2],
>>> layer);
>>> +      }
>>>       }
>>>       else if (target == PIPE_TEXTURE_1D_ARRAY ||
>>>                target == PIPE_TEXTURE_2D_ARRAY) {
>>>          coords[2] = lp_build_iround(&bld->coord_bld, coords[2]);
>>> -      coords[2] = lp_build_layer_coord(bld, texture_index, coords[2],
>>> NULL);
>>> +      coords[2] = lp_build_layer_coord(bld, texture_index, FALSE,
>>> coords[2], NULL);
>>>       }
>>>
>>>       if (bld->static_sampler_state->compare_mode !=
>>> PIPE_TEX_COMPARE_NONE) {
>>> @@ -2223,11 +2232,11 @@ lp_build_fetch_texel(struct
>>> lp_build_sample_context *bld,
>>>       if (target == PIPE_TEXTURE_1D_ARRAY ||
>>>           target == PIPE_TEXTURE_2D_ARRAY) {
>>>          if (out_of_bound_ret_zero) {
>>> -         z = lp_build_layer_coord(bld, texture_unit, z, &out1);
>>> +         z = lp_build_layer_coord(bld, texture_unit, FALSE, z, &out1);
>>>             out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds,
>>> out1);
>>>          }
>>>          else {
>>> -         z = lp_build_layer_coord(bld, texture_unit, z, NULL);
>>> +         z = lp_build_layer_coord(bld, texture_unit, FALSE, z, NULL);
>>>          }
>>>       }
>>>
>>> @@ -2463,7 +2472,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
>>>
>>>       if ((gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD) &&
>>>           (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) &&
>>> -       (static_texture_state->target == PIPE_TEXTURE_CUBE) &&
>>> +       (static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> +        static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) &&
>>>           (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {
>>>          /*
>>>           * special case for using per-pixel lod even for implicit lod,
>>> @@ -2601,7 +2611,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
>>>                use_aos &=
>>> lp_is_simple_wrap_mode(derived_sampler_state.wrap_r);
>>>             }
>>>          }
>>> -      if (static_texture_state->target == PIPE_TEXTURE_CUBE &&
>>> +      if ((static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> +           static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) &&
>>>              derived_sampler_state.seamless_cube_map &&
>>>              (derived_sampler_state.min_img_filter ==
>>> PIPE_TEX_FILTER_LINEAR ||
>>>               derived_sampler_state.mag_img_filter ==
>>> PIPE_TEX_FILTER_LINEAR)) {
>>> @@ -2695,7 +2706,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
>>>             bld4.num_mips = bld4.num_lods = 1;
>>>             if ((gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD) &&
>>>                 (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) &&
>>> -             (static_texture_state->target == PIPE_TEXTURE_CUBE) &&
>>> +             (static_texture_state->target == PIPE_TEXTURE_CUBE ||
>>> +              static_texture_state->target ==
>>> PIPE_TEXTURE_CUBE_ARRAY) &&
>>>                 (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {
>>>                bld4.num_mips = type4.length;
>>>                bld4.num_lods = type4.length;
>>> @@ -2891,6 +2903,7 @@ lp_build_size_query_soa(struct gallivm_state
>>> *gallivm,
>>>       switch (target) {
>>>       case PIPE_TEXTURE_1D_ARRAY:
>>>       case PIPE_TEXTURE_2D_ARRAY:
>>> +   case PIPE_TEXTURE_CUBE_ARRAY:
>>>          has_array = TRUE;
>>>          break;
>>>       default:
>>> @@ -2932,10 +2945,20 @@ lp_build_size_query_soa(struct gallivm_state
>>> *gallivm,
>>>
>>>       size = lp_build_minify(&bld_int_vec4, size, lod, TRUE);
>>>
>>> -   if (has_array)
>>> -      size = LLVMBuildInsertElement(gallivm->builder, size,
>>> -
>>> dynamic_state->depth(dynamic_state, gallivm, texture_unit),
>>> +   if (has_array) {
>>> +      LLVMValueRef layers = dynamic_state->depth(dynamic_state,
>>> gallivm, texture_unit);
>>> +      if (target == PIPE_TEXTURE_CUBE_ARRAY) {
>>> +         /*
>>> +          * It looks like GL wants number of cubes, d3d10.1 has it
>>> undefined?
>>> +          * Could avoid this by passing in number of cubes instead of
>>> total
>>> +          * number of layers (might make things easier elsewhere too).
>>> +          */
>>> +         LLVMValueRef six = lp_build_const_int32(gallivm, 6);
>>> +         layers = LLVMBuildSDiv(gallivm->builder, layers, six, "");
>>> +      }
>>> +      size = LLVMBuildInsertElement(gallivm->builder, size, layers,
>>>                                        lp_build_const_int32(gallivm,
>>> dims), "");
>>> +   }
>>>
>>>       /*
>>>        * d3d10 requires zero for x/y/z values (but not w, i.e. mip levels)
>>> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
>>> b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
>>> index 93c926a..6731e32 100644
>>> --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
>>> +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
>>> @@ -2333,7 +2333,7 @@ emit_fetch_texels( struct
>>> lp_build_tgsi_soa_context *bld,
>>>       unsigned unit, target;
>>>       LLVMValueRef coord_undef =
>>> LLVMGetUndef(bld->bld_base.base.int_vec_type);
>>>       LLVMValueRef explicit_lod = NULL;
>>> -   LLVMValueRef coords[3];
>>> +   LLVMValueRef coords[5];
>>
>>
>> Is this really necessary? AFAICT, only coord[0..2] is ever writte.
> I noticed we copy all 5 array members unconditionally later in
> lp_build_sample_soa(), even though clearly in this case they won't be
> used, that's why I added it. Blame the sampling interface...

I see. Please add a comment  "// lp_build_sample_soa expects 5". In that 
case please update the for-cycle that initializes it to go through all 
members, otherwise valgrind will complain about uninitialized memory use.

Jose


>>
>> Otherwise series looks good AFAICT.  (Though I only skimmed through
>> softpipe.)
>
> Thanks! I had to send out a new version though which has some hope to
> work with seamless too...
>
> Roland
>
>> Jose
>>
>>>       LLVMValueRef offsets[3] = { NULL };
>>>       enum lp_sampler_lod_property lod_property = LP_SAMPLER_LOD_SCALAR;
>>>       unsigned dims, i;
>>>
>>
>



More information about the mesa-dev mailing list