anv: Add support for sample locations
Allowing the user to set custom sample locations, 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. v2: In v1, we used the custom anv_sample struct to store the location and the distance from the pixel center because we would then use this distance to sort the locations and send them in increasing monotonical order to the GPU. That was because the Skylake PRM Vol. 2a "3DSTATE_SAMPLE_PATTERN" says that the samples must have monotonically increasing distance from the pixel center to get the correct centroid computation in the device. However, the Vulkan spec seems to require that the samples occur in the order provided through the API and this requirement is only for the standard locations. 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. (Jason Ekstrand) For that we made the following changes: 1- We removed the custom structs and functions from anv_private.h and anv_sample_locations.h and anv_sample_locations.c (the last two files were removed). (Jason Ekstrand) 2- We modified the macros used to take also the array as parameter and we renamed them to start by GEN_. (Jason Ekstrand) 3- We don't sort the samples anymore. (Jason Ekstrand) v3 (Jason Ekstrand): Break the refactoring out into multiple commits v4: Merge dynamic/non-dynamic changes into a single commit (Lionel) Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/1887>
This commit is contained in:
parent
43acc10bd0
commit
27ee40f4c9
|
@ -188,6 +188,14 @@ anv_dynamic_state_copy(struct anv_dynamic_state *dest,
|
||||||
ANV_CMP_COPY(dyn_vbo_stride, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE);
|
ANV_CMP_COPY(dyn_vbo_stride, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE);
|
||||||
ANV_CMP_COPY(dyn_vbo_size, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE);
|
ANV_CMP_COPY(dyn_vbo_size, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE);
|
||||||
|
|
||||||
|
if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
|
||||||
|
dest->sample_locations.samples = src->sample_locations.samples;
|
||||||
|
typed_memcpy(dest->sample_locations.locations,
|
||||||
|
src->sample_locations.locations,
|
||||||
|
dest->sample_locations.samples);
|
||||||
|
changed |= ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
|
||||||
|
}
|
||||||
|
|
||||||
#undef ANV_CMP_COPY
|
#undef ANV_CMP_COPY
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
|
@ -687,6 +695,22 @@ void anv_CmdSetStencilReference(
|
||||||
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE;
|
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void anv_CmdSetSampleLocationsEXT(
|
||||||
|
VkCommandBuffer commandBuffer,
|
||||||
|
const VkSampleLocationsInfoEXT* pSampleLocationsInfo)
|
||||||
|
{
|
||||||
|
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||||
|
|
||||||
|
struct anv_dynamic_state *dyn_state = &cmd_buffer->state.gfx.dynamic;
|
||||||
|
uint32_t samples = pSampleLocationsInfo->sampleLocationsPerPixel;
|
||||||
|
|
||||||
|
dyn_state->sample_locations.samples = samples;
|
||||||
|
typed_memcpy(dyn_state->sample_locations.locations,
|
||||||
|
pSampleLocationsInfo->pSampleLocations, samples);
|
||||||
|
|
||||||
|
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
|
||||||
|
}
|
||||||
|
|
||||||
void anv_CmdSetLineStippleEXT(
|
void anv_CmdSetLineStippleEXT(
|
||||||
VkCommandBuffer commandBuffer,
|
VkCommandBuffer commandBuffer,
|
||||||
uint32_t lineStippleFactor,
|
uint32_t lineStippleFactor,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "util/os_time.h"
|
#include "util/os_time.h"
|
||||||
#include "common/gen_l3_config.h"
|
#include "common/gen_l3_config.h"
|
||||||
#include "common/gen_disasm.h"
|
#include "common/gen_disasm.h"
|
||||||
|
#include "common/gen_sample_positions.h"
|
||||||
#include "anv_private.h"
|
#include "anv_private.h"
|
||||||
#include "compiler/brw_nir.h"
|
#include "compiler/brw_nir.h"
|
||||||
#include "anv_nir.h"
|
#include "anv_nir.h"
|
||||||
|
@ -2044,6 +2045,34 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (states & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
|
||||||
|
const VkPipelineMultisampleStateCreateInfo *ms_info =
|
||||||
|
pCreateInfo->pMultisampleState;
|
||||||
|
const VkPipelineSampleLocationsStateCreateInfoEXT *sl_info = ms_info ?
|
||||||
|
vk_find_struct_const(ms_info, PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT) : NULL;
|
||||||
|
|
||||||
|
if (sl_info) {
|
||||||
|
dynamic->sample_locations.samples =
|
||||||
|
sl_info->sampleLocationsInfo.sampleLocationsCount;
|
||||||
|
const VkSampleLocationEXT *positions =
|
||||||
|
sl_info->sampleLocationsInfo.pSampleLocations;
|
||||||
|
for (uint32_t i = 0; i < dynamic->sample_locations.samples; i++) {
|
||||||
|
dynamic->sample_locations.locations[i].x = positions[i].x;
|
||||||
|
dynamic->sample_locations.locations[i].y = positions[i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dynamic->sample_locations.samples =
|
||||||
|
ms_info ? ms_info->rasterizationSamples : 1;
|
||||||
|
const struct gen_sample_position *positions =
|
||||||
|
gen_get_sample_positions(dynamic->sample_locations.samples);
|
||||||
|
for (uint32_t i = 0; i < dynamic->sample_locations.samples; i++) {
|
||||||
|
dynamic->sample_locations.locations[i].x = positions[i].x;
|
||||||
|
dynamic->sample_locations.locations[i].y = positions[i].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pipeline->dynamic_state_mask = states;
|
pipeline->dynamic_state_mask = states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ struct gen_perf_query_result;
|
||||||
#define ANV_SSBO_ALIGNMENT 4
|
#define ANV_SSBO_ALIGNMENT 4
|
||||||
#define ANV_SSBO_BOUNDS_CHECK_ALIGNMENT 4
|
#define ANV_SSBO_BOUNDS_CHECK_ALIGNMENT 4
|
||||||
#define MAX_VIEWS_FOR_PRIMITIVE_REPLICATION 16
|
#define MAX_VIEWS_FOR_PRIMITIVE_REPLICATION 16
|
||||||
|
#define MAX_SAMPLE_LOCATIONS 16
|
||||||
|
|
||||||
/* From the Skylake PRM Vol. 7 "Binding Table Surface State Model":
|
/* From the Skylake PRM Vol. 7 "Binding Table Surface State Model":
|
||||||
*
|
*
|
||||||
|
@ -2372,6 +2373,7 @@ enum anv_cmd_dirty_bits {
|
||||||
ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE = 1 << 21, /* VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT */
|
ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE = 1 << 21, /* VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT */
|
||||||
ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE = 1 << 22, /* VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT */
|
ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE = 1 << 22, /* VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT */
|
||||||
ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP = 1 << 23, /* VK_DYNAMIC_STATE_STENCIL_OP_EXT */
|
ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP = 1 << 23, /* VK_DYNAMIC_STATE_STENCIL_OP_EXT */
|
||||||
|
ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS = 1 << 24, /* VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT */
|
||||||
};
|
};
|
||||||
typedef uint32_t anv_cmd_dirty_mask_t;
|
typedef uint32_t anv_cmd_dirty_mask_t;
|
||||||
|
|
||||||
|
@ -2395,7 +2397,8 @@ typedef uint32_t anv_cmd_dirty_mask_t;
|
||||||
ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | \
|
ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP | \
|
||||||
ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE | \
|
ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE | \
|
||||||
ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | \
|
ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE | \
|
||||||
ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP)
|
ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP | \
|
||||||
|
ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS)
|
||||||
|
|
||||||
static inline enum anv_cmd_dirty_bits
|
static inline enum anv_cmd_dirty_bits
|
||||||
anv_cmd_dirty_bit_for_vk_dynamic_state(VkDynamicState vk_state)
|
anv_cmd_dirty_bit_for_vk_dynamic_state(VkDynamicState vk_state)
|
||||||
|
@ -2443,6 +2446,8 @@ anv_cmd_dirty_bit_for_vk_dynamic_state(VkDynamicState vk_state)
|
||||||
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE;
|
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE;
|
||||||
case VK_DYNAMIC_STATE_STENCIL_OP_EXT:
|
case VK_DYNAMIC_STATE_STENCIL_OP_EXT:
|
||||||
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP;
|
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP;
|
||||||
|
case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
|
||||||
|
return ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
|
||||||
default:
|
default:
|
||||||
assert(!"Unsupported dynamic state");
|
assert(!"Unsupported dynamic state");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2769,6 +2774,11 @@ struct anv_dynamic_state {
|
||||||
uint16_t pattern;
|
uint16_t pattern;
|
||||||
} line_stipple;
|
} line_stipple;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t samples;
|
||||||
|
VkSampleLocationEXT locations[MAX_SAMPLE_LOCATIONS];
|
||||||
|
} sample_locations;
|
||||||
|
|
||||||
VkCullModeFlags cull_mode;
|
VkCullModeFlags cull_mode;
|
||||||
VkFrontFace front_face;
|
VkFrontFace front_face;
|
||||||
VkPrimitiveTopology primitive_topology;
|
VkPrimitiveTopology primitive_topology;
|
||||||
|
|
|
@ -345,6 +345,13 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
cmd_buffer->state.gfx.primitive_topology = topology;
|
cmd_buffer->state.gfx.primitive_topology = topology;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd_buffer->device->enabled_extensions.EXT_sample_locations &&
|
||||||
|
cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
|
||||||
|
genX(emit_multisample)(&cmd_buffer->batch,
|
||||||
|
cmd_buffer->state.gfx.dynamic.sample_locations.samples,
|
||||||
|
cmd_buffer->state.gfx.dynamic.sample_locations.locations);
|
||||||
|
}
|
||||||
|
|
||||||
cmd_buffer->state.gfx.dirty = 0;
|
cmd_buffer->state.gfx.dirty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -648,6 +648,13 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd_buffer->device->enabled_extensions.EXT_sample_locations &&
|
||||||
|
cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
|
||||||
|
genX(emit_sample_pattern)(&cmd_buffer->batch,
|
||||||
|
cmd_buffer->state.gfx.dynamic.sample_locations.samples,
|
||||||
|
cmd_buffer->state.gfx.dynamic.sample_locations.locations);
|
||||||
|
}
|
||||||
|
|
||||||
cmd_buffer->state.gfx.dirty = 0;
|
cmd_buffer->state.gfx.dirty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -734,11 +734,39 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emit_ms_state(struct anv_graphics_pipeline *pipeline,
|
emit_ms_state(struct anv_graphics_pipeline *pipeline,
|
||||||
const VkPipelineMultisampleStateCreateInfo *info)
|
const VkPipelineMultisampleStateCreateInfo *info,
|
||||||
|
uint32_t dynamic_states)
|
||||||
{
|
{
|
||||||
uint32_t samples = info ? info->rasterizationSamples : 1;
|
/* If the sample locations are dynamic, 3DSTATE_MULTISAMPLE on Gen7/7.5
|
||||||
|
* will be emitted dynamically, so skip it here. On Gen8+
|
||||||
|
* 3DSTATE_SAMPLE_PATTERN will be emitted dynamically, so skip it here.
|
||||||
|
*/
|
||||||
|
if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS)) {
|
||||||
|
/* Only lookup locations if the extensions is active, otherwise the
|
||||||
|
* default ones will be used either at device initialization time or
|
||||||
|
* through 3DSTATE_MULTISAMPLE on Gen7/7.5 by passing NULL locations.
|
||||||
|
*/
|
||||||
|
if (pipeline->base.device->enabled_extensions.EXT_sample_locations) {
|
||||||
|
#if GEN_GEN >= 8
|
||||||
|
genX(emit_sample_pattern)(&pipeline->base.batch,
|
||||||
|
pipeline->dynamic_state.sample_locations.samples,
|
||||||
|
pipeline->dynamic_state.sample_locations.locations);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
genX(emit_multisample)(&pipeline->base.batch, samples, NULL);
|
genX(emit_multisample)(&pipeline->base.batch,
|
||||||
|
pipeline->dynamic_state.sample_locations.samples,
|
||||||
|
pipeline->dynamic_state.sample_locations.locations);
|
||||||
|
} else {
|
||||||
|
/* On Gen8+ 3DSTATE_MULTISAMPLE does not hold anything we need to modify
|
||||||
|
* for sample locations, so we don't have to emit it dynamically.
|
||||||
|
*/
|
||||||
|
#if GEN_GEN >= 8
|
||||||
|
genX(emit_multisample)(&pipeline->base.batch,
|
||||||
|
info ? info->rasterizationSamples : 1,
|
||||||
|
NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* From the Vulkan 1.0 spec:
|
/* From the Vulkan 1.0 spec:
|
||||||
* If pSampleMask is NULL, it is treated as if the mask has all bits
|
* If pSampleMask is NULL, it is treated as if the mask has all bits
|
||||||
|
@ -2264,7 +2292,7 @@ genX(graphics_pipeline_create)(
|
||||||
pCreateInfo->pRasterizationState,
|
pCreateInfo->pRasterizationState,
|
||||||
ms_info, line_info, dynamic_states, pass, subpass,
|
ms_info, line_info, dynamic_states, pass, subpass,
|
||||||
urb_deref_block_size);
|
urb_deref_block_size);
|
||||||
emit_ms_state(pipeline, ms_info);
|
emit_ms_state(pipeline, ms_info, dynamic_states);
|
||||||
emit_ds_state(pipeline, ds_info, dynamic_states, pass, subpass);
|
emit_ds_state(pipeline, ds_info, dynamic_states, pass, subpass);
|
||||||
emit_cb_state(pipeline, cb_info, ms_info);
|
emit_cb_state(pipeline, cb_info, ms_info);
|
||||||
compute_kill_pixel(pipeline, ms_info, subpass);
|
compute_kill_pixel(pipeline, ms_info, subpass);
|
||||||
|
|
Loading…
Reference in New Issue