anv: VK_EXT_multi_draw implementation
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11531>
This commit is contained in:

committed by
Marge Bot

parent
1e39f2c199
commit
6a79ee97f4
@@ -321,6 +321,7 @@ get_device_extensions(const struct anv_physical_device *device,
|
||||
.INTEL_performance_query = device->perf &&
|
||||
device->perf->i915_perf_version >= 3,
|
||||
.INTEL_shader_integer_functions2 = device->info.ver >= 8,
|
||||
.EXT_multi_draw = true,
|
||||
.NV_compute_shader_derivatives = true,
|
||||
};
|
||||
}
|
||||
@@ -1832,6 +1833,12 @@ void anv_GetPhysicalDeviceFeatures2(
|
||||
break;
|
||||
}
|
||||
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: {
|
||||
VkPhysicalDeviceMultiDrawFeaturesEXT *features = (VkPhysicalDeviceMultiDrawFeaturesEXT *)ext;
|
||||
features->multiDraw = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
anv_debug_ignored_stype(ext->sType);
|
||||
break;
|
||||
@@ -2632,6 +2639,12 @@ void anv_GetPhysicalDeviceProperties2(
|
||||
break;
|
||||
}
|
||||
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: {
|
||||
VkPhysicalDeviceMultiDrawPropertiesEXT *props = (VkPhysicalDeviceMultiDrawPropertiesEXT *)ext;
|
||||
props->maxMultiDrawCount = 2048;
|
||||
break;
|
||||
}
|
||||
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES:
|
||||
anv_get_physical_device_properties_1_1(pdevice, (void *)ext);
|
||||
break;
|
||||
|
@@ -3936,7 +3936,9 @@ void genX(CmdDraw)(
|
||||
if (cmd_buffer->state.conditional_render_enabled)
|
||||
genX(cmd_emit_conditional_render_predicate)(cmd_buffer);
|
||||
|
||||
cmd_buffer_emit_vertex_constants_and_flush(cmd_buffer, vs_prog_data, firstVertex, firstInstance, 0, true);
|
||||
cmd_buffer_emit_vertex_constants_and_flush(cmd_buffer, vs_prog_data,
|
||||
firstVertex, firstInstance, 0,
|
||||
true);
|
||||
|
||||
/* Our implementation of VK_KHR_multiview uses instancing to draw the
|
||||
* different views. We need to multiply instanceCount by the view count.
|
||||
@@ -3958,6 +3960,61 @@ void genX(CmdDraw)(
|
||||
update_dirty_vbs_for_gfx8_vb_flush(cmd_buffer, SEQUENTIAL);
|
||||
}
|
||||
|
||||
void genX(CmdDrawMultiEXT)(
|
||||
VkCommandBuffer commandBuffer,
|
||||
uint32_t drawCount,
|
||||
const VkMultiDrawInfoEXT *pVertexInfo,
|
||||
uint32_t instanceCount,
|
||||
uint32_t firstInstance,
|
||||
uint32_t stride)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
|
||||
const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline);
|
||||
|
||||
if (anv_batch_has_error(&cmd_buffer->batch))
|
||||
return;
|
||||
|
||||
const uint32_t count = (drawCount *
|
||||
instanceCount *
|
||||
(pipeline->use_primitive_replication ?
|
||||
1 : anv_subpass_view_count(cmd_buffer->state.subpass)));
|
||||
anv_measure_snapshot(cmd_buffer,
|
||||
INTEL_SNAPSHOT_DRAW,
|
||||
"draw_multi", count);
|
||||
|
||||
genX(cmd_buffer_flush_state)(cmd_buffer);
|
||||
|
||||
if (cmd_buffer->state.conditional_render_enabled)
|
||||
genX(cmd_emit_conditional_render_predicate)(cmd_buffer);
|
||||
|
||||
/* Our implementation of VK_KHR_multiview uses instancing to draw the
|
||||
* different views. We need to multiply instanceCount by the view count.
|
||||
*/
|
||||
if (!pipeline->use_primitive_replication)
|
||||
instanceCount *= anv_subpass_view_count(cmd_buffer->state.subpass);
|
||||
|
||||
uint32_t i = 0;
|
||||
vk_foreach_multi_draw(draw, i, pVertexInfo, drawCount, stride) {
|
||||
cmd_buffer_emit_vertex_constants_and_flush(cmd_buffer, vs_prog_data,
|
||||
draw->firstVertex,
|
||||
firstInstance, i, !i);
|
||||
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
|
||||
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
|
||||
prim.VertexAccessType = SEQUENTIAL;
|
||||
prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology;
|
||||
prim.VertexCountPerInstance = draw->vertexCount;
|
||||
prim.StartVertexLocation = draw->firstVertex;
|
||||
prim.InstanceCount = instanceCount;
|
||||
prim.StartInstanceLocation = firstInstance;
|
||||
prim.BaseVertexLocation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
update_dirty_vbs_for_gfx8_vb_flush(cmd_buffer, SEQUENTIAL);
|
||||
}
|
||||
|
||||
void genX(CmdDrawIndexed)(
|
||||
VkCommandBuffer commandBuffer,
|
||||
uint32_t indexCount,
|
||||
@@ -4009,6 +4066,118 @@ void genX(CmdDrawIndexed)(
|
||||
update_dirty_vbs_for_gfx8_vb_flush(cmd_buffer, RANDOM);
|
||||
}
|
||||
|
||||
void genX(CmdDrawMultiIndexedEXT)(
|
||||
VkCommandBuffer commandBuffer,
|
||||
uint32_t drawCount,
|
||||
const VkMultiDrawIndexedInfoEXT *pIndexInfo,
|
||||
uint32_t instanceCount,
|
||||
uint32_t firstInstance,
|
||||
uint32_t stride,
|
||||
const int32_t *pVertexOffset)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
|
||||
const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline);
|
||||
|
||||
if (anv_batch_has_error(&cmd_buffer->batch))
|
||||
return;
|
||||
|
||||
const uint32_t count = (drawCount *
|
||||
instanceCount *
|
||||
(pipeline->use_primitive_replication ?
|
||||
1 : anv_subpass_view_count(cmd_buffer->state.subpass)));
|
||||
anv_measure_snapshot(cmd_buffer,
|
||||
INTEL_SNAPSHOT_DRAW,
|
||||
"draw indexed_multi",
|
||||
count);
|
||||
|
||||
genX(cmd_buffer_flush_state)(cmd_buffer);
|
||||
|
||||
if (cmd_buffer->state.conditional_render_enabled)
|
||||
genX(cmd_emit_conditional_render_predicate)(cmd_buffer);
|
||||
|
||||
/* Our implementation of VK_KHR_multiview uses instancing to draw the
|
||||
* different views. We need to multiply instanceCount by the view count.
|
||||
*/
|
||||
if (!pipeline->use_primitive_replication)
|
||||
instanceCount *= anv_subpass_view_count(cmd_buffer->state.subpass);
|
||||
|
||||
uint32_t i = 0;
|
||||
if (pVertexOffset) {
|
||||
if (vs_prog_data->uses_drawid) {
|
||||
bool emitted = true;
|
||||
if (vs_prog_data->uses_firstvertex ||
|
||||
vs_prog_data->uses_baseinstance) {
|
||||
emit_base_vertex_instance(cmd_buffer, *pVertexOffset, firstInstance);
|
||||
emitted = true;
|
||||
}
|
||||
vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) {
|
||||
if (vs_prog_data->uses_drawid) {
|
||||
emit_draw_index(cmd_buffer, i);
|
||||
emitted = true;
|
||||
}
|
||||
/* Emitting draw index or vertex index BOs may result in needing
|
||||
* additional VF cache flushes.
|
||||
*/
|
||||
if (emitted)
|
||||
genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer);
|
||||
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
|
||||
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
|
||||
prim.VertexAccessType = RANDOM;
|
||||
prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology;
|
||||
prim.VertexCountPerInstance = draw->indexCount;
|
||||
prim.StartVertexLocation = draw->firstIndex;
|
||||
prim.InstanceCount = instanceCount;
|
||||
prim.StartInstanceLocation = firstInstance;
|
||||
prim.BaseVertexLocation = *pVertexOffset;
|
||||
}
|
||||
emitted = false;
|
||||
}
|
||||
} else {
|
||||
if (vs_prog_data->uses_firstvertex ||
|
||||
vs_prog_data->uses_baseinstance) {
|
||||
emit_base_vertex_instance(cmd_buffer, *pVertexOffset, firstInstance);
|
||||
/* Emitting draw index or vertex index BOs may result in needing
|
||||
* additional VF cache flushes.
|
||||
*/
|
||||
genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer);
|
||||
}
|
||||
vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) {
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
|
||||
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
|
||||
prim.VertexAccessType = RANDOM;
|
||||
prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology;
|
||||
prim.VertexCountPerInstance = draw->indexCount;
|
||||
prim.StartVertexLocation = draw->firstIndex;
|
||||
prim.InstanceCount = instanceCount;
|
||||
prim.StartInstanceLocation = firstInstance;
|
||||
prim.BaseVertexLocation = *pVertexOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vk_foreach_multi_draw_indexed(draw, i, pIndexInfo, drawCount, stride) {
|
||||
cmd_buffer_emit_vertex_constants_and_flush(cmd_buffer, vs_prog_data,
|
||||
draw->vertexOffset,
|
||||
firstInstance, i, i != 0);
|
||||
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
|
||||
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
|
||||
prim.VertexAccessType = RANDOM;
|
||||
prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology;
|
||||
prim.VertexCountPerInstance = draw->indexCount;
|
||||
prim.StartVertexLocation = draw->firstIndex;
|
||||
prim.InstanceCount = instanceCount;
|
||||
prim.StartInstanceLocation = firstInstance;
|
||||
prim.BaseVertexLocation = draw->vertexOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_dirty_vbs_for_gfx8_vb_flush(cmd_buffer, RANDOM);
|
||||
}
|
||||
|
||||
/* Auto-Draw / Indirect Registers */
|
||||
#define GFX7_3DPRIM_END_OFFSET 0x2420
|
||||
#define GFX7_3DPRIM_START_VERTEX 0x2430
|
||||
|
Reference in New Issue
Block a user