On Mon, Mar 11, 2019 at 10:05 AM Eleni Maria Stea <es...@igalia.com> wrote:
> 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); > Are we allowed to re-order the samples like this? The spec says: The sample location for sample i at the pixel grid location (x,y) is taken from pSampleLocations[(x + y * sampleLocationGridSize.width) * sampleLocationsPerPixel + i] 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. --Jason > +} > 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 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev