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;
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,
#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"
}
}
+ 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;
}
#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":
*
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;
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)
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;
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;
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;
}
}
}
+ 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;
}
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
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);