Path: blob/21.2-virgl/src/gallium/auxiliary/tessellator/tessellator.hpp
4565 views
/*1Copyright (c) Microsoft Corporation23Permission is hereby granted, free of charge, to any person obtaining a copy of this software and4associated documentation files (the "Software"), to deal in the Software without restriction,5including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,6and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,7subject to the following conditions:89The above copyright notice and this permission notice shall be included in all copies or substantial10portions of the Software.1112THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT13NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.14IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,15WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE16SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.17*/1819#pragma once20//=================================================================================================================================21// Microsoft D3D11 Fixed Function Tessellator Reference - May 7, 201222// [email protected]23//24// CHWTessellator demonstrates what is expected of hardware in the D3D11 fixed function Tessellator stage. Hardware25// implementers need only look at this class.26//27// CHLSLTessellator is a wrapper for CHWTessellator, representing the effect of shader code that will28// be autogenerated by HLSL in the Hull Shader, both for plumbing data around, and to precondition TessFactor values before they29// are passed to the hardware (such as deriving inside TessFactors from edge TessFactors). The algorithms used30// in CHLSLTessellator are subject to change, but since they represent shader code auto-generated by the HLSL compiler,31// CHLSLTessellator has no effect on hardware design at all. Note the HLSL compiler will expose all the raw hardware32// control illustrated by CHWTessellator for those who don't need the helper functionality illustrated by CHLSLTessellator.33//34// Usage: (1) Create either a CHLSLTessellator or CHWTessellator object, depending on which you want to verify.35// (2) Call C*Tessellator::Init()36// (3) Call C*Tessellator::Tessellate[IsoLine|Tri|Quad]Domain()37// - Here you pass in TessFactors (how much to tessellate)38// (4) Call C*Tessellator::GetPointCount(), C*Tessellator::GetIndexCount() to see how much data was generated.39// (5) Call C*Tessellator::GetPoints() and C*Tessellator::GetIndices() to get pointers to the data.40// The pointers are fixed for the lifetime of the object (storage for max tessellation),41// so if you ::Tessellate again, the data in the buffers is overwritten.42// (6) There are various other Get() methods to retrieve TessFactors that have been processed from43// what you passed in at step 3. You can retrieve separate TessFactors that the tessellator44// produced after clamping but before rounding, and also after rounding (say in pow2 mode).45// These numbers can be useful information if you are geomorphing displacement maps.46// (7) Goto Step 2 or 3 if you want to animate TessFactors or tessellate a different patch47//48// Code implementation details:49//50// There is lots of headroom to make this code run faster on CPUs. It was written merely as a reference for51// what results hardware should produce, with CPU performance not a consideration. It is nice that this implementation52// only generates the exact number of vertices needed (no duplicates) in the output vertex buffer. Also, the number53// of calculations done for each U/V domain coordinate is minimized by doing some precalculation of some patch or edge54// invariant numbers (see TESS_FACTOR_CONTEXT). All the vertex coordinate calculations could be computed with as much55// parallelism as you like. Similarly the calculation of connectivity itself is highly parallelizable, and can also56// be done independent of the vertex calculations.57//58//=================================================================================================================================5960#define PIPE_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR 161#define PIPE_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR 6362#define PIPE_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR 263#define PIPE_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR 646465#define PIPE_TESSELLATOR_MIN_ISOLINE_DENSITY_TESSELLATION_FACTOR 166#define PIPE_TESSELLATOR_MAX_ISOLINE_DENSITY_TESSELLATION_FACTOR 646768#define PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR 64 // max of even and odd tessFactors6970#define MAX_POINT_COUNT ((PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR+1)*(PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR+1))71#define MAX_INDEX_COUNT (PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR*PIPE_TESSELLATOR_MAX_TESSELLATION_FACTOR*2*3)7273//=================================================================================================================================74// Data types for the caller75//=================================================================================================================================76enum PIPE_TESSELLATOR_PARTITIONING77{78PIPE_TESSELLATOR_PARTITIONING_INTEGER,79PIPE_TESSELLATOR_PARTITIONING_POW2,80PIPE_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD,81PIPE_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN82};8384enum PIPE_TESSELLATOR_REDUCTION85{86PIPE_TESSELLATOR_REDUCTION_MIN,87PIPE_TESSELLATOR_REDUCTION_MAX,88PIPE_TESSELLATOR_REDUCTION_AVERAGE89};9091enum PIPE_TESSELLATOR_QUAD_REDUCTION_AXIS92{93PIPE_TESSELLATOR_QUAD_REDUCTION_1_AXIS,94PIPE_TESSELLATOR_QUAD_REDUCTION_2_AXIS95};9697enum PIPE_TESSELLATOR_OUTPUT_PRIMITIVE98{99PIPE_TESSELLATOR_OUTPUT_POINT,100PIPE_TESSELLATOR_OUTPUT_LINE,101PIPE_TESSELLATOR_OUTPUT_TRIANGLE_CW,102PIPE_TESSELLATOR_OUTPUT_TRIANGLE_CCW,103};104105typedef struct DOMAIN_POINT106{107float u;108float v; // for tri, w = 1 - u - v;109} DOMAIN_POINT;110111//=================================================================================================================================112// CHWTessellator: D3D11 Tessellation Fixed Function Hardware Reference113//=================================================================================================================================114typedef unsigned int FXP; // fixed point number115116class CHWTessellator117{118119//---------------------------------------------------------------------------------------------------------------------------------120public:121void Init( PIPE_TESSELLATOR_PARTITIONING partitioning,122PIPE_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive);123124void TessellateIsoLineDomain( float TessFactor_V_LineDensity,125float TessFactor_U_LineDetail );126127void TessellateTriDomain( float TessFactor_Ueq0,128float TessFactor_Veq0,129float TessFactor_Weq0,130float TessFactor_Inside );131132void TessellateQuadDomain( float TessFactor_Ueq0,133float TessFactor_Veq0,134float TessFactor_Ueq1,135float TessFactor_Veq1,136float TessFactor_InsideU,137float TessFactor_InsideV );138139int GetPointCount();140int GetIndexCount();141142DOMAIN_POINT* GetPoints(); // Get CHWTessellator owned pointer to vertices (UV values).143// Pointer is fixed for lifetime of CHWTessellator object.144int* GetIndices(); // Get CHWTessellator owned pointer to vertex indices.145// Pointer is fixed for lifetime of CHWTessellator object.146147CHWTessellator();148~CHWTessellator();149//---------------------------------------------------------------------------------------------------------------------------------150//=============================================================================================================================151// Some defines so that numbers are usually self commenting152//=============================================================================================================================153static const int U = 0; // points on a tri patch154static const int V = 1;155static const int W = 2;156static const int Ueq0 = 0; // edges on a tri patch157static const int Veq0 = 1;158static const int Weq0 = 2;159160static const int Ueq1 = 2; // edges on a quad patch: Ueq0, Veq0, Ueq1, Veq1161static const int Veq1 = 3;162163static const int QUAD_AXES = 2;164static const int QUAD_EDGES = 4;165static const int TRI_EDGES = 3;166//=============================================================================================================================167168enum TESSELLATOR_PARITY // derived from PIPE_TESSELLATOR_PARTITIONING169{ // (note: for integer tessellation, both parities are used)170TESSELLATOR_PARITY_EVEN,171TESSELLATOR_PARITY_ODD172};173private:174TESSELLATOR_PARITY m_originalParity; // user chosen parity175TESSELLATOR_PARITY m_parity; // current parity: if allowing mix of even/odd during discrete176// tessellation, this can vary from the user defined parity177PIPE_TESSELLATOR_PARTITIONING m_originalPartitioning; // user chosen partitioning178PIPE_TESSELLATOR_PARTITIONING m_partitioning; // current partitioning. IsoLines overrides for line density179PIPE_TESSELLATOR_OUTPUT_PRIMITIVE m_outputPrimitive;180DOMAIN_POINT* m_Point; // array where we will store u/v's for the points we generate181int* m_Index; // array where we will store index topology182int m_NumPoints;183int m_NumIndices;184// PlacePointIn1D below is the workhorse for all position placement.185// It is code that could run as preamble in a Domain Shader, so the tessellator itself186// doesn't necessarily need to have floating point.187// Some per-TessFactor fixed context is needed, and that can be computed wherever188// the TessFactor reduction is done, perhaps as Hull Shader postamble - this is shared189// for all point evaluation.190typedef struct TESS_FACTOR_CONTEXT191{192FXP fxpInvNumSegmentsOnFloorTessFactor;193FXP fxpInvNumSegmentsOnCeilTessFactor;194FXP fxpHalfTessFactorFraction;195int numHalfTessFactorPoints;196int splitPointOnFloorHalfTessFactor;197} TESS_FACTOR_CONTEXT;198void ComputeTessFactorContext( FXP fxpTessFactor, TESS_FACTOR_CONTEXT& TessFactorCtx );199void PlacePointIn1D( const TESS_FACTOR_CONTEXT& TessFactorCtx, int point, FXP& fxpLocation );200201int NumPointsForTessFactor(FXP fxpTessFactor);202203// Tessellation parity control204bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;}205void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;}206207// HWIntegerPartitioning() - hardware doesn't care about what pow2 partitioning is - the query below is true for208// both integer and pow2.209bool HWIntegerPartitioning() {return ((m_partitioning == PIPE_TESSELLATOR_PARTITIONING_INTEGER)||210(m_partitioning == PIPE_TESSELLATOR_PARTITIONING_POW2)) ? true : false;}211212// Tesselation Partitioning control213void RestorePartitioning() {m_partitioning = m_originalPartitioning;};214void OverridePartitioning(PIPE_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density215216// Call these to generate new points and indices. Max TessFactor storage is already allocated.217int DefinePoint(FXP u, FXP v, int pointStorageOffset);218void DefineIndex(int index, int indexStorageOffset);219void DefineClockwiseTriangle(int index0, int index1, int index2, int indexStorageBaseOffset);220221// Couple of trivial ways to generate index data just given points and no other connectivity.222void DumpAllPoints(); // Make point indices for point rendering mode -223// redundant, but just here for orthogonality.224void DumpAllPointsAsInOrderLineList(); // A debug visualization of all the points connected225// in the order they were generated.226// Asking to draw line topology on a tri or quad patch will do this227228229// The structures below define the data that is derived given input TessFactors and which230// is used by point generation and connectivity generation steps (each of which are independent)231typedef struct PROCESSED_TESS_FACTORS_ISOLINE232{233TESSELLATOR_PARITY lineDensityParity;234TESSELLATOR_PARITY lineDetailParity;235TESS_FACTOR_CONTEXT lineDensityTessFactorCtx;236TESS_FACTOR_CONTEXT lineDetailTessFactorCtx;237bool bPatchCulled;238int numPointsPerLine;239int numLines;240} PROCESSED_TESS_FACTORS_ISOLINE;241typedef struct PROCESSED_TESS_FACTORS_TRI242{243FXP outsideTessFactor[TRI_EDGES];244FXP insideTessFactor;245TESSELLATOR_PARITY outsideTessFactorParity[TRI_EDGES];246TESSELLATOR_PARITY insideTessFactorParity;247TESS_FACTOR_CONTEXT outsideTessFactorCtx[TRI_EDGES];248TESS_FACTOR_CONTEXT insideTessFactorCtx;249bool bJustDoMinimumTessFactor;250bool bPatchCulled;251// Stuff below is just specific to the traversal order252// this code happens to use to generate points/lines253int numPointsForOutsideEdge[TRI_EDGES];254int numPointsForInsideTessFactor;255int insideEdgePointBaseOffset;256} PROCESSED_TESS_FACTORS_TRI;257typedef struct PROCESSED_TESS_FACTORS_QUAD258{259FXP outsideTessFactor[QUAD_EDGES];260FXP insideTessFactor[QUAD_AXES];261TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES];262TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES];263TESS_FACTOR_CONTEXT outsideTessFactorCtx[QUAD_EDGES];264TESS_FACTOR_CONTEXT insideTessFactorCtx[QUAD_AXES];265bool bJustDoMinimumTessFactor;266bool bPatchCulled;267// Stuff below is just specific to the traversal order268// this code happens to use to generate points/lines269int numPointsForOutsideEdge[QUAD_EDGES];270int numPointsForInsideTessFactor[QUAD_AXES];271int insideEdgePointBaseOffset;272} PROCESSED_TESS_FACTORS_QUAD;273274// These are the workhorse functions for tessellation:275// (1) Process input TessFactors276// (2) Generate points277// (3) Generate connectivity (can be done in parallel to (2))278void IsoLineProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail, PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );279void IsoLineGeneratePoints( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );280void IsoLineGenerateConnectivity( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );281void TriProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor, PROCESSED_TESS_FACTORS_TRI& processedTessFactors );282void TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors );283void TriGenerateConnectivity( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors );284void QuadProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1,285float insideTessFactor_U, float insideTessFactor_V, PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );286void QuadGeneratePoints( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );287void QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );288289// Stitching290// ---------291// Given pointers to the beginning of 2 parallel rows of points, and TessFactors for each, stitch them.292// The assumption is the stitch is symmetric.293void StitchTransition(int baseIndexOffset, int insideEdgePointBaseOffset, int insideNumHalfTessFactorPoints,294TESSELLATOR_PARITY insideEdgeTessFactorParity,295int outsideEdgePointBaseOffset, int outsideNumHalfTessFactorPoints,296TESSELLATOR_PARITY outsideEdgeTessFactorParity );297// The interior can just use a simpler stitch.298enum DIAGONALS299{300DIAGONALS_INSIDE_TO_OUTSIDE,301DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE,302DIAGONALS_MIRRORED303};304305void StitchRegular(bool bTrapezoid, DIAGONALS diagonals, int baseIndexOffset, int numInsideEdgePoints,306int insideEdgePointBaseOffset, int outsideEdgePointBaseOffset);307308//---------------------------------------------------------------------------------------------------------------------------------309// Index Patching310// --------------311// The code below patches index values produces during triangulation, so triangulation doesn't have to know312// where points should go. I happened to never produce duplicate vertices, but the patching would313// be simpler if some duplicate vertices were introduced in practice. During point rendering mode however,314// it is not permitted for duplicate points to show up.315316// Since the points are generated in concentric rings, most of the time, the point locations are317// sequentially increasing in memory for each side of a ring, which the stitch can take advantage of.318// However, there are exceptions where the points are not sequentially increasing, such as319// the 4th row in a given ring, where the last point on the outside of each row is actually the beginning320// point.321// So we let the stitching code think it sees sequential vertices, and when it emits a vertex index,322// we patch it to be the real location.323int PatchIndexValue(int index);324typedef struct INDEX_PATCH_CONTEXT325{326int insidePointIndexDeltaToRealValue;327int insidePointIndexBadValue;328int insidePointIndexReplacementValue;329int outsidePointIndexPatchBase;330int outsidePointIndexDeltaToRealValue;331int outsidePointIndexBadValue;332int outsidePointIndexReplacementValue;333} INDEX_PATCH_CONTEXT;334void SetUsingPatchedIndices(bool bUsingPatchedIndices) {m_bUsingPatchedIndices = bUsingPatchedIndices;}335336// A second index patch we have to do handles the leftover strip of quads in the middle of an odd quad patch after337// finishing all the concentric rings.338// This also handles the leftover strip of points in the middle of an even quad339// patch, when stitching the row of triangles up the left side (V major quad) or bottom (U major quad) of the340// inner ring341typedef struct INDEX_PATCH_CONTEXT2342{343int baseIndexToInvert;344int indexInversionEndPoint;345int cornerCaseBadValue;346int cornerCaseReplacementValue;347} INDEX_PATCH_CONTEXT2;348void SetUsingPatchedIndices2(bool bUsingPatchedIndices) {m_bUsingPatchedIndices2 = bUsingPatchedIndices;}349bool m_bUsingPatchedIndices;350bool m_bUsingPatchedIndices2;351INDEX_PATCH_CONTEXT m_IndexPatchContext;352INDEX_PATCH_CONTEXT2 m_IndexPatchContext2;353354};355356//=================================================================================================================================357// CHLSLTessellator: PIPE Tessellation HLSL Tessellator Interface358// Demonstrates TessFactor preconditioning code auto-generated by HLSL. Subject to change, but this359// just represents the effect of shader code the HLSL compiler will generate in the Hull Shader,360// so it does not affect hardware design at all.361//=================================================================================================================================362class CHLSLTessellator : public CHWTessellator363{364public:365void Init( PIPE_TESSELLATOR_PARTITIONING partitioning,366PIPE_TESSELLATOR_REDUCTION insideTessFactorReduction,367PIPE_TESSELLATOR_QUAD_REDUCTION_AXIS quadInsideTessFactorReductionAxis,368PIPE_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive);369370void TessellateIsoLineDomain( float TessFactor_V_LineDensity,371float TessFactor_U_LineDetail );372373void TessellateTriDomain( float tessFactor_Ueq0,374float TessFactor_Veq0,375float TessFactor_Weq0,376float insideTessFactorScale /*[0..1]*/ );377378void TessellateQuadDomain( float TessFactorUeq0,379float TessFactorVeq0,380float TessFactorUeq1,381float TessFactorVeq1,382float insideTessFactorScaleU /*[0..1]*/,383float insideTessFactorScaleV /*[0..1]*/ );384385int GetPointCount() {return CHWTessellator::GetPointCount();};386int GetIndexCount() {return CHWTessellator::GetIndexCount();}387388DOMAIN_POINT* GetPoints() {return CHWTessellator::GetPoints();} // Get CHLSLTessellator owned pointer to vertices (UV values).389// Pointer is fixed for lifetime of CHLSLTessellator object.390int* GetIndices() {return CHWTessellator::GetIndices();} // Get CHLSLTessellator owned pointer to vertex indices.391// Pointer is fixed for lifetime of CHLSLTessellator object.392393// Retrieve TessFactors actually used by the "hardware"394// This includes clamping to valid range, and more interestingly395// if integer or pow2 partitioning is being done, the rounded TessFactors can be retrieved.396// Getting the rounded TessFactors can be useful for geomorphing of displacement maps.397float GetIsoLineDensityTessFactor() {return m_LastComputedTessFactors[0];}398float GetIsoLineDetailTessFactor() {return m_LastComputedTessFactors[1];}399float GetTriUeq0TessFactor() {return m_LastComputedTessFactors[0];}400float GetTriVeq0TessFactor() {return m_LastComputedTessFactors[1];}401float GetTriWeq0TessFactor() {return m_LastComputedTessFactors[2];}402float GetTriInsideTessFactor() {return m_LastComputedTessFactors[3];}403float GetQuadUeq0TessFactor() {return m_LastComputedTessFactors[0];}404float GetQuadVeq0TessFactor() {return m_LastComputedTessFactors[1];}405float GetQuadUeq1TessFactor() {return m_LastComputedTessFactors[2];}406float GetQuadVeq1TessFactor() {return m_LastComputedTessFactors[3];}407float GetQuadInsideUTessFactor() {return m_LastComputedTessFactors[4];}408float GetQuadInsideVTessFactor() {return m_LastComputedTessFactors[5];}409float GetUnRoundedIsoLineDensityTessFactor() {return m_LastUnRoundedComputedTessFactors[0];}410float GetUnRoundedIsoLineDetailTessFactor() {return m_LastUnRoundedComputedTessFactors[1];}411float GetUnRoundedTriUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];}412float GetUnRoundedTriVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];}413float GetUnRoundedTriWeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[2];}414float GetUnRoundedTriInsideTessFactor() {return m_LastUnRoundedComputedTessFactors[3];}415float GetUnRoundedQuadUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];}416float GetUnRoundedQuadVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];}417float GetUnRoundedQuadUeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[2];}418float GetUnRoundedQuadVeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[3];}419float GetUnRoundedQuadInsideUTessFactor() {return m_LastUnRoundedComputedTessFactors[4];}420float GetUnRoundedQuadInsideVTessFactor() {return m_LastUnRoundedComputedTessFactors[5];}421422CHLSLTessellator();423//---------------------------------------------------------------------------------------------------------------------------------424private:425TESSELLATOR_PARITY m_originalParity; // user chosen parity426TESSELLATOR_PARITY m_parity; // current parity: if allowing mix of even/odd during discrete427// tessellation, this can vary from the user defined parity428PIPE_TESSELLATOR_PARTITIONING m_originalPartitioning; // user chosen partitioning429PIPE_TESSELLATOR_PARTITIONING m_partitioning; // current partitioning. IsoLines overrides for line density430PIPE_TESSELLATOR_OUTPUT_PRIMITIVE m_outputPrimitive;431PIPE_TESSELLATOR_REDUCTION m_insideTessFactorReduction;432PIPE_TESSELLATOR_QUAD_REDUCTION_AXIS m_quadInsideTessFactorReductionAxis;433float m_LastComputedTessFactors[6]; // TessFactors used for last tessellation434float m_LastUnRoundedComputedTessFactors[6]; // TessFactors used for last tessellation (before they were rounded)435bool IntegerPartitioning() {return (m_partitioning == PIPE_TESSELLATOR_PARTITIONING_INTEGER) ? true : false;}436bool Pow2Partitioning() {return (m_partitioning == PIPE_TESSELLATOR_PARTITIONING_POW2)? true : false;}437void ClampTessFactor(float& TessFactor);438void RoundUpTessFactor(float& TessFactor);439void CleanupFloatTessFactor(float& input); // clamp float to [1.0f... +INF] (incl NaN->1.0f)440void ClampFloatTessFactorScale(float& input); // clamp float to [0.0f... +INF] (incl NaN->0.0f)441442// Tessellation parity control443bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;}444void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;}445446// Tesselation Partitioning control447void RestorePartitioning() {m_partitioning = m_originalPartitioning;};448void OverridePartitioning(PIPE_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density449450void IsoLineHLSLProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail );451void TriHLSLProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor );452void QuadHLSLProcessTessFactors( float TessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Ueq1, float TessFactor_Veq1,453float insideTessFactor_U, float insideTessFactor_V );454455};456457458459