[Mesa-dev] [PATCH v2 4/9] anv: Added support for non-dynamic sample locations on Gen8+

Eleni Maria Stea estea at igalia.com
Tue Mar 12 10:34:49 UTC 2019


Allowing the user to set custom sample locations non-dynamically, by
filling the extension structs and chaining them to the pipeline structs
according to the Vulkan specification section [26.5. Custom Sample Locations]
for the following structures:

'VkPipelineSampleLocationsStateCreateInfoEXT'
'VkSampleLocationsInfoEXT'
'VkSampleLocationEXT'

Once custom locations are used, the default locations are lost and need to be
re-emitted again in the next pipeline creation. For that, we emit the
3DSTATE_SAMPLE_PATTERN at every pipeline creation.
---
 src/intel/common/gen_sample_positions.h | 53 ++++++++++++++++
 src/intel/vulkan/anv_genX.h             |  5 ++
 src/intel/vulkan/anv_private.h          |  9 +++
 src/intel/vulkan/anv_sample_locations.c | 38 +++++++++++-
 src/intel/vulkan/anv_sample_locations.h | 29 +++++++++
 src/intel/vulkan/genX_pipeline.c        | 80 +++++++++++++++++++++----
 src/intel/vulkan/genX_state.c           | 59 ++++++++++++++++++
 7 files changed, 259 insertions(+), 14 deletions(-)
 create mode 100644 src/intel/vulkan/anv_sample_locations.h

diff --git a/src/intel/common/gen_sample_positions.h b/src/intel/common/gen_sample_positions.h
index da48dcb5ed0..e8af2a552dc 100644
--- a/src/intel/common/gen_sample_positions.h
+++ b/src/intel/common/gen_sample_positions.h
@@ -160,4 +160,57 @@ prefix##14YOffset  = 0.9375; \
 prefix##15XOffset  = 0.0625; \
 prefix##15YOffset  = 0.0000;
 
+/* Examples:
+ * in case of GEN_GEN < 8:
+ * SET_SAMPLE_POS(ms.Sample, 0); expands to:
+ *    ms.Sample0XOffset = anv_samples[0].offs_x;
+ *    ms.Sample0YOffset = anv_samples[0].offs_y;
+ *
+ * in case of GEN_GEN >= 8:
+ * SET_SAMPLE_POS(sp._16xSample, 0); expands to:
+ *    sp._16xSample0XOffset = anv_samples[0].offs_x;
+ *    sp._16xSample0YOffset = anv_samples[0].offs_y;
+ */
+#define SET_SAMPLE_POS(prefix, sample_idx) \
+prefix##sample_idx##XOffset = anv_samples[sample_idx].offs_x; \
+prefix##sample_idx##YOffset = anv_samples[sample_idx].offs_y;
+
+#define SET_SAMPLE_POS_2X(prefix) \
+SET_SAMPLE_POS(prefix, 0); \
+SET_SAMPLE_POS(prefix, 1);
+
+#define SET_SAMPLE_POS_4X(prefix) \
+SET_SAMPLE_POS(prefix, 0); \
+SET_SAMPLE_POS(prefix, 1); \
+SET_SAMPLE_POS(prefix, 2); \
+SET_SAMPLE_POS(prefix, 3);
+
+#define SET_SAMPLE_POS_8X(prefix) \
+SET_SAMPLE_POS(prefix, 0); \
+SET_SAMPLE_POS(prefix, 1); \
+SET_SAMPLE_POS(prefix, 2); \
+SET_SAMPLE_POS(prefix, 3); \
+SET_SAMPLE_POS(prefix, 4); \
+SET_SAMPLE_POS(prefix, 5); \
+SET_SAMPLE_POS(prefix, 6); \
+SET_SAMPLE_POS(prefix, 7);
+
+#define SET_SAMPLE_POS_16X(prefix) \
+SET_SAMPLE_POS(prefix, 0); \
+SET_SAMPLE_POS(prefix, 1); \
+SET_SAMPLE_POS(prefix, 2); \
+SET_SAMPLE_POS(prefix, 3); \
+SET_SAMPLE_POS(prefix, 4); \
+SET_SAMPLE_POS(prefix, 5); \
+SET_SAMPLE_POS(prefix, 6); \
+SET_SAMPLE_POS(prefix, 7); \
+SET_SAMPLE_POS(prefix, 8); \
+SET_SAMPLE_POS(prefix, 9); \
+SET_SAMPLE_POS(prefix, 10); \
+SET_SAMPLE_POS(prefix, 11); \
+SET_SAMPLE_POS(prefix, 12); \
+SET_SAMPLE_POS(prefix, 13); \
+SET_SAMPLE_POS(prefix, 14); \
+SET_SAMPLE_POS(prefix, 15);
+
 #endif /* GEN_SAMPLE_POSITIONS_H */
diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h
index 8fd32cabf1e..52415c04a45 100644
--- a/src/intel/vulkan/anv_genX.h
+++ b/src/intel/vulkan/anv_genX.h
@@ -88,3 +88,8 @@ void genX(cmd_buffer_mi_memset)(struct anv_cmd_buffer *cmd_buffer,
 
 void genX(blorp_exec)(struct blorp_batch *batch,
                       const struct blorp_params *params);
+
+void genX(emit_sample_locations)(struct anv_batch *batch,
+                                 uint32_t num_samples,
+                                 const VkSampleLocationsInfoEXT *sl,
+                                 bool custom_locations);
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 5905299e59d..981956e5706 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -71,6 +71,7 @@ struct anv_buffer;
 struct anv_buffer_view;
 struct anv_image_view;
 struct anv_instance;
+struct anv_sample;
 
 struct gen_l3_config;
 
@@ -165,6 +166,7 @@ struct gen_l3_config;
 #define MAX_PUSH_DESCRIPTORS 32 /* Minimum requirement */
 #define MAX_INLINE_UNIFORM_BLOCK_SIZE 4096
 #define MAX_INLINE_UNIFORM_BLOCK_DESCRIPTORS 32
+#define MAX_SAMPLE_LOCATIONS 16
 
 /* The kernel relocation API has a limitation of a 32-bit delta value
  * applied to the address before it is written which, in spite of it being
@@ -2086,6 +2088,13 @@ struct anv_push_constants {
    struct brw_image_param images[MAX_GEN8_IMAGES];
 };
 
+struct
+anv_sample {
+   float offs_x;
+   float offs_y;
+   float radius;
+};
+
 struct anv_dynamic_state {
    struct {
       uint32_t                                  count;
diff --git a/src/intel/vulkan/anv_sample_locations.c b/src/intel/vulkan/anv_sample_locations.c
index 1ebf280e05b..c660cb5ae84 100644
--- a/src/intel/vulkan/anv_sample_locations.c
+++ b/src/intel/vulkan/anv_sample_locations.c
@@ -21,7 +21,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "anv_private.h"
+#include "anv_sample_locations.h"
 
 void
 anv_GetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice physicalDevice,
@@ -58,3 +58,39 @@ anv_GetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice physicalDevice,
       .maxSampleLocationGridSize = grid_size
    };
 }
+
+static int
+compare_samples(const void *a, const void *b)
+{
+   struct anv_sample *s1 = (struct anv_sample *)a;
+   struct anv_sample *s2 = (struct anv_sample *)b;
+
+   return s1->radius - s2->radius;
+}
+
+void
+anv_calc_sample_locations(struct anv_sample *samples,
+                          uint32_t num_samples,
+                          const VkSampleLocationsInfoEXT *info)
+{
+   int i;
+
+   for(i = 0; i < num_samples; i++) {
+      float dx, dy;
+
+      /* this is because the grid is 1x1, in case that
+       * we support different grid sizes in the future
+       * this must be changed.
+       */
+      samples[i].offs_x = info->pSampleLocations[i].x;
+      samples[i].offs_y = info->pSampleLocations[i].y;
+
+      /* distance from the center */
+      dx = samples[i].offs_x - 0.5;
+      dy = samples[i].offs_y - 0.5;
+
+      samples[i].radius = dx * dx + dy * dy;
+   }
+
+   qsort(samples, num_samples, sizeof *samples, compare_samples);
+}
diff --git a/src/intel/vulkan/anv_sample_locations.h b/src/intel/vulkan/anv_sample_locations.h
new file mode 100644
index 00000000000..000d04aca08
--- /dev/null
+++ b/src/intel/vulkan/anv_sample_locations.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "anv_private.h"
+
+void
+anv_calc_sample_locations(struct anv_sample *samples,
+                          uint32_t num_samples,
+                          const VkSampleLocationsInfoEXT *info);
diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c
index 975052deb79..feb431e10cd 100644
--- a/src/intel/vulkan/genX_pipeline.c
+++ b/src/intel/vulkan/genX_pipeline.c
@@ -22,6 +22,7 @@
  */
 
 #include "anv_private.h"
