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