1 /*
2     Copyright (c) Microsoft Corporation
3 
4     Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5     associated documentation files (the "Software"), to deal in the Software without restriction,
6     including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7     and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8     subject to the following conditions:
9 
10     The above copyright notice and this permission notice shall be included in all copies or substantial
11     portions of the Software.
12 
13     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14     NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
16     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 */
19 
20 #pragma once
21 //=================================================================================================================================
22 // Microsoft D3D11 Fixed Function Tessellator Reference - May 7, 2012
23 // amar.patel@microsoft.com
24 //
25 // CHWTessellator demonstrates what is expected of hardware in the D3D11 fixed function Tessellator stage.  Hardware
26 // implementers need only look at this class.
27 //
28 // CHLSLTessellator is a wrapper for CHWTessellator, representing the effect of shader code that will
29 // be autogenerated by HLSL in the Hull Shader, both for plumbing data around, and to precondition TessFactor values before they
30 // are passed to the hardware (such as deriving inside TessFactors from edge TessFactors).  The algorithms used
31 // in CHLSLTessellator are subject to change, but since they represent shader code auto-generated by the HLSL compiler,
32 // CHLSLTessellator has no effect on hardware design at all.  Note the HLSL compiler will expose all the raw hardware
33 // control illustrated by CHWTessellator for those who don't need the helper functionality illustrated by CHLSLTessellator.
34 //
35 // Usage:        (1) Create either a CHLSLTessellator or CHWTessellator object, depending on which you want to verify.
36 //               (2) Call C*Tessellator::Init()
37 //               (3) Call C*Tessellator::Tessellate[IsoLine|Tri|Quad]Domain()
38 //                      - Here you pass in TessFactors (how much to tessellate)
39 //               (4) Call C*Tessellator::GetPointCount(), C*Tessellator::GetIndexCount() to see how much data was generated.
40 //               (5) Call C*Tessellator::GetPoints() and C*Tessellator::GetIndices() to get pointers to the data.
41 //                   The pointers are fixed for the lifetime of the object (storage for max tessellation),
42 //                   so if you ::Tessellate again, the data in the buffers is overwritten.
43 //               (6) There are various other Get() methods to retrieve TessFactors that have been processed from
44 //                   what you passed in at step 3.  You can retrieve separate TessFactors that the tessellator
45 //                   produced after clamping but before rounding, and also after rounding (say in pow2 mode).
46 //                   These numbers can be useful information if you are geomorphing displacement maps.
47 //               (7) Goto Step 2 or 3 if you want to animate TessFactors or tessellate a different patch
48 //
49 // Code implementation details:
50 //
51 // There is lots of headroom to make this code run faster on CPUs.  It was written merely as a reference for
52 // what results hardware should produce, with CPU performance not a consideration.  It is nice that this implementation
53 // only generates the exact number of vertices needed (no duplicates) in the output vertex buffer.  Also, the number
54 // of calculations done for each U/V domain coordinate is minimized by doing some precalculation of some patch or edge
55 // invariant numbers (see TESS_FACTOR_CONTEXT).  All the vertex coordinate calculations could be computed with as much
56 // parallelism as you like.  Similarly the calculation of connectivity itself is highly parallelizable, and can also
57 // be done independent of the vertex calculations.
58 //
59 //=================================================================================================================================
60 
61 #define D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR 1
62 #define D3D11_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR 63
63 #define D3D11_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR 2
64 #define D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR 64
65 
66 #define D3D11_TESSELLATOR_MIN_ISOLINE_DENSITY_TESSELLATION_FACTOR 1
67 #define D3D11_TESSELLATOR_MAX_ISOLINE_DENSITY_TESSELLATION_FACTOR 64
68 
69 #define D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR 64 // max of even and odd tessFactors
70 
71 #define MAX_POINT_COUNT ((D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR+1)*(D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR+1))
72 #define MAX_INDEX_COUNT (D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR*D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR*2*3)
73 
74 //=================================================================================================================================
75 // Data types for the caller
76 //=================================================================================================================================
77 enum D3D11_TESSELLATOR_PARTITIONING
78 {
79     D3D11_TESSELLATOR_PARTITIONING_INTEGER,
80     D3D11_TESSELLATOR_PARTITIONING_POW2,
81     D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD,
82     D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN
83 };
84 
85 enum D3D11_TESSELLATOR_REDUCTION
86 {
87     D3D11_TESSELLATOR_REDUCTION_MIN,
88     D3D11_TESSELLATOR_REDUCTION_MAX,
89     D3D11_TESSELLATOR_REDUCTION_AVERAGE
90 };
91 
92 enum D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS
93 {
94     D3D11_TESSELLATOR_QUAD_REDUCTION_1_AXIS,
95     D3D11_TESSELLATOR_QUAD_REDUCTION_2_AXIS
96 };
97 
98 enum D3D11_TESSELLATOR_OUTPUT_PRIMITIVE
99 {
100     D3D11_TESSELLATOR_OUTPUT_POINT,
101     D3D11_TESSELLATOR_OUTPUT_LINE,
102     D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW,
103     D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW,
104 };
105 
106 typedef struct DOMAIN_POINT
107 {
108     float u;
109     float v; // for tri, w = 1 - u - v;
110 } DOMAIN_POINT;
111 
112 //=================================================================================================================================
113 // CHWTessellator: D3D11 Tessellation Fixed Function Hardware Reference
114 //=================================================================================================================================
115 typedef unsigned int FXP; // fixed point number
116 
117 class CHWTessellator
118 {
119 
120 //---------------------------------------------------------------------------------------------------------------------------------
121 public:
122     void Init( D3D11_TESSELLATOR_PARTITIONING         partitioning,
123                D3D11_TESSELLATOR_OUTPUT_PRIMITIVE     outputPrimitive);
124 
125     void TessellateIsoLineDomain( float TessFactor_V_LineDensity,
126                                   float TessFactor_U_LineDetail );
127 
128     void TessellateTriDomain( float TessFactor_Ueq0,
129                               float TessFactor_Veq0,
130                               float TessFactor_Weq0,
131                               float TessFactor_Inside );
132 
133     void TessellateQuadDomain( float TessFactor_Ueq0,
134                                float TessFactor_Veq0,
135                                float TessFactor_Ueq1,
136                                float TessFactor_Veq1,
137                                float TessFactor_InsideU,
138                                float TessFactor_InsideV );
139 
140     int GetPointCount();
141     int GetIndexCount();
142 
143     DOMAIN_POINT* GetPoints(); // Get CHWTessellator owned pointer to vertices (UV values).
144                                // Pointer is fixed for lifetime of CHWTessellator object.
145     int* GetIndices();         // Get CHWTessellator owned pointer to vertex indices.
146                                // Pointer is fixed for lifetime of CHWTessellator object.
147 
148 #define ALLOW_XBOX_360_COMPARISON // Different vertex splitting order. This is NOT D3D11 behavior, just available here for comparison.
149 	                              // Setting this define true just allows the XBox split style to be enabled via
150 	                              // SetXBox360Mode() below, but by default this XBox360 mode still always starts off DISABLED.
151 								  // The XBox360 always splits from the center of an edge (D3D11 uses ruler function).  Splitting
152 	                              // from the center causes sliver triangles in transition areas, which cause numerous problems.
153                                   // Note the XBox360 only supports adaptive tessellation via fractional_even partitioning,
154                                   // though this #define lets you try the XBox vertex splitting order with any of the
155                                   // partitioning modes: even, odd, integer or pow2.
156 #ifdef ALLOW_XBOX_360_COMPARISON
SetXBox360Mode(bool bXboxMode)157     void SetXBox360Mode(bool bXboxMode) {m_bXBox360Mode = bXboxMode;}
158 #endif
159     CHWTessellator();
160     ~CHWTessellator();
161 //---------------------------------------------------------------------------------------------------------------------------------
162     //=============================================================================================================================
163     // Some defines so that numbers are usually self commenting
164     //=============================================================================================================================
165     static const int U = 0; // points on a tri patch
166     static const int V = 1;
167     static const int W = 2;
168     static const int Ueq0 = 0; // edges on a tri patch
169     static const int Veq0 = 1;
170     static const int Weq0 = 2;
171 
172     static const int Ueq1 = 2; // edges on a quad patch: Ueq0, Veq0, Ueq1, Veq1
173     static const int Veq1 = 3;
174 
175     static const int QUAD_AXES = 2;
176     static const int QUAD_EDGES = 4;
177     static const int TRI_EDGES = 3;
178     //=============================================================================================================================
179 
180     enum TESSELLATOR_PARITY // derived from D3D11_TESSELLATOR_PARTITIONING
181     {                               // (note: for integer tessellation, both parities are used)
182         TESSELLATOR_PARITY_EVEN,
183         TESSELLATOR_PARITY_ODD
184     };
185 private:
186     TESSELLATOR_PARITY                   m_originalParity; // user chosen parity
187     TESSELLATOR_PARITY                   m_parity; // current parity: if allowing mix of even/odd during discrete
188                                                    // tessellation, this can vary from the user defined parity
189     D3D11_TESSELLATOR_PARTITIONING       m_originalPartitioning; // user chosen partitioning
190     D3D11_TESSELLATOR_PARTITIONING       m_partitioning; // current partitioning.  IsoLines overrides for line density
191     D3D11_TESSELLATOR_OUTPUT_PRIMITIVE   m_outputPrimitive;
192     DOMAIN_POINT*                        m_Point; // array where we will store u/v's for the points we generate
193     int*                                 m_Index; // array where we will store index topology
194     int                                  m_NumPoints;
195     int                                  m_NumIndices;
196 #ifdef ALLOW_XBOX_360_COMPARISON
197     bool                                 m_bXBox360Mode;
198 #endif
199     // PlacePointIn1D below is the workhorse for all position placement.
200     // It is code that could run as preamble in a Domain Shader, so the tessellator itself
201     // doesn't necessarily need to have floating point.
202     // Some per-TessFactor fixed context is needed, and that can be computed wherever
203     // the TessFactor reduction is done, perhaps as Hull Shader postamble - this is shared
204     // for all point evaluation.
205     typedef struct TESS_FACTOR_CONTEXT
206     {
207         FXP fxpInvNumSegmentsOnFloorTessFactor;
208         FXP fxpInvNumSegmentsOnCeilTessFactor;
209         FXP fxpHalfTessFactorFraction;
210         int numHalfTessFactorPoints;
211         int splitPointOnFloorHalfTessFactor;
212     } TESS_FACTOR_CONTEXT;
213     void ComputeTessFactorContext( FXP fxpTessFactor, TESS_FACTOR_CONTEXT& TessFactorCtx );
214     void PlacePointIn1D( const TESS_FACTOR_CONTEXT& TessFactorCtx, int point, FXP& fxpLocation );
215 
216     int NumPointsForTessFactor(FXP fxpTessFactor);
217 
218     // Tessellation parity control
Odd()219     bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;}
SetTessellationParity(TESSELLATOR_PARITY parity)220     void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;}
221 
222     // HWIntegerPartitioning() - hardware doesn't care about what pow2 partitioning is - the query below is true for
223     //                           both integer and pow2.
HWIntegerPartitioning()224     bool HWIntegerPartitioning() {return ((m_partitioning == D3D11_TESSELLATOR_PARTITIONING_INTEGER)||
225                                           (m_partitioning == D3D11_TESSELLATOR_PARTITIONING_POW2)) ? true : false;}
226 
227     // Tesselation Partitioning control
RestorePartitioning()228     void RestorePartitioning() {m_partitioning = m_originalPartitioning;};
OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING partitioning)229     void OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density
230 
231     // Call these to generate new points and indices.  Max TessFactor storage is already allocated.
232     int DefinePoint(FXP u, FXP v, int pointStorageOffset);
233     void DefineIndex(int index, int indexStorageOffset);
234     void DefineClockwiseTriangle(int index0, int index1, int index2, int indexStorageBaseOffset);
235 
236     // Couple of trivial ways to generate index data just given points and no other connectivity.
237     void DumpAllPoints();                  // Make point indices for point rendering mode -
238                                            // redundant, but just here for orthogonality.
239     void DumpAllPointsAsInOrderLineList(); // A debug visualization of all the points connected
240                                            // in the order they were generated.
241                                            // Asking to draw line topology on a tri or quad patch will do this
242 
243 
244     // The structures below define the data that is derived given input TessFactors and which
245     // is used by point generation and connectivity generation steps (each of which are independent)
246     typedef struct PROCESSED_TESS_FACTORS_ISOLINE
247     {
248         TESSELLATOR_PARITY lineDensityParity;
249         TESSELLATOR_PARITY lineDetailParity;
250         TESS_FACTOR_CONTEXT lineDensityTessFactorCtx;
251         TESS_FACTOR_CONTEXT lineDetailTessFactorCtx;
252         bool bPatchCulled;
253         int numPointsPerLine;
254         int numLines;
255     } PROCESSED_TESS_FACTORS_ISOLINE;
256     typedef struct PROCESSED_TESS_FACTORS_TRI
257     {
258         FXP outsideTessFactor[TRI_EDGES];
259         FXP insideTessFactor;
260         TESSELLATOR_PARITY outsideTessFactorParity[TRI_EDGES];
261         TESSELLATOR_PARITY insideTessFactorParity;
262         TESS_FACTOR_CONTEXT outsideTessFactorCtx[TRI_EDGES];
263         TESS_FACTOR_CONTEXT insideTessFactorCtx;
264         bool bJustDoMinimumTessFactor;
265         bool bPatchCulled;
266         // Stuff below is just specific to the traversal order
267         // this code happens to use to generate points/lines
268         int numPointsForOutsideEdge[TRI_EDGES];
269         int numPointsForInsideTessFactor;
270         int insideEdgePointBaseOffset;
271     } PROCESSED_TESS_FACTORS_TRI;
272     typedef struct PROCESSED_TESS_FACTORS_QUAD
273     {
274         FXP outsideTessFactor[QUAD_EDGES];
275         FXP insideTessFactor[QUAD_AXES];
276         TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES];
277         TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES];
278         TESS_FACTOR_CONTEXT outsideTessFactorCtx[QUAD_EDGES];
279         TESS_FACTOR_CONTEXT insideTessFactorCtx[QUAD_AXES];
280         bool bJustDoMinimumTessFactor;
281         bool bPatchCulled;
282         // Stuff below is just specific to the traversal order
283         // this code happens to use to generate points/lines
284         int numPointsForOutsideEdge[QUAD_EDGES];
285         int numPointsForInsideTessFactor[QUAD_AXES];
286         int insideEdgePointBaseOffset;
287     } PROCESSED_TESS_FACTORS_QUAD;
288 
289     // These are the workhorse functions for tessellation:
290     // (1) Process input TessFactors
291     // (2) Generate points
292     // (3) Generate connectivity (can be done in parallel to (2))
293     void IsoLineProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail, PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );
294     void IsoLineGeneratePoints( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );
295     void IsoLineGenerateConnectivity( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );
296     void TriProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor, PROCESSED_TESS_FACTORS_TRI& processedTessFactors );
297     void TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors );
298     void TriGenerateConnectivity( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors );
299     void QuadProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1,
300                                float insideTessFactor_U, float insideTessFactor_V, PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );
301     void QuadGeneratePoints( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );
302     void QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );
303 
304     // Stitching
305     // ---------
306     // Given pointers to the beginning of 2 parallel rows of points, and TessFactors for each, stitch them.
307     // The assumption is the stitch is symmetric.
308     void StitchTransition(int baseIndexOffset, int insideEdgePointBaseOffset, int insideNumHalfTessFactorPoints,
309                                                TESSELLATOR_PARITY insideEdgeTessFactorParity,
310                                                int outsideEdgePointBaseOffset, int outsideNumHalfTessFactorPoints,
311                                                TESSELLATOR_PARITY outsideEdgeTessFactorParity );
312     // The interior can just use a simpler stitch.
313     enum DIAGONALS
314     {
315         DIAGONALS_INSIDE_TO_OUTSIDE,
316         DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE,
317         DIAGONALS_MIRRORED
318     };
319 
320     void StitchRegular(bool bTrapezoid, DIAGONALS diagonals, int baseIndexOffset, int numInsideEdgePoints,
321                                         int insideEdgePointBaseOffset, int outsideEdgePointBaseOffset);
322 
323 //---------------------------------------------------------------------------------------------------------------------------------
324     // Index Patching
325     // --------------
326     // The code below patches index values produces during triangulation, so triangulation doesn't have to know
327     // where points should go.  I happened to never produce duplicate vertices, but the patching would
328     // be simpler if some duplicate vertices were introduced in practice.  During point rendering mode however,
329     // it is not permitted for duplicate points to show up.
330 
331     // Since the points are generated in concentric rings, most of the time, the point locations are
332     // sequentially increasing in memory for each side of a ring, which the stitch can take advantage of.
333     // However, there are exceptions where the points are not sequentially increasing, such as
334     // the 4th row in a given ring, where the last point on the outside of each row is actually the beginning
335     // point.
336     // So we let the stitching code think it sees sequential vertices, and when it emits a vertex index,
337     // we patch it to be the real location.
338     int  PatchIndexValue(int index);
339     typedef struct INDEX_PATCH_CONTEXT
340     {
341         int insidePointIndexDeltaToRealValue;
342         int insidePointIndexBadValue;
343         int insidePointIndexReplacementValue;
344         int outsidePointIndexPatchBase;
345         int outsidePointIndexDeltaToRealValue;
346         int outsidePointIndexBadValue;
347         int outsidePointIndexReplacementValue;
348     } INDEX_PATCH_CONTEXT;
SetUsingPatchedIndices(bool bUsingPatchedIndices)349     void SetUsingPatchedIndices(bool bUsingPatchedIndices) {m_bUsingPatchedIndices = bUsingPatchedIndices;}
350 
351     // A second index patch we have to do handles the leftover strip of quads in the middle of an odd quad patch after
352     // finishing all the concentric rings.
353     // This also handles the leftover strip of points in the middle of an even quad
354     // patch, when stitching the row of triangles up the left side (V major quad) or bottom (U major quad) of the
355     // inner ring
356     typedef struct INDEX_PATCH_CONTEXT2
357     {
358         int baseIndexToInvert;
359         int indexInversionEndPoint;
360         int cornerCaseBadValue;
361         int cornerCaseReplacementValue;
362     } INDEX_PATCH_CONTEXT2;
SetUsingPatchedIndices2(bool bUsingPatchedIndices)363     void SetUsingPatchedIndices2(bool bUsingPatchedIndices) {m_bUsingPatchedIndices2 = bUsingPatchedIndices;}
364     bool                                 m_bUsingPatchedIndices;
365     bool                                 m_bUsingPatchedIndices2;
366     INDEX_PATCH_CONTEXT                  m_IndexPatchContext;
367     INDEX_PATCH_CONTEXT2                 m_IndexPatchContext2;
368 
369 };
370 
371 //=================================================================================================================================
372 // CHLSLTessellator: D3D11 Tessellation HLSL Tessellator Interface
373 // Demonstrates TessFactor preconditioning code auto-generated by HLSL.  Subject to change, but this
374 // just represents the effect of shader code the HLSL compiler will generate in the Hull Shader,
375 // so it does not affect hardware design at all.
376 //=================================================================================================================================
377 class CHLSLTessellator : public CHWTessellator
378 {
379 public:
380     void Init( D3D11_TESSELLATOR_PARTITIONING         partitioning,
381                D3D11_TESSELLATOR_REDUCTION            insideTessFactorReduction,
382                D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS  quadInsideTessFactorReductionAxis,
383                D3D11_TESSELLATOR_OUTPUT_PRIMITIVE     outputPrimitive);
384 
385     void TessellateIsoLineDomain( float TessFactor_V_LineDensity,
386                                   float TessFactor_U_LineDetail );
387 
388     void TessellateTriDomain( float tessFactor_Ueq0,
389                               float TessFactor_Veq0,
390                               float TessFactor_Weq0,
391                               float insideTessFactorScale /*[0..1]*/ );
392 
393     void TessellateQuadDomain( float TessFactorUeq0,
394                                float TessFactorVeq0,
395                                float TessFactorUeq1,
396                                float TessFactorVeq1,
397                                float insideTessFactorScaleU /*[0..1]*/,
398                                float insideTessFactorScaleV /*[0..1]*/ );
399 
GetPointCount()400     int GetPointCount() {return CHWTessellator::GetPointCount();};
GetIndexCount()401     int GetIndexCount() {return CHWTessellator::GetIndexCount();}
402 
GetPoints()403     DOMAIN_POINT* GetPoints() {return CHWTessellator::GetPoints();} // Get CHLSLTessellator owned pointer to vertices (UV values).
404                                // Pointer is fixed for lifetime of CHLSLTessellator object.
GetIndices()405     int* GetIndices() {return CHWTessellator::GetIndices();}         // Get CHLSLTessellator owned pointer to vertex indices.
406                                // Pointer is fixed for lifetime of CHLSLTessellator object.
407 
408     // Retrieve TessFactors actually used by the "hardware"
409     // This includes clamping to valid range, and more interestingly
410     // if integer or pow2 partitioning is being done, the rounded TessFactors can be retrieved.
411     // Getting the rounded TessFactors can be useful for geomorphing of displacement maps.
GetIsoLineDensityTessFactor()412     float GetIsoLineDensityTessFactor() {return m_LastComputedTessFactors[0];}
GetIsoLineDetailTessFactor()413     float GetIsoLineDetailTessFactor() {return m_LastComputedTessFactors[1];}
GetTriUeq0TessFactor()414     float GetTriUeq0TessFactor() {return m_LastComputedTessFactors[0];}
GetTriVeq0TessFactor()415     float GetTriVeq0TessFactor() {return m_LastComputedTessFactors[1];}
GetTriWeq0TessFactor()416     float GetTriWeq0TessFactor() {return m_LastComputedTessFactors[2];}
GetTriInsideTessFactor()417     float GetTriInsideTessFactor() {return m_LastComputedTessFactors[3];}
GetQuadUeq0TessFactor()418     float GetQuadUeq0TessFactor() {return m_LastComputedTessFactors[0];}
GetQuadVeq0TessFactor()419     float GetQuadVeq0TessFactor() {return m_LastComputedTessFactors[1];}
GetQuadUeq1TessFactor()420     float GetQuadUeq1TessFactor() {return m_LastComputedTessFactors[2];}
GetQuadVeq1TessFactor()421     float GetQuadVeq1TessFactor() {return m_LastComputedTessFactors[3];}
GetQuadInsideUTessFactor()422     float GetQuadInsideUTessFactor() {return m_LastComputedTessFactors[4];}
GetQuadInsideVTessFactor()423     float GetQuadInsideVTessFactor() {return m_LastComputedTessFactors[5];}
GetUnRoundedIsoLineDensityTessFactor()424     float GetUnRoundedIsoLineDensityTessFactor() {return m_LastUnRoundedComputedTessFactors[0];}
GetUnRoundedIsoLineDetailTessFactor()425     float GetUnRoundedIsoLineDetailTessFactor() {return m_LastUnRoundedComputedTessFactors[1];}
GetUnRoundedTriUeq0TessFactor()426     float GetUnRoundedTriUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];}
GetUnRoundedTriVeq0TessFactor()427     float GetUnRoundedTriVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];}
GetUnRoundedTriWeq0TessFactor()428     float GetUnRoundedTriWeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[2];}
GetUnRoundedTriInsideTessFactor()429     float GetUnRoundedTriInsideTessFactor() {return m_LastUnRoundedComputedTessFactors[3];}
GetUnRoundedQuadUeq0TessFactor()430     float GetUnRoundedQuadUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];}
GetUnRoundedQuadVeq0TessFactor()431     float GetUnRoundedQuadVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];}
GetUnRoundedQuadUeq1TessFactor()432     float GetUnRoundedQuadUeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[2];}
GetUnRoundedQuadVeq1TessFactor()433     float GetUnRoundedQuadVeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[3];}
GetUnRoundedQuadInsideUTessFactor()434     float GetUnRoundedQuadInsideUTessFactor() {return m_LastUnRoundedComputedTessFactors[4];}
GetUnRoundedQuadInsideVTessFactor()435     float GetUnRoundedQuadInsideVTessFactor() {return m_LastUnRoundedComputedTessFactors[5];}
436 
437     CHLSLTessellator();
438 //---------------------------------------------------------------------------------------------------------------------------------
439 private:
440     TESSELLATOR_PARITY                   m_originalParity; // user chosen parity
441     TESSELLATOR_PARITY                   m_parity; // current parity: if allowing mix of even/odd during discrete
442                                                    // tessellation, this can vary from the user defined parity
443     D3D11_TESSELLATOR_PARTITIONING       m_originalPartitioning; // user chosen partitioning
444     D3D11_TESSELLATOR_PARTITIONING       m_partitioning; // current partitioning.  IsoLines overrides for line density
445     D3D11_TESSELLATOR_OUTPUT_PRIMITIVE   m_outputPrimitive;
446     D3D11_TESSELLATOR_REDUCTION          m_insideTessFactorReduction;
447     D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS m_quadInsideTessFactorReductionAxis;
448     float                                m_LastComputedTessFactors[6]; // TessFactors used for last tessellation
449     float                                m_LastUnRoundedComputedTessFactors[6]; // TessFactors used for last tessellation (before they were rounded)
IntegerPartitioning()450     bool IntegerPartitioning() {return (m_partitioning == D3D11_TESSELLATOR_PARTITIONING_INTEGER) ? true : false;}
Pow2Partitioning()451     bool Pow2Partitioning() {return (m_partitioning == D3D11_TESSELLATOR_PARTITIONING_POW2)? true : false;}
452     void ClampTessFactor(float& TessFactor);
453     void RoundUpTessFactor(float& TessFactor);
454     void CleanupFloatTessFactor(float& input); // clamp float to [1.0f... +INF] (incl NaN->1.0f)
455     void ClampFloatTessFactorScale(float& input); // clamp float to [0.0f... +INF] (incl NaN->0.0f)
456 
457     // Tessellation parity control
Odd()458     bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;}
SetTessellationParity(TESSELLATOR_PARITY parity)459     void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;}
460 
461     // Tesselation Partitioning control
RestorePartitioning()462     void RestorePartitioning() {m_partitioning = m_originalPartitioning;};
OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING partitioning)463     void OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density
464 
465     void IsoLineHLSLProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail );
466     void TriHLSLProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor );
467     void QuadHLSLProcessTessFactors( float TessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Ueq1, float TessFactor_Veq1,
468                                float insideTessFactor_U, float insideTessFactor_V );
469 
470 };
471 
472