+#include "anv_sample_locations.h"
 
 #include "genxml/gen_macros.h"
 #include "genxml/genX_pack.h"
@@ -548,12 +549,9 @@ emit_rs_state(struct anv_pipeline *pipeline,
 }
 
 static void
-emit_ms_state(struct anv_pipeline *pipeline,
-              const VkPipelineMultisampleStateCreateInfo *info)
+emit_sample_mask(struct anv_pipeline *pipeline,
+                 const VkPipelineMultisampleStateCreateInfo *info)
 {
-   uint32_t samples = 1;
-   uint32_t log2_samples = 0;
-
    /* From the Vulkan 1.0 spec:
     *    If pSampleMask is NULL, it is treated as if the mask has all bits
     *    enabled, i.e. no coverage is removed from fragments.
@@ -566,14 +564,19 @@ emit_ms_state(struct anv_pipeline *pipeline,
    uint32_t sample_mask = 0xff;
 #endif
 
-   if (info) {
-      samples = info->rasterizationSamples;
-      log2_samples = __builtin_ffs(samples) - 1;
-   }
-
    if (info && info->pSampleMask)
       sample_mask &= info->pSampleMask[0];
 
+   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) {
+      sm.SampleMask = sample_mask;
+   }
+}
+
+static void
+emit_multisample(struct anv_pipeline *pipeline,
+                 uint32_t samples,
+                 uint32_t log2_samples)
+{
    anv_batch_emit(&pipeline->batch, GENX(3DSTATE_MULTISAMPLE), ms) {
       ms.NumberofMultisamples       = log2_samples;
 
@@ -605,10 +608,61 @@ emit_ms_state(struct anv_pipeline *pipeline,
       }
 #endif
    }
+}
 
-   anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) {
-      sm.SampleMask = sample_mask;
+static void
+emit_ms_state(struct anv_pipeline *pipeline,
+              const VkPipelineMultisampleStateCreateInfo *info,
+              const VkPipelineDynamicStateCreateInfo *dinfo)
+{
+#if GEN_GEN >= 8
+   bool custom_locations = false;
+   VkSampleLocationsInfoEXT *sl;
+#endif
+
+   uint32_t samples = 1;
+   uint32_t log2_samples = 0;
+
+   emit_sample_mask(pipeline, info);
+
+   if (info) {
+      samples = info->rasterizationSamples;
+
+#if GEN_GEN >= 8
+      if (info->pNext) {
+         VkPipelineSampleLocationsStateCreateInfoEXT *slinfo =
+            (VkPipelineSampleLocationsStateCreateInfoEXT *)info->pNext;
+
+         if (slinfo &&
+               (slinfo->sType ==
+                VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT)) {
+            if (slinfo->sampleLocationsEnable == VK_TRUE) {
+               uint32_t i;
+
+               for (i = 0; i < dinfo->dynamicStateCount; i++) {
+                  if (dinfo->pDynamicStates[i] ==
+                      VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT)
+                     return;
+               }
+
+               if ((sl = &slinfo->sampleLocationsInfo))
+                  samples = sl->sampleLocationsPerPixel;
+
+               custom_locations = true;
+            }
+         }
+      }
+#endif
+
+      log2_samples = __builtin_ffs(samples) - 1;
    }
+
+   emit_multisample(pipeline, samples, log2_samples);
+
+#if GEN_GEN >= 8
+   genX(emit_sample_locations)(&pipeline->batch, samples, sl,
+                               custom_locations);
+#endif
 }
 
 static const uint32_t vk_to_gen_logic_op[] = {
@@ -1938,7 +1992,7 @@ genX(graphics_pipeline_create)(
    assert(pCreateInfo->pRasterizationState);
    emit_rs_state(pipeline, pCreateInfo->pRasterizationState,
                  pCreateInfo->pMultisampleState, pass, subpass);
-   emit_ms_state(pipeline, pCreateInfo->pMultisampleState);
+   emit_ms_state(pipeline, pCreateInfo->pMultisampleState, pCreateInfo->pDynamicState);
    emit_ds_state(pipeline, pCreateInfo->pDepthStencilState, pass, subpass);
    emit_cb_state(pipeline, pCreateInfo->pColorBlendState,
                            pCreateInfo->pMultisampleState);
diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c
index cffd1e47247..c14e502a68d 100644
--- a/src/intel/vulkan/genX_state.c
+++ b/src/intel/vulkan/genX_state.c
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 
 #include "anv_private.h"
+#include "anv_sample_locations.h"
 
 #include "common/gen_sample_positions.h"
 #include "genxml/gen_macros.h"
@@ -435,3 +436,61 @@ VkResult genX(CreateSampler)(
 
    return VK_SUCCESS;
 }
+
+void
+genX(emit_sample_locations)(struct anv_batch *batch,
+                            uint32_t num_samples,
+                            const VkSampleLocationsInfoEXT *sl,
+                            bool custom_locations)
+{
+#if GEN_GEN >= 8
+   struct anv_sample anv_samples[MAX_SAMPLE_LOCATIONS];
+
+#if GEN_GEN == 10
+   gen10_emit_wa_cs_stall_flush(batch);
+#endif
+
+   if (custom_locations) {
+      anv_calc_sample_locations(anv_samples, num_samples, sl);
+
+      anv_batch_emit(batch,  GENX(3DSTATE_SAMPLE_PATTERN), sp) {
+         switch (num_samples) {
+         case 1:
+            SET_SAMPLE_POS(sp._1xSample, 0);
+            break;
+         case 2:
+            SET_SAMPLE_POS_2X(sp._2xSample);
+            break;
+         case 4:
+            SET_SAMPLE_POS_4X(sp._4xSample);
+            break;
+         case 8:
+            SET_SAMPLE_POS_8X(sp._8xSample);
+            break;
+#if GEN_GEN >= 9
+         case 16:
+            SET_SAMPLE_POS_16X(sp._16xSample);
+            break;
+#endif
+         default:
+            break;
+         }
+      }
+   } else {
+      anv_batch_emit(batch, GENX(3DSTATE_SAMPLE_PATTERN), sp) {
+         GEN_SAMPLE_POS_1X(sp._1xSample);
+         GEN_SAMPLE_POS_2X(sp._2xSample);
+         GEN_SAMPLE_POS_4X(sp._4xSample);
+         GEN_SAMPLE_POS_8X(sp._8xSample);
+#if GEN_GEN >= 9
+         GEN_SAMPLE_POS_16X(sp._16xSample);
+#endif
+      }
+   }
+
+#if GEN_GEN == 10
+   gen10_emit_wa_lri_to_cache_mode_zero(batch);
+#endif
+
+#endif
+}
-- 
2.20.1



More information about the mesa-dev mailing list