Detailed steps of DX11 tesselation

silent_guy

Veteran
Supporter
I've been trying to understand the details of tessellation better, as present in XBOX and pre-RV870, and as mandated by DX11.

The way I've seen it explained is like this (for DX11)
- vertex shader transforms control points of a patch.
- hull shader determines parameters per patch for a fixed function tessellator
- the tessellator breaks up each patch into triangles
- domain shader does additional operations on the triangle vertices
- those triangles are (optionally) fed into the geometry shader

Is this more or less correct?

Questions:
- the fixed function tessellator works with bezier patches. Is that the only surface type it can work with? Are there different variants?

- If the tessellator only supports 1 kind of surface, is the same true for the input of the hull shader? That is: would it be possible to write the hull shader such that it converts a different kind of patch? (e.g.: a NURBS surface into a bezier patch?) Can a hull shader create new patches like a geometry shader? Or is the functionality of the hull shader limited to calculating whatever additional parameters are required for the HW tessellator? In case the hull shader cannot create additional patches, can it at least modify the incoming vertices or are those simply passed through unmodified from the vertex shader?

- The fixed function tessellator step: does it convert a bezier patch into a uniform grid of triangles? Or can it module the triangle density across the patch? The latter case would allow one to have only a few bezier patches for very large surfaces and still be efficient wrt the number of triangles.

- Why is there a domain shader at all? At first sight, one would think that domain shaders and geometry shaders can be merged into one? The only thing I can think of is that maybe a domain shader will have access to the patch control points while a geometry shader does not, but then why not simply extend the functionality of the geometry shader?

- There was some back and forth about whether or not tessellation in Fermi is hardware or software, as in: "done by the shaders". Given that hull shaders and domain shaders are called shaders, I assume that this discussion was then specifically about the fixed function tessellator step that sits between them? If this step were done in the shaders, then this would mean that you're basically have another geometry shader that converts a quad into tons of triangles, right? (Is this something a geometry shader could do on DX10 hardware?) Why would it be a bad thing for this to happen in a shader instead of fixed function hardware? I obviously understand that this will take away calculation power from the other shaders, but you could argue the same about going from fixed function vertex shader/pixel shader architecture to a unified architecture. ;) When you don't use tessellation, do you don't have hardware sitting idle.

- Wrt XBOX and pre-RV870: there were not hull shaders and domain shaders there. Which raises the question: how were the tessellation parameters calculated then? Some heuristic based on the proximity of input vertices? As for the domain shader: geometry shader coming to the rescue?
 
Thanks for that pointer, it clarifies a lot.

So the fixed function tessellator doesn't even use the control points that are generated by the hull shaders. That's a surprise. In a way, the tessellator is a bit like a rasterizer in a normalized geometry space.
 
I've been trying to understand the details of tessellation better, as present in XBOX and pre-RV870, and as mandated by DX11.

The way I've seen it explained is like this (for DX11)
- vertex shader transforms control points of a patch.
- hull shader determines parameters per patch for a fixed function tessellator
- the tessellator breaks up each patch into triangles
- domain shader does additional operations on the triangle vertices
- those triangles are (optionally) fed into the geometry shader

Is this more or less correct?
Yes.

Questions:
- the fixed function tessellator works with bezier patches. Is that the only surface type it can work with? Are there different variants?\
The FF tessellator receives tessellation factors as input and doesn't care if the patch is bezier or something else.

- If the tessellator only supports 1 kind of surface, is the same true for the input of the hull shader? That is: would it be possible to write the hull shader such that it converts a different kind of patch? (e.g.: a NURBS surface into a bezier patch?) Can a hull shader create new patches like a geometry shader? Or is the functionality of the hull shader limited to calculating whatever additional parameters are required for the HW tessellator? In case the hull shader cannot create additional patches, can it at least modify the incoming vertices or are those simply passed through unmodified from the vertex shader?
The HS can alter the number of control points and data associated with them, but it can't create new patches.

- The fixed function tessellator step: does it convert a bezier patch into a uniform grid of triangles? Or can it module the triangle density across the patch? The latter case would allow one to have only a few bezier patches for very large surfaces and still be efficient wrt the number of triangles.
There are multiple tessellation factors per patch and they can very to modulate the triangle density.

- Why is there a domain shader at all? At first sight, one would think that domain shaders and geometry shaders can be merged into one? The only thing I can think of is that maybe a domain shader will have access to the patch control points while a geometry shader does not, but then why not simply extend the functionality of the geometry shader?
The domain shader is what gives the tessellation algorithm flexibility allowing programmers to implement more than just one type of patch. It's separate from the geometry shader to improve performance. It takes advantage of vertex reuse.

