3

I am totally new to tessellation and relatively new to Metal API, and have been referring to this sample code https://developer.apple.com/library/archive/samplecode/MetalBasicTessellation/Introduction/Intro.html

I realise the max tessellation factor on iOS is 16, which is very low for my use case compared to 64 on OSX. I suppose i'll need to apply tessellation on a quad that has been sub-divided to 4 by 4 smaller sections to begin with, so that after tessellation it will end up into something like one with a tessellation factor of 64?

So, i've changed the input control points to something like this

static const float controlPointPositionsQuad[] = {
    -0.8,  0.8, 0.0, 1.0,   // upper-left
     0.0,  0.8, 0.0, 1.0,   // upper-mid
     0.0,  0.0, 0.0, 1.0,   // mid-mid
    -0.8,  0.0, 0.0, 1.0,   // mid-left

    -0.8,  0.0, 0.0, 1.0,   // mid-left
     0.0,  0.0, 0.0, 1.0,   // mid-mid
     0.0, -0.8, 0.0, 1.0,   // lower-mid
    -0.8, -0.8, 0.0, 1.0,   // lower-left

     0.0,  0.8, 0.0, 1.0,   // upper-mid
     0.8,  0.8, 0.0, 1.0,   // upper-right
     0.8,  0.0, 0.0, 1.0,   // mid-right
     0.0,  0.0, 0.0, 1.0,   // mid-mid

     0.0,  0.0, 0.0, 1.0,   // mid-mid
     0.8,  0.0, 0.0, 1.0,   // mid-right
     0.8, -0.8, 0.0, 1.0,   // lower-right
     0.0, -0.8, 0.0, 1.0,   // lower-mid
};

and for the drawPatches i changed it to 16 instead of 4. But the result is that it is only showing only the first 4 points (top left). if i change the vertex layout stride to this:

vertexDescriptor.layouts[0].stride = 16*sizeof(float);

it is still showing the same.

I don't really know what i'm doing but what i'm going for is similar to tessellating a 3d mesh, but for my case is just a quad with subdivisions. I am unable to find any tutorial / code samples that teach about this using Metal API.

Can someone please point me to the right direction? thanks!

Darren
  • 152
  • 9
  • I don't think you need to update the stride of the buffer layout; it should remain `4 * sizeof(float)` unless you add more vertex attributes. Did you update the call to `dispatchThreadgroups` to generate tessellation factors for the new patches? You should dispatch as many threads as you have patches. – warrenm Dec 26 '19 at 08:41
  • ok @warrenm , i tried this [computeCommandEncoder dispatchThreadgroups:MTLSizeMake(2, 2, 1) threadsPerThreadgroup:MTLSizeMake(2, 2, 1)]; but i'm getting this error "failed assertion `component 1: 4 must be <= 1 for pid [[ thread_position_in_grid ]]'" – Darren Dec 26 '19 at 12:36
  • I think you want to use a 1D grid, even though the patches comprise a 2D lattice. Try setting the width of each size to 4 and the height to 1. – warrenm Dec 26 '19 at 15:05
  • @warrenm thanks for the suggestion! that has removed the error but it is still displaying the same. For my draw command am i doing it correctly? [renderCommandEncoder drawPatches:16 patchStart:0 patchCount:4 patchIndexBuffer:NULL patchIndexBufferOffset:0 instanceCount:1 baseInstance:0]; or is the order of vertices wrong? – Darren Dec 27 '19 at 04:44
  • 1
    I think you might want to swap your `numberOfPatchControlPoints` and `patchCount` parameters. The first parameter indicates the number of control points _per patch_ (probably 4 in your case), while the `patchCount` parameter determines the actual number of patches to draw. – warrenm Dec 27 '19 at 04:46
  • @warrenm oh wow bingo! that's the answer to the puzzle! it worked! thank you so much! if you would, do write an answer and i'll mark it as the accepted answer~ – Darren Dec 27 '19 at 05:42

1 Answers1

1

Here are a few things to check:

  1. Ensure that your tessellation factor compute kernel is generating inside/edge factors for all patches by dispatching a compute grid of the appropriate size.
  2. When dispatching threadgroups to execute your tessellation factor kernel, use 1D threadgroup counts and sizes (such that the total thread count is the number of patches, and the heights of both sizes passed to the dispatch method are 1).
  3. When drawing patches, the first parameter (numberOfPatchControlPoints) should equal the number of control points in each patch (3 for triangles; 4 for quads), and the third parameter should be the number of patches to draw.
warrenm
  • 31,094
  • 6
  • 92
  • 116
  • Does it ever make sense to use a 2D threadgroup? E.g., if there are 200x200 patches to tessellate and the tessellation function is a bit expensive, can you get a performance advantage by dispatching 200x200x1 instead of 40000x1x1? – Dan Oct 14 '20 at 13:28