[Mesa-dev] [PATCH 5/5] anv: setup appropriate border color structures on gen7/gen75

Jason Ekstrand jason at jlekstrand.net
Mon Oct 17 18:09:32 UTC 2016


On Mon, Oct 17, 2016 at 8:46 AM, Lionel Landwerlin <llandwerlin at gmail.com>
wrote:

> Up to this point we were using the gen8+ structures. Altough this commit
> doesn't fixes the border color CTS tests, this is a step in the right
> direction to fix the following tests :
>

It's not entirely clear where you're headed but I'm afraid the approach may
ultimately be doomed to failure.  The fundamental problem is that Vulkan
allows complete mix-and-match of images and samplers in the shader.  We
cannot know, until the shader *executes* which sampler will be associated
with a particular texture.  This leaves us with two possible solutions:

 1) Emit a sampler for every possible sampler+image combination.
 2) Piles of shader hacks.

Both approaches are highly annoying.  While the first option is probably
the less annoying of the two, there is one format (R32_UINT maybe?  I don't
remember for sure) for which integer border color just doesn't work at all
on Haswell.  On Ivy Bridge, integer border color is so broken we probably
shouldn't be using it at all.  This leaves us with shader hacks.  Ken wrote
a bunch of code for this so that we could get the ES 3.1 CTS passing on
Haswell and Ivy Bridge.  Maybe that could be ported?  Maybe we can find
some magic Ivy Bridge "make border color work" bit?


