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

Lionel Landwerlin llandwerlin at gmail.com
Wed Oct 19 15:50:21 UTC 2016


Up to this point we were using the gen8+ structures to program border
colors. This commit sets up the correct border colors for HSW & IVB.

On HSW:
   This fixes 140 failures of :
     dEQP-VK.pipeline.sampler.view_type.*.format.*.address_modes.all_mode_clamp_to_border_*
     (11 failures remain out of 840 tests)

   Failures :
     - dEQP-VK.pipeline.sampler.view_type.*.format.b4g4r4a4_unorm_pack16.address_modes.all_mode_clamp_to_border_*

       There is no equivalent of b4g4r4a4_unorm on the GLES31 test suite and
       the documentation doesn't seem to list this format in any of the
       8/16/32bits supported ones.

     - dEQP-VK.pipeline.sampler.view_type.2d.format.r32g32b32_uint.address_modes.all_mode_clamp_to_border_*

       Some GLES31 equivalent tests are failing too :

         dEQP-GLES31.functional.texture.border_clamp.formats.rgba32ui.nearest_size_pot
         dEQP-GLES31.functional.texture.border_clamp.formats.rgba32ui.nearest_size_npot

     - dEQP-VK.pipeline.sampler.view_type.2d.format.r32_uint.address_modes.all_mode_clamp_to_border_*

       Seems to exhibit the same issue as r32g32b32_uint (some of the
       corners of the sampled texture are missing).

On IVB:
   This fixes 73 failures of :
     dEQP-VK.pipeline.sampler.view_type.*.format.*.address_modes.all_mode_clamp_to_border_*
     (139 failures remain out of 795 tests)

     All tests using *_sfloat, *_unorm, *_snorm formats are passing.

   Failures :
     - dEQP-VK.pipeline.sampler.view_type.*.format.r8g8b8_uint.address_modes.all_mode_clamp_to_border_*
       dEQP-VK.pipeline.sampler.view_type.*.format.r16g16b16_sint.address_modes.all_mode_clamp_to_border_*
       dEQP-VK.pipeline.sampler.view_type.*.format.r16g16b16_sfloat.address_modes.all_mode_clamp_to_border_*

       These tests were triggering an assert before and remain broken. This
       seems to be a hardware limitation we can't express through the Vulkan
       API.

     - Most of uint formats produce invalid results (some with invalid
       border color, some with invalid texture data) with exception of :

       dEQP-VK.pipeline.sampler.view_type.*.format.r32_sint.address_modes.all_mode_clamp_to_border_*

v2: Implement Jason's suggestion to have all sampler configuration ready at
    sampler cration
    Also fix remaining issues with 1 & 2 components texture

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
---
 src/intel/vulkan/anv_device.c      |  42 -------
 src/intel/vulkan/anv_genX.h        |   3 +-
 src/intel/vulkan/anv_private.h     |  11 +-
 src/intel/vulkan/genX_cmd_buffer.c |   5 +-
 src/intel/vulkan/genX_state.c      | 229 ++++++++++++++++++++++++++++++++++---
 5 files changed, 228 insertions(+), 62 deletions(-)

diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index c995630..3ad01b9 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)
@@ -943,8 +903,6 @@ VkResult anv_CreateDevice(

    anv_device_init_blorp(device);

-   anv_device_init_border_colors(device);
-
    *pDevice = anv_device_to_handle(device);

    return VK_SUCCESS;
diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h
index d4ed325..ebd0ee7 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);
+uint32_t genX(sampler_index)(VkFormat format);

 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 0e25827..2cca5c3 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -552,6 +552,7 @@ struct anv_device {
     struct blorp_context                        blorp;

     struct anv_state                            border_colors;
+    uint32_t                                    border_color_align;

     struct anv_queue                            queue;

@@ -1642,7 +1643,15 @@ void anv_buffer_view_fill_image_param(struct anv_device *device,
                                       struct brw_image_param *param);

 struct anv_sampler {
-   uint32_t state[4];
+   /* On Haswell we need to have all samplers declined per number of component
+    * for each possible integer format (8, 16 and 32 bits) and we also need
+    * sampler configurations for normalized and floating point formats :
+    *
+    * 4 components * 3 integer formats + floats&normalized = 13 configurations
+    *
+    * On all other platforms, only state[0] is used.
+    */
+   uint32_t state[13][4];
 };

 struct anv_framebuffer {
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index 5ea7c5f..88ed284 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -905,8 +905,9 @@ emit_samplers(struct anv_cmd_buffer *cmd_buffer,
       if (sampler == NULL)
          continue;

-      memcpy(state->map + (s * 16),
-             sampler->state, sizeof(sampler->state));
+      uint32_t sampler_index = genX(sampler_index)(desc->image_view->vk_format);
+      memcpy(state->map + (s * 16), sampler->state[sampler_index],
+             GENX(SAMPLER_STATE_length) * 4);
    }

    if (!cmd_buffer->device->info.has_llc)
diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c
index be1bd78..61aeef3 100644
--- a/src/intel/vulkan/genX_state.c
+++ b/src/intel/vulkan/genX_state.c
@@ -28,11 +28,172 @@
 #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"

+uint32_t
+genX(sampler_index)(VkFormat format)
+{
+#if ! GEN_IS_HASWELL
+   return 0;
+#else
+   if (!vk_format_is_integer(format))
+      return 0;
+
+   uint32_t index = 3 * (vk_format_n_channels(format) - 1);
+
+   switch(vk_format_max_bpc(format)) {
+   case 8:
+      index += 1;
+      break;
+
+   case 10:
+   case 16:
+   case 24:
+      index += 2;
+      break;
+
+   case 32:
+      index += 3;
+      break;
+   default:
+      anv_finishme("unsupported sampling format with border color");
+      return 0;
+   }
+
+   return index;
+#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,               \
+   }
+
+static void
+border_colors_setup(struct anv_device *device)
+{
+#if GEN_IS_HASWELL
+   /* We order things differently for Haswell and only ever care about the
+    * color, not whether the color integer or float (see genX(sampler_index)).
+    * This consumes 13 * 3 * 512 ~= 20kb of memory. */
+   static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[] = {
+      /* Transparent black: */
+      BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0),
+      /*  - R textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+      /*  - RG textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+      /*  - RGB textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+      /*  - RBGA textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   0),
+      BORDER_COLOR(16bit, 0,   0,   0,   0),
+      BORDER_COLOR(32bit, 0,   0,   0,   0),
+
+      /* Opaque black: */
+      BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0),
+      /*  - R textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+      /*  - RG textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+      /*  - RGB textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+      /*  - RGBA textures */
+      BORDER_COLOR(8bit,  0,   0,   0,   1),
+      BORDER_COLOR(16bit, 0,   0,   0,   1),
+      BORDER_COLOR(32bit, 0,   0,   0,   1),
+
+      /* Opaque white: */
+      BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0),
+      /*  - R textures */
+      BORDER_COLOR(8bit,  1,   0,   0,   1),
+      BORDER_COLOR(16bit, 1,   0,   0,   1),
+      BORDER_COLOR(32bit, 1,   0,   0,   1),
+      /*  - RG textures */
+      BORDER_COLOR(8bit,  1,   1,   0,   1),
+      BORDER_COLOR(16bit, 1,   1,   0,   1),
+      BORDER_COLOR(32bit, 1,   1,   0,   1),
+      /*  - RGB textures */
+      BORDER_COLOR(8bit,  1,   1,   1,   1),
+      BORDER_COLOR(16bit, 1,   1,   1,   1),
+      BORDER_COLOR(32bit, 1,   1,   1,   1),
+      /*  - RGBA textures */
+      BORDER_COLOR(8bit,  1,   1,   1,   1),
+      BORDER_COLOR(16bit, 1,   1,   1,   1),
+      BORDER_COLOR(32bit, 1,   1,   1,   1),
+   };
+   static_assert(sizeof(struct anv_sampler) / (4 * GENX(SAMPLER_STATE_length)) ==
+                 ARRAY_SIZE(border_colors) / 3,
+                 "struct anv_sampler size doesn't match border_colors");
+   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)
 {
@@ -91,6 +252,8 @@ genX(init_device_state)(struct anv_device *device)

    assert(batch.next <= batch.end);

+   border_colors_setup(device);
+
    return anv_device_submit_simple_batch(device, &batch);
 }

@@ -148,24 +311,34 @@ static const uint32_t vk_to_gen_shadow_compare_op[] = {
    [VK_COMPARE_OP_ALWAYS]                       = PREFILTEROPNEVER,
 };

-VkResult genX(CreateSampler)(
-    VkDevice                                    _device,
+static void
+pack_sampler_state(
+   struct anv_device *                          device,
+   struct anv_sampler *                         sampler,
     const VkSamplerCreateInfo*                  pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkSampler*                                  pSampler)
+   uint32_t                                     offset,
+   void *                                       dest)
 {
-   ANV_FROM_HANDLE(anv_device, device, _device);
-   struct anv_sampler *sampler;
-
-   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
+#if GEN_IS_HASWELL
+   static const uint32_t haswell_border_color_offset[] = {
+      [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = 0,
+      [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = 0,

-   sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
-                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (!sampler)
-      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+      [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = 1,
+      [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = 1,

-   uint32_t border_color_offset = device->border_colors.offset +
-                                  pCreateInfo->borderColor * 64;
+      [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = 2,
+      [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = 2,
+   };
+   uint32_t color_index =
+      ARRAY_SIZE(sampler->state) *
+      haswell_border_color_offset[pCreateInfo->borderColor] + offset;
+#else
+   uint32_t color_index = pCreateInfo->borderColor;
+#endif
+   uint32_t color_offset =
+      device->border_colors.offset +
+      color_index * device->border_color_align;

    struct GENX(SAMPLER_STATE) sampler_state = {
       .SamplerDisable = false,
@@ -195,7 +368,7 @@ VkResult genX(CreateSampler)(
       .ShadowFunction = vk_to_gen_shadow_compare_op[pCreateInfo->compareOp],
       .CubeSurfaceControlMode = OVERRIDE,

-      .BorderColorPointer = border_color_offset,
+      .BorderColorPointer = color_offset,

 #if GEN_GEN >= 8
       .LODClampMagnificationMode = MIPNONE,
@@ -215,7 +388,31 @@ VkResult genX(CreateSampler)(
       .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW],
    };

-   GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state);
+   GENX(SAMPLER_STATE_pack)(NULL, dest, &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 = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
+                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!sampler)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   pack_sampler_state(device, sampler, pCreateInfo, 0, sampler->state[0]);
+#if GEN_IS_HASWELL
+   for (uint32_t i = 1; i < ARRAY_SIZE(sampler->state); i++)
+      pack_sampler_state(device, sampler, pCreateInfo, i, sampler->state[i]);
+#endif

    *pSampler = anv_sampler_to_handle(sampler);

--
2.9.3


More information about the mesa-dev mailing list