Mesa (main): anv: VK_EXT_multi_draw implementation
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Jun 25 17:29:30 UTC 2021
Module: Mesa
Branch: main
Commit: 6a79ee97f48ee99718b97bb8870a74faeecd56d9
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=6a79ee97f48ee99718b97bb8870a74faeecd56d9
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Tue Jun 22 12:53:15 2021 -0400
anv: VK_EXT_multi_draw implementation
Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11531>
---
src/intel/vulkan/anv_device.c | 13 +++
src/intel/vulkan/genX_cmd_buffer.c | 171 ++++++++++++++++++++++++++++++++++++-
2 files changed, 183 insertions(+), 1 deletion(-)
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 82185ede36f..0caf9dad361 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -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;
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index b2aedf7c87a..abb66c0de56 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -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
More information about the mesa-commit
mailing list