* Vulkan. These correspond to the Vulkan "standard sample locations".
*/
+/* Examples:
+ * in case of GEN_GEN < 8:
+ * GEN_SAMPLE_POS_ELEM(ms.Sample, info->pSampleLocations, 0); expands to:
+ * ms.Sample0XOffset = info->pSampleLocations[0].x;
+ * ms.Sample0YOffset = info->pSampleLocations[0].y;
+ *
+ * in case of GEN_GEN >= 8:
+ * GEN_SAMPLE_POS_ELEM(sp._16xSample, info->pSampleLocations, 0); expands to:
+ * sp._16xSample0XOffset = info->pSampleLocations[0].x;
+ * sp._16xSample0YOffset = info->pSampleLocations[0].y;
+ */
+
+#define GEN_SAMPLE_POS_ELEM(prefix, arr, sample_idx) \
+prefix##sample_idx##XOffset = arr[sample_idx].x; \
+prefix##sample_idx##YOffset = arr[sample_idx].y;
+
+#define GEN_SAMPLE_POS_1X_ARRAY(prefix, arr)\
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 0);
+
+#define GEN_SAMPLE_POS_2X_ARRAY(prefix, arr) \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 0); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 1);
+
+#define GEN_SAMPLE_POS_4X_ARRAY(prefix, arr) \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 0); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 1); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 2); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 3);
+
+#define GEN_SAMPLE_POS_8X_ARRAY(prefix, arr) \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 0); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 1); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 2); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 3); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 4); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 5); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 6); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 7);
+
+#define GEN_SAMPLE_POS_16X_ARRAY(prefix, arr) \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 0); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 1); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 2); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 3); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 4); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 5); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 6); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 7); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 8); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 9); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 10); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 11); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 12); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 13); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 14); \
+ GEN_SAMPLE_POS_ELEM(prefix, arr, 15);
+
/**
* 1x MSAA has a single sample at the center: (0.5, 0.5) -> (0x8, 0x8).
*/
const unsigned entry_size[4],
enum gen_urb_deref_block_size *deref_block_size);
-void genX(emit_multisample)(struct anv_batch *batch, uint32_t samples);
+void genX(emit_multisample)(struct anv_batch *batch, uint32_t samples,
+ const VkSampleLocationEXT *locations);
-void genX(emit_sample_pattern)(struct anv_batch *batch);
+void genX(emit_sample_pattern)(struct anv_batch *batch, uint32_t samples,
+ const VkSampleLocationEXT *locations);
void genX(cmd_buffer_so_memcpy)(struct anv_cmd_buffer *cmd_buffer,
struct anv_address dst, struct anv_address src,
{
uint32_t samples = info ? info->rasterizationSamples : 1;
- genX(emit_multisample)(&pipeline->base.batch, samples);
+ genX(emit_multisample)(&pipeline->base.batch, samples, NULL);
/* From the Vulkan 1.0 spec:
* If pSampleMask is NULL, it is treated as if the mask has all bits
#if GEN_GEN >= 8
anv_batch_emit(&batch, GENX(3DSTATE_WM_CHROMAKEY), ck);
- genX(emit_sample_pattern)(&batch);
+ genX(emit_sample_pattern)(&batch, 0, NULL);
/* The BDW+ docs describe how to use the 3DSTATE_WM_HZ_OP instruction in the
* section titled, "Optimized Depth Buffer Clear and/or Stencil Buffer
}
void
-genX(emit_multisample)(struct anv_batch *batch, uint32_t samples)
+genX(emit_multisample)(struct anv_batch *batch, uint32_t samples,
+ const VkSampleLocationEXT *locations)
{
anv_batch_emit(batch, GENX(3DSTATE_MULTISAMPLE), ms) {
ms.NumberofMultisamples = __builtin_ffs(samples) - 1;
ms.PixelPositionOffsetEnable = false;
#else
- switch (samples) {
- case 1:
- GEN_SAMPLE_POS_1X(ms.Sample);
- break;
- case 2:
- GEN_SAMPLE_POS_2X(ms.Sample);
- break;
- case 4:
- GEN_SAMPLE_POS_4X(ms.Sample);
- break;
- case 8:
- GEN_SAMPLE_POS_8X(ms.Sample);
- break;
- default:
- break;
+ if (locations) {
+ switch (samples) {
+ case 1:
+ GEN_SAMPLE_POS_1X_ARRAY(ms.Sample, locations);
+ break;
+ case 2:
+ GEN_SAMPLE_POS_2X_ARRAY(ms.Sample, locations);
+ break;
+ case 4:
+ GEN_SAMPLE_POS_4X_ARRAY(ms.Sample, locations);
+ break;
+ case 8:
+ GEN_SAMPLE_POS_8X_ARRAY(ms.Sample, locations);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (samples) {
+ case 1:
+ GEN_SAMPLE_POS_1X(ms.Sample);
+ break;
+ case 2:
+ GEN_SAMPLE_POS_2X(ms.Sample);
+ break;
+ case 4:
+ GEN_SAMPLE_POS_4X(ms.Sample);
+ break;
+ case 8:
+ GEN_SAMPLE_POS_8X(ms.Sample);
+ break;
+ default:
+ break;
+ }
}
#endif
}
#if GEN_GEN >= 8
void
-genX(emit_sample_pattern)(struct anv_batch *batch)
+genX(emit_sample_pattern)(struct anv_batch *batch, uint32_t samples,
+ const VkSampleLocationEXT *locations)
{
/* See the Vulkan 1.0 spec Table 24.1 "Standard sample locations" and
* VkPhysicalDeviceFeatures::standardSampleLocations.
*/
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 (locations) {
+ /* The Skylake PRM Vol. 2a "3DSTATE_SAMPLE_PATTERN" says:
+ *
+ * "When programming the sample offsets (for NUMSAMPLES_4 or _8
+ * and MSRASTMODE_xxx_PATTERN), the order of the samples 0 to 3
+ * (or 7 for 8X, or 15 for 16X) must have monotonically increasing
+ * distance from the pixel center. This is required to get the
+ * correct centroid computation in the device."
+ *
+ * However, the Vulkan spec seems to require that the the samples
+ * occur in the order provided through the API. The standard sample
+ * patterns have the above property that they have monotonically
+ * increasing distances from the center but client-provided ones do
+ * not. As long as this only affects centroid calculations as the
+ * docs say, we should be ok because OpenGL and Vulkan only require
+ * that the centroid be some lit sample and that it's the same for
+ * all samples in a pixel; they have no requirement that it be the
+ * one closest to center.
+ */
+ switch (samples) {
+ case 1:
+ GEN_SAMPLE_POS_1X_ARRAY(sp._1xSample, locations);
+ break;
+ case 2:
+ GEN_SAMPLE_POS_2X_ARRAY(sp._2xSample, locations);
+ break;
+ case 4:
+ GEN_SAMPLE_POS_4X_ARRAY(sp._4xSample, locations);
+ break;
+ case 8:
+ GEN_SAMPLE_POS_8X_ARRAY(sp._8xSample, locations);
+ break;
#if GEN_GEN >= 9
- GEN_SAMPLE_POS_16X(sp._16xSample);
+ case 16:
+ GEN_SAMPLE_POS_16X_ARRAY(sp._16xSample, locations);
+ break;
#endif
+ default:
+ break;
+ }
+ } else {
+ 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
+ }
}
}
#endif