diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index c27d4883e8b..5a757b04772 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -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_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 return changed; @@ -687,6 +695,22 @@ void anv_CmdSetStencilReference( 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( VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index e008cc67c5b..56b6d451b8c 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -31,6 +31,7 @@ #include "util/os_time.h" #include "common/gen_l3_config.h" #include "common/gen_disasm.h" +#include "common/gen_sample_positions.h" #include "anv_private.h" #include "compiler/brw_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; } diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index fb4cd5c2e20..905174fd68a 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -189,6 +189,7 @@ struct gen_perf_query_result; #define ANV_SSBO_ALIGNMENT 4 #define ANV_SSBO_BOUNDS_CHECK_ALIGNMENT 4 #define MAX_VIEWS_FOR_PRIMITIVE_REPLICATION 16 +#define MAX_SAMPLE_LOCATIONS 16 /* 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_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_SAMPLE_LOCATIONS = 1 << 24, /* VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT */ }; 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_BOUNDS_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 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; case VK_DYNAMIC_STATE_STENCIL_OP_EXT: return ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP; + case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT: + return ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS; default: assert(!"Unsupported dynamic state"); return 0; @@ -2769,6 +2774,11 @@ struct anv_dynamic_state { uint16_t pattern; } line_stipple; + struct { + uint32_t samples; + VkSampleLocationEXT locations[MAX_SAMPLE_LOCATIONS]; + } sample_locations; + VkCullModeFlags cull_mode; VkFrontFace front_face; VkPrimitiveTopology primitive_topology; diff --git a/src/intel/vulkan/gen7_cmd_buffer.c b/src/intel/vulkan/gen7_cmd_buffer.c index 531344a3ea9..29410c5287e 100644 --- a/src/intel/vulkan/gen7_cmd_buffer.c +++ b/src/intel/vulkan/gen7_cmd_buffer.c @@ -345,6 +345,13 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) 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; } diff --git a/src/intel/vulkan/gen8_cmd_buffer.c b/src/intel/vulkan/gen8_cmd_buffer.c index 80e63731f04..6161aac82e8 100644 --- a/src/intel/vulkan/gen8_cmd_buffer.c +++ b/src/intel/vulkan/gen8_cmd_buffer.c @@ -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; } diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index 3aeeaf943bf..1ed5344c2d6 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -734,11 +734,39 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline, static void 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: * If pSampleMask is NULL, it is treated as if the mask has all bits @@ -2264,7 +2292,7 @@ genX(graphics_pipeline_create)( pCreateInfo->pRasterizationState, ms_info, line_info, dynamic_states, pass, subpass, 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_cb_state(pipeline, cb_info, ms_info); compute_kill_pixel(pipeline, ms_info, subpass);