- There was some back and forth about whether or not tessellation in Fermi is hardware or software, as in: "done by the shaders". Given that hull shaders and domain shaders are called shaders, I assume that this discussion was then specifically about the fixed function tessellator step that sits between them? If this step were done in the shaders, then this would mean that you're basically have another geometry shader that converts a quad into tons of triangles, right? (Is this something a geometry shader could do on DX10 hardware?) Why would it be a bad thing for this to happen in a shader instead of fixed function hardware? I obviously understand that this will take away calculation power from the other shaders, but you could argue the same about going from fixed function vertex shader/pixel shader architecture to a unified architecture. ;) When you don't use tessellation, do you don't have hardware sitting idle.
The main arguments against using the GS for tessellation are performance and functionality. Functionality comes into play because the GS can only output 1024 dwords of data per instance which is far less than the max tessellation level required by DX11. I have no idea how Nvidia is implementing things. They could always change how the GS works, though if they planned to do this I'd figure they'd lobby Microsoft to increase the capability of the GS.

- Wrt XBOX and pre-RV870: there were not hull shaders and domain shaders there. Which raises the question: how were the tessellation parameters calculated then? Some heuristic based on the proximity of input vertices? As for the domain shader: geometry shader coming to the rescue?
Multi-pass, if adaptive tessellation is required. If the tessellation factors are known ahead of time they're put in a buffer and input the the fixed function tessellator. The domain shader and vertex shader are the same thing in the single pass implementation.

A multi-pass implementation might be performing vertex skinning and using mem export to save off the vertex data and tessellation factors. The second pass reads this data, tessellates, and draws stuff.
 
Multi-pass, if adaptive tessellation is required. If the tessellation factors are known ahead of time they're put in a buffer and input the the fixed function tessellator. The domain shader and vertex shader are the same thing in the single pass implementation.

A multi-pass implementation might be performing vertex skinning and using mem export to save off the vertex data and tessellation factors. The second pass reads this data, tessellates, and draws stuff.

So if I understand this correctly, the fixed function tessellator for those chips is similar in its output to the one in DX11 in that it also only outputs weighing factors which need to be processed by a subsequent shader step. And you don't have a vertex shader before the tessellator but vertex shader after, which combines the control points and the weights and then does the additional (regular) transformation. That makes sense.

Thanks!
 
So if I understand this correctly, the fixed function tessellator for those chips is similar in its output to the one in DX11 in that it also only outputs weighing factors which need to be processed by a subsequent shader step. And you don't have a vertex shader before the tessellator but vertex shader after, which combines the control points and the weights and then does the additional (regular) transformation. That makes sense.

Thanks!
Yes, the concept is the same between the DX11 and Xenos tessellators, but the algorithm is a bit different and the max tessellation level is higher for DX11.
 
There are multiple tessellation factors per patch and they can very to modulate the triangle density.

But how granular is this control really? If it's a simple LOD scheme based on distance from the camera then if you need a certain triangle density for just one part of an object you have to tessellate all of that object's patches to that same density. Is that not a concern for tessellation performance or does this fixed function step run at the same speed no matter the tessellation factor?
 
But how granular is this control really? If it's a simple LOD scheme based on distance from the camera then if you need a certain triangle density for just one part of an object you have to tessellate all of that object's patches to that same density. Is that not a concern for tessellation performance or does this fixed function step run at the same speed no matter the tessellation factor?
Tessellation factors can be varied per patch so it's granular. Since the Hull Shader has knowledge of it's patch's location in space it can determine the distance to the camera and output the desired factors.

As to the performance of the fixed function step that likely depends on the implementation. For Xenos' tessellator performance is mostly dependent on the number of verts being output irregardless of varying tessellation factors.
 
Oh, thanks I didn't know that tessellation factors could be assigned per patch by the app. I don't get that second comment though - isn't the number of output verts directly dependent on the tessellation factor? i.e more tessellation => more output vertices.
 
Oh, thanks I didn't know that tessellation factors could be assigned per patch by the app. I don't get that second comment though - isn't the number of output verts directly dependent on the tessellation factor? i.e more tessellation => more output vertices.
I meant if the tessellation factors vary across edges of a patch it doesn't affect performance. I was attempting to answer "does this fixed function step run at the same speed no matter the tessellation factor?"
 
Hmm, I don't understand the purpose of tesselation. Is there something similar in openGL?

If you already have the patches, why go through the costly act of tessellating them at all? Why not just point sample (with pixels or voxels or discs or whatever primitive you'd like to define) the functions and display that approximation directly? It seems especially costly when many of the examples seem to be creating polygons at or approaching the individual pixel level, I always thought the advantage of polygon rendering was lost when polygons reached sub-pixel size.
 
You can use tessellation in OpenGL via a ATI extension and maybe other methods, but it's not part of core OpenGL. One reason to tessellate to triangles is that's what GPUs render.
 
Back
Top