>
> dEQP-VK.pipeline.sampler.view_type.2d.format.*.address_
> modes.all_mode_clamp_to_border_*
>
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
> ---
>  src/intel/vulkan/anv_cmd_buffer.c |  10 ++
>  src/intel/vulkan/anv_device.c     |  42 +-------
>  src/intel/vulkan/anv_genX.h       |   3 +-
>  src/intel/vulkan/anv_private.h    |   7 ++
>  src/intel/vulkan/genX_state.c     | 220 ++++++++++++++++++++++++++++++
> ++------
>  5 files changed, 208 insertions(+), 74 deletions(-)
>
> diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_
> buffer.c
> index b051489..a63f3d9 100644
> --- a/src/intel/vulkan/anv_cmd_buffer.c
> +++ b/src/intel/vulkan/anv_cmd_buffer.c
> @@ -931,6 +931,16 @@ anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer
> *cmd_buffer,
>        if (sampler == NULL)
>           continue;
>
> +      /* On Haswell, although the border color structures are 20 dwords
> long
> +       * and must be aligned at 512 bytes, the position of the 8/16/32bits
> +       * colors overlap, meaning we can't have a single color structure
> +       * configured for all formats. We therefore need to reemit the
> sampler
> +       * structure for the used format. */
> +      if (cmd_buffer->device->info.is_haswell) {
> +         gen75_pack_sampler_state(cmd_buffer->device, sampler,
> +                                  desc->image_view->vk_format);
> +      }
> +
>        memcpy(state->map + (s * 16),
>               sampler->state, sizeof(sampler->state));
>     }
> diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
> index ce1b9c1..4e69307 100644
> --- a/src/intel/vulkan/anv_device.c
> +++ b/src/intel/vulkan/anv_device.c
> @@ -724,46 +724,6 @@ anv_queue_finish(struct anv_queue *queue)
>  {
>  }
>
> -static struct anv_state
> -anv_state_pool_emit_data(struct anv_state_pool *pool, size_t size,
> size_t align, const void *p)
> -{
> -   struct anv_state state;
> -
> -   state = anv_state_pool_alloc(pool, size, align);
> -   memcpy(state.map, p, size);
> -
> -   if (!pool->block_pool->device->info.has_llc)
> -      anv_state_clflush(state);
> -
> -   return state;
> -}
> -
> -struct gen8_border_color {
> -   union {
> -      float float32[4];
> -      uint32_t uint32[4];
> -   };
> -   /* Pad out to 64 bytes */
> -   uint32_t _pad[12];
> -};
> -
> -static void
> -anv_device_init_border_colors(struct anv_device *device)
> -{
> -   static const struct gen8_border_color border_colors[] = {
> -      [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] =  { .float32 = { 0.0,
> 0.0, 0.0, 0.0 } },
> -      [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] =       { .float32 = { 0.0,
> 0.0, 0.0, 1.0 } },
> -      [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] =       { .float32 = { 1.0,
> 1.0, 1.0, 1.0 } },
> -      [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] =    { .uint32 = { 0, 0,
> 0, 0 } },
> -      [VK_BORDER_COLOR_INT_OPAQUE_BLACK] =         { .uint32 = { 0, 0,
> 0, 1 } },
> -      [VK_BORDER_COLOR_INT_OPAQUE_WHITE] =         { .uint32 = { 1, 1,
> 1, 1 } },
> -   };
> -
> -   device->border_colors = anv_state_pool_emit_data(&
> device->dynamic_state_pool,
> -
> sizeof(border_colors), 64,
> -                                                    border_colors);
> -}
> -
>  VkResult
>  anv_device_submit_simple_batch(struct anv_device *device,
>                                 struct anv_batch *batch)
> @@ -926,7 +886,7 @@ VkResult anv_CreateDevice(
>
>     anv_device_init_blorp(device);
>
> -   anv_device_init_border_colors(device);
> +   ANV_GEN_DISPATCH(device, border_colors_setup, device);
>
>     *pDevice = anv_device_to_handle(device);
>
> diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h
> index 27c55b9..a4a39e1 100644
> --- a/src/intel/vulkan/anv_genX.h
> +++ b/src/intel/vulkan/anv_genX.h
> @@ -28,7 +28,7 @@
>  /*
>   * Gen-specific function declarations.  This header must *not* be included
>   * directly.  Instead, it is included multiple times by anv_private.h.
> - *
> + *
>   * In this header file, the usual genx() macro is available.
>   */
>
> @@ -37,6 +37,7 @@
>  #endif
>
>  VkResult genX(init_device_state)(struct anv_device *device);
> +void genX(border_colors_setup)(struct anv_device *device);
>
>  void genX(cmd_buffer_emit_state_base_address)(struct anv_cmd_buffer
> *cmd_buffer);
>
> diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_
> private.h
> index 69e6aac..faebbb2 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -643,6 +643,7 @@ struct anv_device {
>      struct blorp_context                        blorp;
>
>      struct anv_state                            border_colors;
> +    uint32_t                                    border_color_align;
>
>      struct anv_queue                            queue;
>
> @@ -1732,6 +1733,8 @@ void anv_buffer_view_fill_image_param(struct
> anv_device *device,
>
>  struct anv_sampler {
>     uint32_t state[4];
> +
> +   VkSamplerCreateInfo info;
>  };
>
>  struct anv_framebuffer {
> @@ -1783,6 +1786,10 @@ struct anv_query_pool {
>     struct anv_bo                                bo;
>  };
>
> +void gen75_pack_sampler_state(struct anv_device *device,
> +                              struct anv_sampler *sampler,
> +                              VkFormat format);
> +
>  void *anv_lookup_entrypoint(const struct gen_device_info *devinfo,
>                              const char *name);
>
> diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c
> index a6d405d..cbf7df2 100644
> --- a/src/intel/vulkan/genX_state.c
> +++ b/src/intel/vulkan/genX_state.c
> @@ -28,11 +28,144 @@
>  #include <fcntl.h>
>
>  #include "anv_private.h"
> +#include "vk_format_info.h"
>
>  #include "common/gen_sample_positions.h"
>  #include "genxml/gen_macros.h"
>  #include "genxml/genX_pack.h"
>
> +static uint32_t
> +border_color_index(VkBorderColor border_color, VkFormat format)
> +{
> +#if GEN_IS_HASWELL
> +   if (!vk_format_is_integer(format))
> +      return border_color;
> +
> +   uint32_t max_bpc = vk_format_max_bpc(format);
> +   uint32_t index = 0;
> +
> +   if (max_bpc <= 8)
> +      return border_color;
> +
> +   if (max_bpc <= 16)
> +      index = VK_BORDER_COLOR_END_RANGE + 1;
> +   else
> +      index = VK_BORDER_COLOR_END_RANGE + 4;
> +
> +   switch (border_color) {
> +   case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
> +   case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
> +      index += 0;
> +      break;
> +
> +   case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
> +   case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
> +      index += 1;
> +      break;
> +
> +   case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
> +   case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
> +      index += 2;
> +      break;
> +
> +   default:
> +      unreachable("invalid border color");
> +   }
> +
> +   return index;
> +#else
> +   return border_color;
> +#endif
> +}
> +
> +#define BORDER_COLOR(name, r, g, b, a) {           \
> +      .BorderColor##name##Red   = r,               \
> +      .BorderColor##name##Green = g,               \
> +      .BorderColor##name##Blue  = b,               \
> +      .BorderColor##name##Alpha = a,               \
> +   }
> +
> +void
> +genX(border_colors_setup)(struct anv_device *device)
> +{
> +#if GEN_IS_HASWELL
> +   static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[]
> = {
> +      [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0),
> +      [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0),
> +      [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] =
> +         BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0),
> +      [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] =
> +         BORDER_COLOR(8bit, 0, 0, 0, 0),
> +      [VK_BORDER_COLOR_INT_OPAQUE_BLACK] =
> +         BORDER_COLOR(8bit, 0, 0, 0, 1),
> +      [VK_BORDER_COLOR_INT_OPAQUE_WHITE] =
> +         BORDER_COLOR(8bit, 1, 1, 1, 1),
> +      [VK_BORDER_COLOR_END_RANGE + 1] =
> +         BORDER_COLOR(16bit, 0, 0, 0, 0),
> +      [VK_BORDER_COLOR_END_RANGE + 2] =
> +         BORDER_COLOR(16bit, 0, 0, 0, 1),
> +      [VK_BORDER_COLOR_END_RANGE + 3] =
> +         BORDER_COLOR(16bit, 1, 1, 1, 1),
> +      [VK_BORDER_COLOR_END_RANGE + 4] =
> +         BORDER_COLOR(32bit, 0, 0, 0, 0),
> +      [VK_BORDER_COLOR_END_RANGE + 5] =
> +         BORDER_COLOR(32bit, 0, 0, 0, 1),
> +      [VK_BORDER_COLOR_END_RANGE + 6] =
> +         BORDER_COLOR(32bit, 1, 1, 1, 1)
> +   };
> +   device->border_color_align = 512;
> +#elif GEN_GEN == 7
> +   static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[]
> = {
> +      [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0),
> +      [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0),
> +      [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] =
> +         BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0),
> +      [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0),
> +      [VK_BORDER_COLOR_INT_OPAQUE_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0),
> +      [VK_BORDER_COLOR_INT_OPAQUE_WHITE] =
> +         BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0)
> +   };
> +   device->border_color_align = 64;
> +#else /* GEN_GEN >= 8 */
> +   static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[]
> = {
> +      [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0),
> +      [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] =
> +         BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0),
> +      [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] =
> +         BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0),
> +      [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] =
> +         BORDER_COLOR(32bit, 0, 0, 0, 0),
> +      [VK_BORDER_COLOR_INT_OPAQUE_BLACK] =
> +         BORDER_COLOR(32bit, 0, 0, 0, 1),
> +      [VK_BORDER_COLOR_INT_OPAQUE_WHITE] =
> +         BORDER_COLOR(32bit, 1, 1, 1, 1)
> +   };
> +   device->border_color_align = 64;
> +#endif
> +
> +   device->border_colors =
> +      anv_state_pool_alloc(&device->dynamic_state_pool,
> +                           ARRAY_SIZE(border_colors) *
> device->border_color_align,
> +                           device->border_color_align);
> +
> +   for (uint32_t i = 0; i < ARRAY_SIZE(border_colors); i++) {
> +      GENX(SAMPLER_BORDER_COLOR_STATE_pack)(
> +         NULL,
> +         device->border_colors.map + i * device->border_color_align,
> +         &border_colors[i]);
> +   }
> +
> +   if (!device->info.has_llc)
> +      anv_state_clflush(device->border_colors);
> +}
> +
>  VkResult
>  genX(init_device_state)(struct anv_device *device)
>  {
> @@ -148,24 +281,21 @@ static const uint32_t vk_to_gen_shadow_compare_op[]
> = {
>     [VK_COMPARE_OP_ALWAYS]                       = PREFILTEROPNEVER,
>  };
>
> -VkResult genX(CreateSampler)(
> -    VkDevice                                    _device,
> -    const VkSamplerCreateInfo*                  pCreateInfo,
> -    const VkAllocationCallbacks*                pAllocator,
> -    VkSampler*                                  pSampler)
> +#if GEN_IS_HASWELL
> +void
> +#else
> +static void
> +#endif
> +genX(pack_sampler_state)(
> +   struct anv_device *                          device,
> +   struct anv_sampler *                         sampler,
> +   VkFormat                                     format)
>  {
> -   ANV_FROM_HANDLE(anv_device, device, _device);
> -   struct anv_sampler *sampler;
> -
> -   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
> -
> -   sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
> -                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
> -   if (!sampler)
> -      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
> -
> -   uint32_t border_color_offset = device->border_colors.offset +
> -                                  pCreateInfo->borderColor * 64;
> +   uint32_t color_index =
> +      border_color_index(sampler->info.borderColor, format);
> +   uint32_t color_offset =
> +      device->border_colors.offset +
> +      color_index * device->border_color_align;
>
>     struct GENX(SAMPLER_STATE) sampler_state = {
>        .SamplerDisable = false,
> @@ -180,28 +310,28 @@ VkResult genX(CreateSampler)(
>  #if GEN_GEN == 8
>        .BaseMipLevel = 0.0,
>  #endif
> -      .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode],
> -      .MagModeFilter = vk_to_gen_tex_filter(pCreateInfo->magFilter,
> -                                            pCreateInfo->anisotropyEnable)
> ,
> -      .MinModeFilter = vk_to_gen_tex_filter(pCreateInfo->minFilter,
> -                                            pCreateInfo->anisotropyEnable)
> ,
> -      .TextureLODBias = anv_clamp_f(pCreateInfo->mipLodBias, -16,
> 15.996),
> +      .MipModeFilter = vk_to_gen_mipmap_mode[sampler->info.mipmapMode],
> +      .MagModeFilter = vk_to_gen_tex_filter(sampler->info.magFilter,
> +                                            sampler->info.
> anisotropyEnable),
> +      .MinModeFilter = vk_to_gen_tex_filter(sampler->info.minFilter,
> +                                            sampler->info.
> anisotropyEnable),
> +      .TextureLODBias = anv_clamp_f(sampler->info.mipLodBias, -16,
> 15.996),
>        .AnisotropicAlgorithm = EWAApproximation,
> -      .MinLOD = anv_clamp_f(pCreateInfo->minLod, 0, 14),
> -      .MaxLOD = anv_clamp_f(pCreateInfo->maxLod, 0, 14),
> +      .MinLOD = anv_clamp_f(sampler->info.minLod, 0, 14),
> +      .MaxLOD = anv_clamp_f(sampler->info.maxLod, 0, 14),
>        .ChromaKeyEnable = 0,
>        .ChromaKeyIndex = 0,
>        .ChromaKeyMode = 0,
> -      .ShadowFunction = vk_to_gen_shadow_compare_op[
> pCreateInfo->compareOp],
> +      .ShadowFunction = vk_to_gen_shadow_compare_op[
> sampler->info.compareOp],
>        .CubeSurfaceControlMode = OVERRIDE,
>
> -      .BorderColorPointer = border_color_offset,
> +      .BorderColorPointer = color_offset,
>
>  #if GEN_GEN >= 8
>        .LODClampMagnificationMode = MIPNONE,
>  #endif
>
> -      .MaximumAnisotropy = vk_to_gen_max_anisotropy(
> pCreateInfo->maxAnisotropy),
> +      .MaximumAnisotropy = vk_to_gen_max_anisotropy(
> sampler->info.maxAnisotropy),
>        .RAddressMinFilterRoundingEnable = 0,
>        .RAddressMagFilterRoundingEnable = 0,
>        .VAddressMinFilterRoundingEnable = 0,
> @@ -209,13 +339,39 @@ VkResult genX(CreateSampler)(
>        .UAddressMinFilterRoundingEnable = 0,
>        .UAddressMagFilterRoundingEnable = 0,
>        .TrilinearFilterQuality = 0,
> -      .NonnormalizedCoordinateEnable = pCreateInfo->
> unnormalizedCoordinates,
> -      .TCXAddressControlMode = vk_to_gen_tex_address[
> pCreateInfo->addressModeU],
> -      .TCYAddressControlMode = vk_to_gen_tex_address[
> pCreateInfo->addressModeV],
> -      .TCZAddressControlMode = vk_to_gen_tex_address[
> pCreateInfo->addressModeW],
> +      .NonnormalizedCoordinateEnable = sampler->info.
> unnormalizedCoordinates,
> +      .TCXAddressControlMode = vk_to_gen_tex_address[sampler-
> >info.addressModeU],
> +      .TCYAddressControlMode = vk_to_gen_tex_address[sampler-
> >info.addressModeV],
> +      .TCZAddressControlMode = vk_to_gen_tex_address[sampler-
> >info.addressModeW],
>     };
>
>     GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state);
> +}
> +
> +
> +VkResult genX(CreateSampler)(
> +    VkDevice                                    _device,
> +    const VkSamplerCreateInfo*                  pCreateInfo,
> +    const VkAllocationCallbacks*                pAllocator,
> +    VkSampler*                                  pSampler)
> +{
> +   ANV_FROM_HANDLE(anv_device, device, _device);
> +   struct anv_sampler *sampler;
> +
> +   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
> +
> +   sampler = anv_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
> +                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
> +   if (!sampler)
> +      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
> +
> +   sampler->info = *pCreateInfo;
> +
> +   /* No need to pack the sampler state on HSW, as the packing will
> depend on
> +    * the format of the associated texture. */
> +#if ! GEN_IS_HASWELL
> +   genX(pack_sampler_state)(device, sampler, VK_FORMAT_UNDEFINED);
> +#endif
>
>     *pSampler = anv_sampler_to_handle(sampler);
>
> --
> 2.9.3
>
> _______________________________________________
> 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/20161017/ceca41d4/attachment-0001.html>


More information about the mesa-dev mailing list