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 PIPE_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR 1 62 #define PIPE_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR 63 63 #define PIPE_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR 2 64 #define PIPE_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR 64 65 66 #define PIPE_TESSELLATOR_MIN_ISOLINE_DENSITY_TESSELLATION_FACTOR 1 67 #define PIPE_TESSELLATOR_MAX_ISOLINE_DENSITY_TESSELLATION_FACTOR 64 68 69 #define PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR 64 // max of even and odd tessFactors 70 71 #define MAX_POINT_COUNT ((PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR+1)*(PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR+1)) 72 #define MAX_INDEX_COUNT (PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR*PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR*2*3) 73 74 //================================================================================================================================= 75 // Data types for the caller 76 //================================================================================================================================= 77 enum PIPE_TESSELLATOR_PARTITIONING 78 { 79 PIPE_TESSELLATOR_PARTITIONING_INTEGER, 80 PIPE_TESSELLATOR_PARTITIONING_POW2, 81 PIPE_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD, 82 PIPE_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN 83 }; 84 85 enum PIPE_TESSELLATOR_REDUCTION 86 { 87 PIPE_TESSELLATOR_REDUCTION_MIN, 88 PIPE_TESSELLATOR_REDUCTION_MAX, 89 PIPE_TESSELLATOR_REDUCTION_AVERAGE 90 }; 91 92 enum PIPE_TESSELLATOR_QUAD_REDUCTION_AXIS 93 { 94 PIPE_TESSELLATOR_QUAD_REDUCTION_1_AXIS, 95 PIPE_TESSELLATOR_QUAD_REDUCTION_2_AXIS 96 }; 97 98 enum PIPE_TESSELLATOR_OUTPUT_PRIMITIVE 99 { 100 PIPE_TESSELLATOR_OUTPUT_POINT, 101 PIPE_TESSELLATOR_OUTPUT_LINE, 102 PIPE_TESSELLATOR_OUTPUT_TRIANGLE_CW, 103 PIPE_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( PIPE_TESSELLATOR_PARTITIONING partitioning, 123 PIPE_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 CHWTessellator(); 149 ~CHWTessellator(); 150 //--------------------------------------------------------------------------------------------------------------------------------- 151 //============================================================================================================================= 152 // Some defines so that numbers are usually self commenting 153 //============================================================================================================================= 154 static const int U = 0; // points on a tri patch 155 static const int V = 1; 156 static const int W = 2; 157 static const int Ueq0 = 0; // edges on a tri patch 158 static const int Veq0 = 1; 159 static const int Weq0 = 2; 160 161 static const int Ueq1 = 2; // edges on a quad patch: Ueq0, Veq0, Ueq1, Veq1 162 static const int Veq1 = 3; 163 164 static const int QUAD_AXES = 2; 165 static const int QUAD_EDGES = 4; 166 static const int TRI_EDGES = 3; 167 //============================================================================================================================= 168 169 enum TESSELLATOR_PARITY // derived from PIPE_TESSELLATOR_PARTITIONING 170 { // (note: for integer tessellation, both parities are used) 171 TESSELLATOR_PARITY_EVEN, 172 TESSELLATOR_PARITY_ODD 173 }; 174 private: 175 TESSELLATOR_PARITY m_originalParity; // user chosen parity 176 TESSELLATOR_PARITY m_parity; // current parity: if allowing mix of even/odd during discrete 177 // tessellation, this can vary from the user defined parity 178 PIPE_TESSELLATOR_PARTITIONING m_originalPartitioning; // user chosen partitioning 179 PIPE_TESSELLATOR_PARTITIONING m_partitioning; // current partitioning. IsoLines overrides for line density 180 PIPE_TESSELLATOR_OUTPUT_PRIMITIVE m_outputPrimitive; 181 DOMAIN_POINT* m_Point; // array where we will store u/v's for the points we generate 182 int* m_Index; // array where we will store index topology 183 int m_NumPoints; 184 int m_NumIndices; 185 // PlacePointIn1D below is the workhorse for all position placement. 186 // It is code that could run as preamble in a Domain Shader, so the tessellator itself 187 // doesn't necessarily need to have floating point. 188 // Some per-TessFactor fixed context is needed, and that can be computed wherever 189 // the TessFactor reduction is done, perhaps as Hull Shader postamble - this is shared 190 // for all point evaluation. 191 typedef struct TESS_FACTOR_CONTEXT 192 { 193 FXP fxpInvNumSegmentsOnFloorTessFactor; 194 FXP fxpInvNumSegmentsOnCeilTessFactor; 195 FXP fxpHalfTessFactorFraction; 196 int numHalfTessFactorPoints; 197 int splitPointOnFloorHalfTessFactor; 198 } TESS_FACTOR_CONTEXT; 199 void ComputeTessFactorContext( FXP fxpTessFactor, TESS_FACTOR_CONTEXT& TessFactorCtx ); 200 void PlacePointIn1D( const TESS_FACTOR_CONTEXT& TessFactorCtx, int point, FXP& fxpLocation ); 201 202 int NumPointsForTessFactor(FXP fxpTessFactor); 203 204 // Tessellation parity control Odd()205 bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;} SetTessellationParity(TESSELLATOR_PARITY parity)206 void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;} 207 208 // HWIntegerPartitioning() - hardware doesn't care about what pow2 partitioning is - the query below is true for 209 // both integer and pow2. HWIntegerPartitioning()210 bool HWIntegerPartitioning() {return ((m_partitioning == PIPE_TESSELLATOR_PARTITIONING_INTEGER)|| 211 (m_partitioning == PIPE_TESSELLATOR_PARTITIONING_POW2)) ? true : false;} 212 213 // Tesselation Partitioning control RestorePartitioning()214 void RestorePartitioning() {m_partitioning = m_originalPartitioning;}; OverridePartitioning(PIPE_TESSELLATOR_PARTITIONING partitioning)215 void OverridePartitioning(PIPE_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density 216 217 // Call these to generate new points and indices. Max TessFactor storage is already allocated. 218 int DefinePoint(FXP u, FXP v, int pointStorageOffset); 219 void DefineIndex(int index, int indexStorageOffset); 220 void DefineClockwiseTriangle(int index0, int index1, int index2, int indexStorageBaseOffset); 221 222 // Couple of trivial ways to generate index data just given points and no other connectivity. 223 void DumpAllPoints(); // Make point indices for point rendering mode - 224 // redundant, but just here for orthogonality. 225 void DumpAllPointsAsInOrderLineList(); // A debug visualization of all the points connected 226 // in the order they were generated. 227 // Asking to draw line topology on a tri or quad patch will do this 228 229 230 // The structures below define the data that is derived given input TessFactors and which 231 // is used by point generation and connectivity generation steps (each of which are independent) 232 typedef struct PROCESSED_TESS_FACTORS_ISOLINE 233 { 234 TESSELLATOR_PARITY lineDensityParity; 235 TESSELLATOR_PARITY lineDetailParity; 236 TESS_FACTOR_CONTEXT lineDensityTessFactorCtx; 237 TESS_FACTOR_CONTEXT lineDetailTessFactorCtx; 238 bool bPatchCulled; 239 int numPointsPerLine; 240 int numLines; 241 } PROCESSED_TESS_FACTORS_ISOLINE; 242 typedef struct PROCESSED_TESS_FACTORS_TRI 243 { 244 FXP outsideTessFactor[TRI_EDGES]; 245 FXP insideTessFactor; 246 TESSELLATOR_PARITY outsideTessFactorParity[TRI_EDGES]; 247 TESSELLATOR_PARITY insideTessFactorParity; 248 TESS_FACTOR_CONTEXT outsideTessFactorCtx[TRI_EDGES]; 249 TESS_FACTOR_CONTEXT insideTessFactorCtx; 250 bool bJustDoMinimumTessFactor; 251 bool bPatchCulled; 252 // Stuff below is just specific to the traversal order 253 // this code happens to use to generate points/lines 254 int numPointsForOutsideEdge[TRI_EDGES]; 255 int numPointsForInsideTessFactor; 256 int insideEdgePointBaseOffset; 257 } PROCESSED_TESS_FACTORS_TRI; 258 typedef struct PROCESSED_TESS_FACTORS_QUAD 259 { 260 FXP outsideTessFactor[QUAD_EDGES]; 261 FXP insideTessFactor[QUAD_AXES]; 262 TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES]; 263 TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES]; 264 TESS_FACTOR_CONTEXT outsideTessFactorCtx[QUAD_EDGES]; 265 TESS_FACTOR_CONTEXT insideTessFactorCtx[QUAD_AXES]; 266 bool bJustDoMinimumTessFactor; 267 bool bPatchCulled; 268 // Stuff below is just specific to the traversal order 269 // this code happens to use to generate points/lines 270 int numPointsForOutsideEdge[QUAD_EDGES]; 271 int numPointsForInsideTessFactor[QUAD_AXES]; 272 int insideEdgePointBaseOffset; 273 } PROCESSED_TESS_FACTORS_QUAD; 274 275 // These are the workhorse functions for tessellation: 276 // (1) Process input TessFactors 277 // (2) Generate points 278 // (3) Generate connectivity (can be done in parallel to (2)) 279 void IsoLineProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail, PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors ); 280 void IsoLineGeneratePoints( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors ); 281 void IsoLineGenerateConnectivity( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors ); 282 void TriProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor, PROCESSED_TESS_FACTORS_TRI& processedTessFactors ); 283 void TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors ); 284 void TriGenerateConnectivity( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors ); 285 void QuadProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1, 286 float insideTessFactor_U, float insideTessFactor_V, PROCESSED_TESS_FACTORS_QUAD& processedTessFactors ); 287 void QuadGeneratePoints( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors ); 288 void QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors ); 289 290 // Stitching 291 // --------- 292 // Given pointers to the beginning of 2 parallel rows of points, and TessFactors for each, stitch them. 293 // The assumption is the stitch is symmetric. 294 void StitchTransition(int baseIndexOffset, int insideEdgePointBaseOffset, int insideNumHalfTessFactorPoints, 295 TESSELLATOR_PARITY insideEdgeTessFactorParity, 296 int outsideEdgePointBaseOffset, int outsideNumHalfTessFactorPoints, 297 TESSELLATOR_PARITY outsideEdgeTessFactorParity ); 298 // The interior can just use a simpler stitch. 299 enum DIAGONALS 300 { 301 DIAGONALS_INSIDE_TO_OUTSIDE, 302 DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE, 303 DIAGONALS_MIRRORED 304 }; 305 306 void StitchRegular(bool bTrapezoid, DIAGONALS diagonals, int baseIndexOffset, int numInsideEdgePoints, 307 int insideEdgePointBaseOffset, int outsideEdgePointBaseOffset); 308 309 //--------------------------------------------------------------------------------------------------------------------------------- 310 // Index Patching 311 // -------------- 312 // The code below patches index values produces during triangulation, so triangulation doesn't have to know 313 // where points should go. I happened to never produce duplicate vertices, but the patching would 314 // be simpler if some duplicate vertices were introduced in practice. During point rendering mode however, 315 // it is not permitted for duplicate points to show up. 316 317 // Since the points are generated in concentric rings, most of the time, the point locations are 318 // sequentially increasing in memory for each side of a ring, which the stitch can take advantage of. 319 // However, there are exceptions where the points are not sequentially increasing, such as 320 // the 4th row in a given ring, where the last point on the outside of each row is actually the beginning 321 // point. 322 // So we let the stitching code think it sees sequential vertices, and when it emits a vertex index, 323 // we patch it to be the real location. 324 int PatchIndexValue(int index); 325 typedef struct INDEX_PATCH_CONTEXT 326 { 327 int insidePointIndexDeltaToRealValue; 328 int insidePointIndexBadValue; 329 int insidePointIndexReplacementValue; 330 int outsidePointIndexPatchBase; 331 int outsidePointIndexDeltaToRealValue; 332 int outsidePointIndexBadValue; 333 int outsidePointIndexReplacementValue; 334 } INDEX_PATCH_CONTEXT; SetUsingPatchedIndices(bool bUsingPatchedIndices)335 void SetUsingPatchedIndices(bool bUsingPatchedIndices) {m_bUsingPatchedIndices = bUsingPatchedIndices;} 336 337 // A second index patch we have to do handles the leftover strip of quads in the middle of an odd quad patch after 338 // finishing all the concentric rings. 339 // This also handles the leftover strip of points in the middle of an even quad 340 // patch, when stitching the row of triangles up the left side (V major quad) or bottom (U major quad) of the 341 // inner ring 342 typedef struct INDEX_PATCH_CONTEXT2 343 { 344 int baseIndexToInvert; 345 int indexInversionEndPoint; 346 int cornerCaseBadValue; 347 int cornerCaseReplacementValue; 348 } INDEX_PATCH_CONTEXT2; SetUsingPatchedIndices2(bool bUsingPatchedIndices)349 void SetUsingPatchedIndices2(bool bUsingPatchedIndices) {m_bUsingPatchedIndices2 = bUsingPatchedIndices;} 350 bool m_bUsingPatchedIndices; 351 bool m_bUsingPatchedIndices2; 352 INDEX_PATCH_CONTEXT m_IndexPatchContext; 353 INDEX_PATCH_CONTEXT2 m_IndexPatchContext2; 354 355 }; 356 357 //================================================================================================================================= 358 // CHLSLTessellator: PIPE Tessellation HLSL Tessellator Interface 359 // Demonstrates TessFactor preconditioning code auto-generated by HLSL. Subject to change, but this 360 // just represents the effect of shader code the HLSL compiler will generate in the Hull Shader, 361 // so it does not affect hardware design at all. 362 //================================================================================================================================= 363 class CHLSLTessellator : public CHWTessellator 364 { 365 public: 366 void Init( PIPE_TESSELLATOR_PARTITIONING partitioning, 367 PIPE_TESSELLATOR_REDUCTION insideTessFactorReduction, 368 PIPE_TESSELLATOR_QUAD_REDUCTION_AXIS quadInsideTessFactorReductionAxis, 369 PIPE_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive); 370 371 void TessellateIsoLineDomain( float TessFactor_V_LineDensity, 372 float TessFactor_U_LineDetail ); 373 374 void TessellateTriDomain( float tessFactor_Ueq0, 375 float TessFactor_Veq0, 376 float TessFactor_Weq0, 377 float insideTessFactorScale /*[0..1]*/ ); 378 379 void TessellateQuadDomain( float TessFactorUeq0, 380 float TessFactorVeq0, 381 float TessFactorUeq1, 382 float TessFactorVeq1, 383 float insideTessFactorScaleU /*[0..1]*/, 384 float insideTessFactorScaleV /*[0..1]*/ ); 385 GetPointCount()386 int GetPointCount() {return CHWTessellator::GetPointCount();}; GetIndexCount()387 int GetIndexCount() {return CHWTessellator::GetIndexCount();} 388 GetPoints()389 DOMAIN_POINT* GetPoints() {return CHWTessellator::GetPoints();} // Get CHLSLTessellator owned pointer to vertices (UV values). 390 // Pointer is fixed for lifetime of CHLSLTessellator object. GetIndices()391 int* GetIndices() {return CHWTessellator::GetIndices();} // Get CHLSLTessellator owned pointer to vertex indices. 392 // Pointer is fixed for lifetime of CHLSLTessellator object. 393 394 // Retrieve TessFactors actually used by the "hardware" 395 // This includes clamping to valid range, and more interestingly 396 // if integer or pow2 partitioning is being done, the rounded TessFactors can be retrieved. 397 // Getting the rounded TessFactors can be useful for geomorphing of displacement maps. GetIsoLineDensityTessFactor()398 float GetIsoLineDensityTessFactor() {return m_LastComputedTessFactors[0];} GetIsoLineDetailTessFactor()399 float GetIsoLineDetailTessFactor() {return m_LastComputedTessFactors[1];} GetTriUeq0TessFactor()400 float GetTriUeq0TessFactor() {return m_LastComputedTessFactors[0];} GetTriVeq0TessFactor()401 float GetTriVeq0TessFactor() {return m_LastComputedTessFactors[1];} GetTriWeq0TessFactor()402 float GetTriWeq0TessFactor() {return m_LastComputedTessFactors[2];} GetTriInsideTessFactor()403 float GetTriInsideTessFactor() {return m_LastComputedTessFactors[3];} GetQuadUeq0TessFactor()404 float GetQuadUeq0TessFactor() {return m_LastComputedTessFactors[0];} GetQuadVeq0TessFactor()405 float GetQuadVeq0TessFactor() {return m_LastComputedTessFactors[1];} GetQuadUeq1TessFactor()406 float GetQuadUeq1TessFactor() {return m_LastComputedTessFactors[2];} GetQuadVeq1TessFactor()407 float GetQuadVeq1TessFactor() {return m_LastComputedTessFactors[3];} GetQuadInsideUTessFactor()408 float GetQuadInsideUTessFactor() {return m_LastComputedTessFactors[4];} GetQuadInsideVTessFactor()409 float GetQuadInsideVTessFactor() {return m_LastComputedTessFactors[5];} GetUnRoundedIsoLineDensityTessFactor()410 float GetUnRoundedIsoLineDensityTessFactor() {return m_LastUnRoundedComputedTessFactors[0];} GetUnRoundedIsoLineDetailTessFactor()411 float GetUnRoundedIsoLineDetailTessFactor() {return m_LastUnRoundedComputedTessFactors[1];} GetUnRoundedTriUeq0TessFactor()412 float GetUnRoundedTriUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];} GetUnRoundedTriVeq0TessFactor()413 float GetUnRoundedTriVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];} GetUnRoundedTriWeq0TessFactor()414 float GetUnRoundedTriWeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[2];} GetUnRoundedTriInsideTessFactor()415 float GetUnRoundedTriInsideTessFactor() {return m_LastUnRoundedComputedTessFactors[3];} GetUnRoundedQuadUeq0TessFactor()416 float GetUnRoundedQuadUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];} GetUnRoundedQuadVeq0TessFactor()417 float GetUnRoundedQuadVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];} GetUnRoundedQuadUeq1TessFactor()418 float GetUnRoundedQuadUeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[2];} GetUnRoundedQuadVeq1TessFactor()419 float GetUnRoundedQuadVeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[3];} GetUnRoundedQuadInsideUTessFactor()420 float GetUnRoundedQuadInsideUTessFactor() {return m_LastUnRoundedComputedTessFactors[4];} GetUnRoundedQuadInsideVTessFactor()421 float GetUnRoundedQuadInsideVTessFactor() {return m_LastUnRoundedComputedTessFactors[5];} 422 423 CHLSLTessellator(); 424 //--------------------------------------------------------------------------------------------------------------------------------- 425 private: 426 TESSELLATOR_PARITY m_originalParity; // user chosen parity 427 TESSELLATOR_PARITY m_parity; // current parity: if allowing mix of even/odd during discrete 428 // tessellation, this can vary from the user defined parity 429 PIPE_TESSELLATOR_PARTITIONING m_originalPartitioning; // user chosen partitioning 430 PIPE_TESSELLATOR_PARTITIONING m_partitioning; // current partitioning. IsoLines overrides for line density 431 PIPE_TESSELLATOR_OUTPUT_PRIMITIVE m_outputPrimitive; 432 PIPE_TESSELLATOR_REDUCTION m_insideTessFactorReduction; 433 PIPE_TESSELLATOR_QUAD_REDUCTION_AXIS m_quadInsideTessFactorReductionAxis; 434 float m_LastComputedTessFactors[6]; // TessFactors used for last tessellation 435 float m_LastUnRoundedComputedTessFactors[6]; // TessFactors used for last tessellation (before they were rounded) IntegerPartitioning()436 bool IntegerPartitioning() {return (m_partitioning == PIPE_TESSELLATOR_PARTITIONING_INTEGER) ? true : false;} Pow2Partitioning()437 bool Pow2Partitioning() {return (m_partitioning == PIPE_TESSELLATOR_PARTITIONING_POW2)? true : false;} 438 void ClampTessFactor(float& TessFactor); 439 void RoundUpTessFactor(float& TessFactor); 440 void CleanupFloatTessFactor(float& input); // clamp float to [1.0f... +INF] (incl NaN->1.0f) 441 void ClampFloatTessFactorScale(float& input); // clamp float to [0.0f... +INF] (incl NaN->0.0f) 442 443 // Tessellation parity control Odd()444 bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;} SetTessellationParity(TESSELLATOR_PARITY parity)445 void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;} 446 447 // Tesselation Partitioning control RestorePartitioning()448 void RestorePartitioning() {m_partitioning = m_originalPartitioning;}; OverridePartitioning(PIPE_TESSELLATOR_PARTITIONING partitioning)449 void OverridePartitioning(PIPE_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density 450 451 void IsoLineHLSLProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail ); 452 void TriHLSLProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor ); 453 void QuadHLSLProcessTessFactors( float TessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Ueq1, float TessFactor_Veq1, 454 float insideTessFactor_U, float insideTessFactor_V ); 455 456 }; 457 458