<div dir="ltr"><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 11, 2019 at 10:05 AM Eleni Maria Stea <<a href="mailto:estea@igalia.com">estea@igalia.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Allowing the user to set custom sample locations non-dynamically, by<br>
filling the extension structs and chaining them to the pipeline structs<br>
according to the Vulkan specification section [26.5. Custom Sample Locations]<br>
for the following structures:<br>
<br>
'VkPipelineSampleLocationsStateCreateInfoEXT'<br>
'VkSampleLocationsInfoEXT'<br>
'VkSampleLocationEXT'<br>
<br>
Once custom locations are used, the default locations are lost and need to be<br>
re-emitted again in the next pipeline creation. For that, we emit the<br>
3DSTATE_SAMPLE_PATTERN at every pipeline creation.<br>
---<br>
src/intel/common/gen_sample_positions.h | 53 ++++++++++++++++<br>
src/intel/vulkan/anv_genX.h | 5 ++<br>
src/intel/vulkan/anv_private.h | 9 +++<br>
src/intel/vulkan/anv_sample_locations.c | 38 +++++++++++-<br>
src/intel/vulkan/anv_sample_locations.h | 29 +++++++++<br>
src/intel/vulkan/genX_pipeline.c | 80 +++++++++++++++++++++----<br>
src/intel/vulkan/genX_state.c | 59 ++++++++++++++++++<br>
7 files changed, 259 insertions(+), 14 deletions(-)<br>
create mode 100644 src/intel/vulkan/anv_sample_locations.h<br>
<br>
diff --git a/src/intel/common/gen_sample_positions.h b/src/intel/common/gen_sample_positions.h<br>
index da48dcb5ed0..e8af2a552dc 100644<br>
--- a/src/intel/common/gen_sample_positions.h<br>
+++ b/src/intel/common/gen_sample_positions.h<br>
@@ -160,4 +160,57 @@ prefix##14YOffset = 0.9375; \<br>
prefix##15XOffset = 0.0625; \<br>
prefix##15YOffset = 0.0000;<br>
<br>
+/* Examples:<br>
+ * in case of GEN_GEN < 8:<br>
+ * SET_SAMPLE_POS(ms.Sample, 0); expands to:<br>
+ * ms.Sample0XOffset = anv_samples[0].offs_x;<br>
+ * ms.Sample0YOffset = anv_samples[0].offs_y;<br>
+ *<br>
+ * in case of GEN_GEN >= 8:<br>
+ * SET_SAMPLE_POS(sp._16xSample, 0); expands to:<br>
+ * sp._16xSample0XOffset = anv_samples[0].offs_x;<br>
+ * sp._16xSample0YOffset = anv_samples[0].offs_y;<br>
+ */<br>
+#define SET_SAMPLE_POS(prefix, sample_idx) \<br>
+prefix##sample_idx##XOffset = anv_samples[sample_idx].offs_x; \<br>
+prefix##sample_idx##YOffset = anv_samples[sample_idx].offs_y;<br>
+<br>
+#define SET_SAMPLE_POS_2X(prefix) \<br>
+SET_SAMPLE_POS(prefix, 0); \<br>
+SET_SAMPLE_POS(prefix, 1);<br>
+<br>
+#define SET_SAMPLE_POS_4X(prefix) \<br>
+SET_SAMPLE_POS(prefix, 0); \<br>
+SET_SAMPLE_POS(prefix, 1); \<br>
+SET_SAMPLE_POS(prefix, 2); \<br>
+SET_SAMPLE_POS(prefix, 3);<br>
+<br>
+#define SET_SAMPLE_POS_8X(prefix) \<br>
+SET_SAMPLE_POS(prefix, 0); \<br>
+SET_SAMPLE_POS(prefix, 1); \<br>
+SET_SAMPLE_POS(prefix, 2); \<br>
+SET_SAMPLE_POS(prefix, 3); \<br>
+SET_SAMPLE_POS(prefix, 4); \<br>
+SET_SAMPLE_POS(prefix, 5); \<br>
+SET_SAMPLE_POS(prefix, 6); \<br>
+SET_SAMPLE_POS(prefix, 7);<br>
+<br>
+#define SET_SAMPLE_POS_16X(prefix) \<br>
+SET_SAMPLE_POS(prefix, 0); \<br>
+SET_SAMPLE_POS(prefix, 1); \<br>
+SET_SAMPLE_POS(prefix, 2); \<br>
+SET_SAMPLE_POS(prefix, 3); \<br>
+SET_SAMPLE_POS(prefix, 4); \<br>
+SET_SAMPLE_POS(prefix, 5); \<br>
+SET_SAMPLE_POS(prefix, 6); \<br>
+SET_SAMPLE_POS(prefix, 7); \<br>
+SET_SAMPLE_POS(prefix, 8); \<br>
+SET_SAMPLE_POS(prefix, 9); \<br>
+SET_SAMPLE_POS(prefix, 10); \<br>
+SET_SAMPLE_POS(prefix, 11); \<br>
+SET_SAMPLE_POS(prefix, 12); \<br>
+SET_SAMPLE_POS(prefix, 13); \<br>
+SET_SAMPLE_POS(prefix, 14); \<br>
+SET_SAMPLE_POS(prefix, 15);<br>
+<br>
#endif /* GEN_SAMPLE_POSITIONS_H */<br>
diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h<br>
index 8fd32cabf1e..52415c04a45 100644<br>
--- a/src/intel/vulkan/anv_genX.h<br>
+++ b/src/intel/vulkan/anv_genX.h<br>
@@ -88,3 +88,8 @@ void genX(cmd_buffer_mi_memset)(struct anv_cmd_buffer *cmd_buffer,<br>
<br>
void genX(blorp_exec)(struct blorp_batch *batch,<br>
const struct blorp_params *params);<br>
+<br>
+void genX(emit_sample_locations)(struct anv_batch *batch,<br>
+ uint32_t num_samples,<br>
+ const VkSampleLocationsInfoEXT *sl,<br>
+ bool custom_locations);<br>
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h<br>
index 5905299e59d..981956e5706 100644<br>
--- a/src/intel/vulkan/anv_private.h<br>
+++ b/src/intel/vulkan/anv_private.h<br>
@@ -71,6 +71,7 @@ struct anv_buffer;<br>
struct anv_buffer_view;<br>
struct anv_image_view;<br>
struct anv_instance;<br>
+struct anv_sample;<br>
<br>
struct gen_l3_config;<br>
<br>
@@ -165,6 +166,7 @@ struct gen_l3_config;<br>
#define MAX_PUSH_DESCRIPTORS 32 /* Minimum requirement */<br>
#define MAX_INLINE_UNIFORM_BLOCK_SIZE 4096<br>
#define MAX_INLINE_UNIFORM_BLOCK_DESCRIPTORS 32<br>
+#define MAX_SAMPLE_LOCATIONS 16<br>
<br>
/* The kernel relocation API has a limitation of a 32-bit delta value<br>
* applied to the address before it is written which, in spite of it being<br>
@@ -2086,6 +2088,13 @@ struct anv_push_constants {<br>
struct brw_image_param images[MAX_GEN8_IMAGES];<br>
};<br>
<br>
+struct<br>
+anv_sample {<br>
+ float offs_x;<br>
+ float offs_y;<br>
+ float radius;<br>
+};<br>
+<br>
struct anv_dynamic_state {<br>
struct {<br>
uint32_t count;<br>
diff --git a/src/intel/vulkan/anv_sample_locations.c b/src/intel/vulkan/anv_sample_locations.c<br>
index 1ebf280e05b..c660cb5ae84 100644<br>
--- a/src/intel/vulkan/anv_sample_locations.c<br>
+++ b/src/intel/vulkan/anv_sample_locations.c<br>
@@ -21,7 +21,7 @@<br>
* IN THE SOFTWARE.<br>
*/<br>
<br>
-#include "anv_private.h"<br>
+#include "anv_sample_locations.h"<br>
<br>
void<br>
anv_GetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice physicalDevice,<br>
@@ -58,3 +58,39 @@ anv_GetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice physicalDevice,<br>
.maxSampleLocationGridSize = grid_size<br>
};<br>
}<br>
+<br>
+static int<br>
+compare_samples(const void *a, const void *b)<br>
+{<br>
+ struct anv_sample *s1 = (struct anv_sample *)a;<br>
+ struct anv_sample *s2 = (struct anv_sample *)b;<br>
+<br>
+ return s1->radius - s2->radius;<br>
+}<br>
+<br>
+void<br>
+anv_calc_sample_locations(struct anv_sample *samples,<br>
+ uint32_t num_samples,<br>
+ const VkSampleLocationsInfoEXT *info)<br>
+{<br>
+ int i;<br>
+<br>
+ for(i = 0; i < num_samples; i++) {<br>
+ float dx, dy;<br>
+<br>
+ /* this is because the grid is 1x1, in case that<br>
+ * we support different grid sizes in the future<br>
+ * this must be changed.<br>
+ */<br>
+ samples[i].offs_x = info->pSampleLocations[i].x;<br>
+ samples[i].offs_y = info->pSampleLocations[i].y;<br>
+<br>
+ /* distance from the center */<br>
+ dx = samples[i].offs_x - 0.5;<br>
+ dy = samples[i].offs_y - 0.5;<br>
+<br>
+ samples[i].radius = dx * dx + dy * dy;<br>
+ }<br>
+<br>
+ qsort(samples, num_samples, sizeof *samples, compare_samples);<br></blockquote><div><br></div><div>Are we allowed to re-order the samples like this? The spec says:</div><div><br></div><div>The sample location for sample <span class="eq">i</span> at the pixel grid location
<span class="eq">(x,y)</span> is taken from <span class="eq"><code>pSampleLocations</code>[(x + y *
<code>sampleLocationGridSize.width</code>) * <code>sampleLocationsPerPixel</code> + i]</span></div><div><span class="eq"><br></span></div><div><span class="eq">Which leads me to think that they expect the ordering of samples to be respected. Yes, I know the HW docs say we're supposed to order them from nearest to furthest. However, AFAIK, that's only so we get nice centroids and I don't know that it's actually required.</span></div><div><span class="eq"><br></span></div><div><span class="eq">--Jason<br></span></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+}<br>
diff --git a/src/intel/vulkan/anv_sample_locations.h b/src/intel/vulkan/anv_sample_locations.h<br>
new file mode 100644<br>
index 00000000000..000d04aca08<br>
--- /dev/null<br>
+++ b/src/intel/vulkan/anv_sample_locations.h<br>
@@ -0,0 +1,29 @@<br>
+/*<br>
+ * Copyright © 2019 Intel Corporation<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include "anv_private.h"<br>
+<br>
+void<br>
+anv_calc_sample_locations(struct anv_sample *samples,<br>
+ uint32_t num_samples,<br>
+ const VkSampleLocationsInfoEXT *info);<br>
diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c<br>
index 975052deb79..feb431e10cd 100644<br>
--- a/src/intel/vulkan/genX_pipeline.c<br>
+++ b/src/intel/vulkan/genX_pipeline.c<br>
@@ -22,6 +22,7 @@<br>
*/<br>
<br>
#include "anv_private.h"<br>
+#include "anv_sample_locations.h"<br>
<br>
#include "genxml/gen_macros.h"<br>
#include "genxml/genX_pack.h"<br>
@@ -548,12 +549,9 @@ emit_rs_state(struct anv_pipeline *pipeline,<br>
}<br>
<br>
static void<br>
-emit_ms_state(struct anv_pipeline *pipeline,<br>
- const VkPipelineMultisampleStateCreateInfo *info)<br>
+emit_sample_mask(struct anv_pipeline *pipeline,<br>
+ const VkPipelineMultisampleStateCreateInfo *info)<br>
{<br>
- uint32_t samples = 1;<br>
- uint32_t log2_samples = 0;<br>
-<br>
/* From the Vulkan 1.0 spec:<br>
* If pSampleMask is NULL, it is treated as if the mask has all bits<br>
* enabled, i.e. no coverage is removed from fragments.<br>
@@ -566,14 +564,19 @@ emit_ms_state(struct anv_pipeline *pipeline,<br>
uint32_t sample_mask = 0xff;<br>
#endif<br>
<br>
- if (info) {<br>
- samples = info->rasterizationSamples;<br>
- log2_samples = __builtin_ffs(samples) - 1;<br>
- }<br>
-<br>
if (info && info->pSampleMask)<br>
sample_mask &= info->pSampleMask[0];<br>
<br>
+ anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) {<br>
+ sm.SampleMask = sample_mask;<br>
+ }<br>
+}<br>
+<br>
+static void<br>
+emit_multisample(struct anv_pipeline *pipeline,<br>
+ uint32_t samples,<br>
+ uint32_t log2_samples)<br>
+{<br>
anv_batch_emit(&pipeline->batch, GENX(3DSTATE_MULTISAMPLE), ms) {<br>
ms.NumberofMultisamples = log2_samples;<br>
<br>
@@ -605,10 +608,61 @@ emit_ms_state(struct anv_pipeline *pipeline,<br>
}<br>
#endif<br>
}<br>
+}<br>
<br>
- anv_batch_emit(&pipeline->batch, GENX(3DSTATE_SAMPLE_MASK), sm) {<br>
- sm.SampleMask = sample_mask;<br>
+static void<br>
+emit_ms_state(struct anv_pipeline *pipeline,<br>
+ const VkPipelineMultisampleStateCreateInfo *info,<br>
+ const VkPipelineDynamicStateCreateInfo *dinfo)<br>
+{<br>
+#if GEN_GEN >= 8<br>
+ bool custom_locations = false;<br>
+ VkSampleLocationsInfoEXT *sl;<br>
+#endif<br>
+<br>
+ uint32_t samples = 1;<br>
+ uint32_t log2_samples = 0;<br>
+<br>
+ emit_sample_mask(pipeline, info);<br>
+<br>
+ if (info) {<br>
+ samples = info->rasterizationSamples;<br>
+<br>
+#if GEN_GEN >= 8<br>
+ if (info->pNext) {<br>
+ VkPipelineSampleLocationsStateCreateInfoEXT *slinfo =<br>
+ (VkPipelineSampleLocationsStateCreateInfoEXT *)info->pNext;<br>
+<br>
+ if (slinfo &&<br>
+ (slinfo->sType ==<br>
+ VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT)) {<br>
+ if (slinfo->sampleLocationsEnable == VK_TRUE) {<br>
+ uint32_t i;<br>
+<br>
+ for (i = 0; i < dinfo->dynamicStateCount; i++) {<br>
+ if (dinfo->pDynamicStates[i] ==<br>
+ VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT)<br>
+ return;<br>
+ }<br>
+<br>
+ if ((sl = &slinfo->sampleLocationsInfo))<br>
+ samples = sl->sampleLocationsPerPixel;<br>
+<br>
+ custom_locations = true;<br>
+ }<br>
+ }<br>
+ }<br>
+#endif<br>
+<br>
+ log2_samples = __builtin_ffs(samples) - 1;<br>
}<br>
+<br>
+ emit_multisample(pipeline, samples, log2_samples);<br>
+<br>
+#if GEN_GEN >= 8<br>
+ genX(emit_sample_locations)(&pipeline->batch, samples, sl,<br>
+ custom_locations);<br>
+#endif<br>
}<br>
<br>
static const uint32_t vk_to_gen_logic_op[] = {<br>
@@ -1938,7 +1992,7 @@ genX(graphics_pipeline_create)(<br>
assert(pCreateInfo->pRasterizationState);<br>
emit_rs_state(pipeline, pCreateInfo->pRasterizationState,<br>
pCreateInfo->pMultisampleState, pass, subpass);<br>
- emit_ms_state(pipeline, pCreateInfo->pMultisampleState);<br>
+ emit_ms_state(pipeline, pCreateInfo->pMultisampleState, pCreateInfo->pDynamicState);<br>
emit_ds_state(pipeline, pCreateInfo->pDepthStencilState, pass, subpass);<br>
emit_cb_state(pipeline, pCreateInfo->pColorBlendState,<br>
pCreateInfo->pMultisampleState);<br>
diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c<br>
index cffd1e47247..c14e502a68d 100644<br>
--- a/src/intel/vulkan/genX_state.c<br>
+++ b/src/intel/vulkan/genX_state.c<br>
@@ -28,6 +28,7 @@<br>
#include <fcntl.h><br>
<br>
#include "anv_private.h"<br>
+#include "anv_sample_locations.h"<br>
<br>
#include "common/gen_sample_positions.h"<br>
#include "genxml/gen_macros.h"<br>
@@ -435,3 +436,61 @@ VkResult genX(CreateSampler)(<br>
<br>
return VK_SUCCESS;<br>
}<br>
+<br>
+void<br>
+genX(emit_sample_locations)(struct anv_batch *batch,<br>
+ uint32_t num_samples,<br>
+ const VkSampleLocationsInfoEXT *sl,<br>
+ bool custom_locations)<br>
+{<br>
+#if GEN_GEN >= 8<br>
+ struct anv_sample anv_samples[MAX_SAMPLE_LOCATIONS];<br>
+<br>
+#if GEN_GEN == 10<br>
+ gen10_emit_wa_cs_stall_flush(batch);<br>
+#endif<br>
+<br>
+ if (custom_locations) {<br>
+ anv_calc_sample_locations(anv_samples, num_samples, sl);<br>
+<br>
+ anv_batch_emit(batch, GENX(3DSTATE_SAMPLE_PATTERN), sp) {<br>
+ switch (num_samples) {<br>
+ case 1:<br>
+ SET_SAMPLE_POS(sp._1xSample, 0);<br>
+ break;<br>
+ case 2:<br>
+ SET_SAMPLE_POS_2X(sp._2xSample);<br>
+ break;<br>
+ case 4:<br>
+ SET_SAMPLE_POS_4X(sp._4xSample);<br>
+ break;<br>
+ case 8:<br>
+ SET_SAMPLE_POS_8X(sp._8xSample);<br>
+ break;<br>
+#if GEN_GEN >= 9<br>
+ case 16:<br>
+ SET_SAMPLE_POS_16X(sp._16xSample);<br>
+ break;<br>
+#endif<br>
+ default:<br>
+ break;<br>
+ }<br>
+ }<br>
+ } else {<br>
+ anv_batch_emit(batch, GENX(3DSTATE_SAMPLE_PATTERN), sp) {<br>
+ GEN_SAMPLE_POS_1X(sp._1xSample);<br>
+ GEN_SAMPLE_POS_2X(sp._2xSample);<br>
+ GEN_SAMPLE_POS_4X(sp._4xSample);<br>
+ GEN_SAMPLE_POS_8X(sp._8xSample);<br>
+#if GEN_GEN >= 9<br>
+ GEN_SAMPLE_POS_16X(sp._16xSample);<br>
+#endif<br>
+ }<br>
+ }<br>
+<br>
+#if GEN_GEN == 10<br>
+ gen10_emit_wa_lri_to_cache_mode_zero(batch);<br>
+#endif<br>
+<br>
+#endif<br>
+}<br>
-- <br>
2.20.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a></blockquote></div></div>