Metal draw indirect missing draw count

Why is there no count to any of these draw indirect directives? I am appending draws to a single MTLBuffer on the cpu, but can't limit how many are drawn out of the buffer. An offset isn't enough to specify a range. Can this be supplied in some bind call?

- (void)drawIndexedPrimitives:(MTLPrimitiveType)primitiveType indexType:(MTLIndexType)indexType indexBuffer:(id <MTLBuffer>)indexBuffer indexBufferOffset:(NSUInteger)indexBufferOffset indirectBuffer:(id <MTLBuffer>)indirectBuffer indirectBufferOffset:(NSUInteger)indirectBufferOffset API_AVAILABLE(macos(10.11), ios(9.0));

Contrast this with the Vulkan call which as an offset and count.

	vkCmdDrawIndexedIndirect( m_encoder, indirectBuffer, drawBufferOffset, drawCount, sizeof( vkCmdDrawIndexedIndirect ) );

https://feedbackassistant.apple.com/feedback/9188429

And here's the D3D12 call that is similar. It has MaxCommandCount

void ExecuteIndirect(
  ID3D12CommandSignature *pCommandSignature,
  UINT                   MaxCommandCount, <- 
  ID3D12Resource         *pArgumentBuffer,
  UINT64                 ArgumentBufferOffset,
  ID3D12Resource         *pCountBuffer,
  UINT64                 CountBufferOffset
);

Hi, so we have something similar with Indirect Command Buffers, or ICBs, with the command executeCommandsInBuffer (click here for documentation).

- (void)executeCommandsInBuffer:(id<MTLIndirectCommandBuffer>)indirectCommandBuffer 
                      withRange:(NSRange)executionRange;

So you could initialize an ICB with commands like setRenderPipelineState, setVertexBuffer, setFragmentBuffer and issue a variety of draw calls like drawPrimitives, drawIndexedPrimitives, etc. And then at the time of drawing, you would issue your command similar to the following:

[renderEncoder executeCommandsInBuffer:_indirectCommandBuffer withRange:NSMakeRange(0, AAPLNumObjects)];

We have some sample code which illustrates how to construct an ICB and render with it: Encoding Indirect Command Buffers on the CPU.

We also have a documentation section on Indirect Command Buffers. I hope that helps, and thank you for filing your feedback request.

ICB's are only available on A9+, so that's why I was adopting the ID and not ICB calls. Our game title supports A7+. And yes, the ICB's have a range so I don't understand why the ID calls don't. And there's no sample code on how to use indirect draw that I've found.

This is a simple use case of trying to collect disjoint index buffer offsets/sizes for draws into a series of indirect draw calls. That way it's a single draw call instead of 1000. The materials are all the same for a given range of ID submissions to the buffer. Without a count, one can't even accumulate different materials.

Drawing 8 materials with an offset of 0, then 10 with an offset of 8 draws into the same MTLBuffer of size 80 draws, results in drawing 80 and then 72 indirect draws. But I need 8 and then 10.

Also when I looked into ICB's, they lock down all sorts of pipeline data and have a raster pipeline state inheritance model that makes them unusable except in that Apple sample code. Here I just want to record draws either on the CPU or GPU, and control the draw count of multiple index buffer ranges.

We also target iOS9, but the ICB calls seem to be iOS12/13 level.

Am I misunderstanding this call. I see it used in MoltenVK. Does the drawIndexedPrimitives call only draw one indirect draw call out of the buffer at the offset? Is that why the "count" is missing. So I need to call it multiple times for each of my drawCounts. If so, then I might be able to salvage what I have.

Hi, yes the setting is to draw one at a time. You could definitely use a loop and call it several times.

This also produces an "API is not supported" message on A7/A8 hardware. I guess the indirect draw calls were only introduced on the A9 series. So this isn't going to work for our 5S or 6 devices.

Metal draw indirect missing draw count
 
 
Q