diff options
Diffstat (limited to 'lib/mesa/src/gallium/auxiliary/tessellator/tessellator.cpp')
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/tessellator/tessellator.cpp | 2705 |
1 files changed, 0 insertions, 2705 deletions
diff --git a/lib/mesa/src/gallium/auxiliary/tessellator/tessellator.cpp b/lib/mesa/src/gallium/auxiliary/tessellator/tessellator.cpp deleted file mode 100644 index ac16aabd0..000000000 --- a/lib/mesa/src/gallium/auxiliary/tessellator/tessellator.cpp +++ /dev/null @@ -1,2705 +0,0 @@ -/* - Copyright (c) Microsoft Corporation - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - associated documentation files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "tessellator.hpp" -#if defined(__MINGW32__) || defined(__MINGW64__) -#include <cmath> -#elif defined(_WIN32) || defined(_WIN64) -#include <math.h> // ceil -#else -#include <cmath> -#endif -//#include <windows.h> // Just used for some commented out debug stat printing. -//#include <strsafe.h> // Ditto. -#define min(x,y) (x < y ? x : y) -#define max(x,y) (x > y ? x : y) - -//================================================================================================================================= -// Some D3D Compliant Float Math (reference rasterizer implements these in RefALU class) -//================================================================================================================================= -// -//--------------------------------------------------------------------------------------------------------------------------------- -// isNaN -//--------------------------------------------------------------------------------------------------------------------------------- - -union fiu { - float f; - int i; -}; - -static bool tess_isNaN( float a ) -{ - static const int exponentMask = 0x7f800000; - static const int mantissaMask = 0x007fffff; - union fiu fiu; - fiu.f = a; - return ( ( ( fiu.i & exponentMask ) == exponentMask ) && ( fiu.i & mantissaMask ) ); // NaN -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// flush (denorm) -//--------------------------------------------------------------------------------------------------------------------------------- -static float tess_flush( float a ) -{ - static const int minNormalizedFloat = 0x00800000; - static const int signBit = 0x80000000; - static const int signBitComplement = 0x7fffffff; - union fiu fiu, uif; - fiu.f = a; - int b = fiu.i & signBitComplement; // fabs() - if( b < minNormalizedFloat ) // UINT comparison. NaN/INF do test false here - { - b = signBit & (fiu.i); - uif.i = b; - return uif.f; - } - return a; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// IEEE754R min -//--------------------------------------------------------------------------------------------------------------------------------- -static float tess_fmin( float a, float b ) -{ - float _a = tess_flush( a ); - float _b = tess_flush( b ); - if( tess_isNaN( _b ) ) - { - return a; - } - else if( ( _a == 0 ) && ( _b == 0 ) ) - { - union fiu fiu; - fiu.f = _a; - return ( fiu.i & 0x80000000 ) ? a : b; - } - return _a < _b ? a : b; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// IEEE754R max -//--------------------------------------------------------------------------------------------------------------------------------- -static float tess_fmax( float a, float b ) -{ - float _a = tess_flush( a ); - float _b = tess_flush( b ); - - if( tess_isNaN( _b ) ) - { - return a; - } - else if( ( _a == 0 ) && ( _b == 0 ) ) - { - union fiu fiu; - fiu.f = _b; - return ( fiu.i & 0x80000000 ) ? a : b; - } - return _a >= _b ? a : b; -} - -//================================================================================================================================= -// Fixed Point Math -//================================================================================================================================= - -//----------------------------------------------------------------------------------------------------------------------------- -// floatToFixedPoint -// -// Convert 32-bit float to 32-bit fixed point integer, using only -// integer arithmetic + bitwise operations. -// -// c_uIBits: UINT8 : Width of i (aka. integer bits) -// c_uFBits: UINT8 : Width of f (aka. fractional bits) -// c_bSigned: bool : Whether the integer bits are a 2's complement signed value -// input: float : All values valid. -// output: INT32 : At most 24 bits from LSB are meaningful, depending -// on the fixed point bit representation chosen (see -// below). Extra bits are sign extended from the most -// meaningful bit. -// -//----------------------------------------------------------------------------------------------------------------------------- - -typedef unsigned char UINT8; -typedef int INT32; -template< const UINT8 c_uIBits, const UINT8 c_uFBits, const bool c_bSigned > -INT32 floatToIDotF( const float& input ) -{ - // ------------------------------------------------------------------------ - // output fixed point format - // 32-bit result: - // - // [sign-extend]i.f - // | | - // MSB(31)...LSB(0) - // - // f fractional part of the number, an unsigned - // value with _fxpFracBitCount bits (defined below) - // - // . implied decimal - // - // i integer part of the number, a 2's complement - // value with _fxpIntBitCount bits (defined below) - // - // [sign-extend] MSB of i conditionally replicated - // - // ------------------------------------------------------------------------ - // Define fixed point bit counts - // - - // Commenting out C_ASSERT below to minimise #includes: - // C_ASSERT( 2 <= c_uIBits && c_uIBits <= 32 && c_uFBits <= 32 && c_uIBits + c_uFBits <= 32 ); - - // Define most negative and most positive fixed point values - const INT32 c_iMinResult = (c_bSigned ? INT32( -1 ) << (c_uIBits + c_uFBits - 1) : 0); - const INT32 c_iMaxResult = ~c_iMinResult; - - // ------------------------------------------------------------------------ - // constant float properties - // ------------------------------------------------------------------------ - const UINT8 _fltMantissaBitCount = 23; - const UINT8 _fltExponentBitCount = 8; - const INT32 _fltExponentBias = (INT32( 1 ) << (_fltExponentBitCount - 1)) - 1; - const INT32 _fltHiddenBit = INT32( 1 ) << _fltMantissaBitCount; - const INT32 _fltMantissaMask = _fltHiddenBit - 1; - const INT32 _fltExponentMask = ((INT32( 1 ) << _fltExponentBitCount) - 1) << _fltMantissaBitCount; - const INT32 _fltSignBit = INT32( 1 ) << (_fltExponentBitCount + _fltMantissaBitCount); - - // ------------------------------------------------------------------------ - // define min and max values as floats (clamp to these bounds) - // ------------------------------------------------------------------------ - INT32 _fxpMaxPosValueFloat; - INT32 _fxpMaxNegValueFloat; - - if (c_bSigned) - { - // The maximum positive fixed point value is 2^(i-1) - 2^(-f). - // The following constructs the floating point bit pattern for this value, - // as long as i >= 2. - _fxpMaxPosValueFloat = (_fltExponentBias + c_uIBits - 1) <<_fltMantissaBitCount; - const INT32 iShift = _fltMantissaBitCount + 2 - c_uIBits - c_uFBits; - if (iShift >= 0) - { -// assert( iShift < 32 ); -#if defined(_WIN32) || defined(_WIN64) -#pragma warning( suppress : 4293 ) -#endif - _fxpMaxPosValueFloat -= INT32( 1 ) << iShift; - } - - // The maximum negative fixed point value is -2^(i-1). - // The following constructs the floating point bit pattern for this value, - // as long as i >= 2. - // We need this number without the sign bit - _fxpMaxNegValueFloat = (_fltExponentBias + c_uIBits - 1) << _fltMantissaBitCount; - } - else - { - // The maximum positive fixed point value is 2^(i) - 2^(-f). - // The following constructs the floating point bit pattern for this value, - // as long as i >= 2. - _fxpMaxPosValueFloat = (_fltExponentBias + c_uIBits) <<_fltMantissaBitCount; - const INT32 iShift = _fltMantissaBitCount + 1 - c_uIBits - c_uFBits; - if (iShift >= 0) - { -// assert( iShift < 32 ); -#if defined(_WIN32) || defined(_WIN64) -#pragma warning( suppress : 4293 ) -#endif - _fxpMaxPosValueFloat -= INT32( 1 ) << iShift; - } - - // The maximum negative fixed point value is 0. - _fxpMaxNegValueFloat = 0; - } - - // ------------------------------------------------------------------------ - // float -> fixed conversion - // ------------------------------------------------------------------------ - - // ------------------------------------------------------------------------ - // examine input float - // ------------------------------------------------------------------------ - INT32 output = *(INT32*)&input; - INT32 unbiasedExponent = ((output & _fltExponentMask) >> _fltMantissaBitCount) - _fltExponentBias; - INT32 isNegative = output & _fltSignBit; - - // ------------------------------------------------------------------------ - // nan - // ------------------------------------------------------------------------ - if (unbiasedExponent == (_fltExponentBias + 1) && (output & _fltMantissaMask)) - { - // nan converts to 0 - output = 0; - } - // ------------------------------------------------------------------------ - // too large positive - // ------------------------------------------------------------------------ - else if (!isNegative && output >= _fxpMaxPosValueFloat) // integer compare - { - output = c_iMaxResult; - } - // ------------------------------------------------------------------------ - // too large negative - // ------------------------------------------------------------------------ - // integer compare - else if (isNegative && (output & ~_fltSignBit) >= _fxpMaxNegValueFloat) - { - output = c_iMinResult; - } - // ------------------------------------------------------------------------ - // too small - // ------------------------------------------------------------------------ - else if (unbiasedExponent < -c_uFBits - 1) - { - // clamp to 0 - output = 0; - } - // ------------------------------------------------------------------------ - // within range - // ------------------------------------------------------------------------ - else - { - // copy mantissa, add hidden bit - output = (output & _fltMantissaMask) | _fltHiddenBit; - - INT32 extraBits = _fltMantissaBitCount - c_uFBits - unbiasedExponent; - if (extraBits >= 0) - { - // 2's complement if negative - if (isNegative) - { - output = ~output + 1; - } - - // From the range checks that led here, it is known that - // unbiasedExponent < c_uIBits. So, at most: - // (a) unbiasedExponent == c_uIBits - 1. - // - // From compile validation above, it is known that - // c_uIBits + c_uFBits <= _fltMantissaBitCount + 1). - // So, at minimum: - // (b) _fltMantissaBitCount == _fxtIntBitCount + c_uFBits - 1 - // - // Substituting (a) and (b) into extraBits calculation above: - // extraBits >= (_fxtIntBitCount + c_uFBits - 1) - // - c_uFBits - (c_uIBits - 1) - // extraBits >= 0 - // - // Thus we only have to worry about shifting right by 0 or more - // bits to get the decimal to the right place, and never have - // to shift left. - - INT32 LSB = 1 << extraBits; // last bit being kept - INT32 extraBitsMask = LSB - 1; - INT32 half = LSB >> 1; // round bias - - // round to nearest-even at LSB - if ((output & LSB) || (output & extraBitsMask) > half) - { - output += half; - } - - // shift off the extra bits (sign extending) - output >>= extraBits; - } - else - { - output <<= -extraBits; - - // 2's complement if negative - if (isNegative) - { - output = ~output + 1; - } - } - } - return output; -} -//----------------------------------------------------------------------------------------------------------------------------- - -#define FXP_INTEGER_BITS 15 -#define FXP_FRACTION_BITS 16 -#define FXP_FRACTION_MASK 0x0000ffff -#define FXP_INTEGER_MASK 0x7fff0000 -#define FXP_THREE (3<<FXP_FRACTION_BITS) -#define FXP_ONE (1<<FXP_FRACTION_BITS) -#define FXP_ONE_THIRD 0x00005555 -#define FXP_TWO_THIRDS 0x0000aaaa -#define FXP_ONE_HALF 0x00008000 - -#define FXP_MAX_INPUT_TESS_FACTOR_BEFORE_TRIPLE_AVERAGE 0x55540000 // 1/3 of max fixed point number - 1. Numbers less than - // or equal to this allows avg. reduction on a tri patch - // including rounding. - -#define FXP_MAX_INPUT_TESS_FACTOR_BEFORE_PAIR_AVERAGE 0x7FFF0000 // 1/2 of max fixed point number - 1. Numbers less than - // or equal to this allows avg. reduction on a quad patch - // including rounding. - -static const FXP s_fixedReciprocal[D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR+1] = -{ - 0xffffffff, // 1/0 is the first entry (unused) - 0x10000, 0x8000, 0x5555, 0x4000, - 0x3333, 0x2aab, 0x2492, 0x2000, - 0x1c72, 0x199a, 0x1746, 0x1555, - 0x13b1, 0x1249, 0x1111, 0x1000, - 0xf0f, 0xe39, 0xd79, 0xccd, - 0xc31, 0xba3, 0xb21, 0xaab, - 0xa3d, 0x9d9, 0x97b, 0x925, - 0x8d4, 0x889, 0x842, 0x800, - 0x7c2, 0x788, 0x750, 0x71c, - 0x6eb, 0x6bd, 0x690, 0x666, - 0x63e, 0x618, 0x5f4, 0x5d1, - 0x5b0, 0x591, 0x572, 0x555, - 0x539, 0x51f, 0x505, 0x4ec, - 0x4d5, 0x4be, 0x4a8, 0x492, - 0x47e, 0x46a, 0x457, 0x444, - 0x432, 0x421, 0x410, 0x400, // 1/64 is the last entry -}; - -#define FLOAT_THREE 3.0f -#define FLOAT_ONE 1.0f - -//--------------------------------------------------------------------------------------------------------------------------------- -// floatToFixed -//--------------------------------------------------------------------------------------------------------------------------------- -FXP floatToFixed(const float& input) -{ - return floatToIDotF< FXP_INTEGER_BITS, FXP_FRACTION_BITS, /*bSigned*/false >( input ); -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// fixedToFloat -//--------------------------------------------------------------------------------------------------------------------------------- -float fixedToFloat(const FXP& input) -{ - // not worrying about denorm flushing the float operations (the DX spec behavior for div), since the numbers will not be that small during tessellation. - return ((float)(input>>FXP_FRACTION_BITS) + (float)(input&FXP_FRACTION_MASK)/(1<<FXP_FRACTION_BITS)); -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// isEven -//--------------------------------------------------------------------------------------------------------------------------------- -bool isEven(const float& input) -{ - return (((int)input) & 1) ? false : true; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// fxpCeil -//--------------------------------------------------------------------------------------------------------------------------------- -FXP fxpCeil(const FXP& input) -{ - if( input & FXP_FRACTION_MASK ) - { - return (input & FXP_INTEGER_MASK) + FXP_ONE; - } - return input; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// fxpFloor -//--------------------------------------------------------------------------------------------------------------------------------- -FXP fxpFloor(const FXP& input) -{ - return (input & FXP_INTEGER_MASK); -} - -//================================================================================================================================= -// CHWTessellator -//================================================================================================================================= - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::CHWTessellator -//--------------------------------------------------------------------------------------------------------------------------------- -CHWTessellator::CHWTessellator() -{ - m_Point = 0; - m_Index = 0; - m_NumPoints = 0; - m_NumIndices = 0; - m_bUsingPatchedIndices = false; - m_bUsingPatchedIndices2 = false; -#ifdef ALLOW_XBOX_360_COMPARISON - m_bXBox360Mode = false; -#endif -} -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::~CHWTessellator -//--------------------------------------------------------------------------------------------------------------------------------- -CHWTessellator::~CHWTessellator() -{ - delete [] m_Point; - delete [] m_Index; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::Init -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::Init( - D3D11_TESSELLATOR_PARTITIONING partitioning, - D3D11_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive) -{ - if( 0 == m_Point ) - { - m_Point = new DOMAIN_POINT[MAX_POINT_COUNT]; - } - if( 0 == m_Index ) - { - m_Index = new int[MAX_INDEX_COUNT]; - } - m_partitioning = partitioning; - m_originalPartitioning = partitioning; - switch( partitioning ) - { - case D3D11_TESSELLATOR_PARTITIONING_INTEGER: - default: - break; - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: - m_parity = TESSELLATOR_PARITY_ODD; - break; - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: - m_parity = TESSELLATOR_PARITY_EVEN; - break; - } - m_originalParity = m_parity; - m_outputPrimitive = outputPrimitive; - m_NumPoints = 0; - m_NumIndices = 0; -} -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::TessellateQuadDomain -// User calls this -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::TessellateQuadDomain( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1, - float insideTessFactor_U, float insideTessFactor_V ) -{ - PROCESSED_TESS_FACTORS_QUAD processedTessFactors; - QuadProcessTessFactors(tessFactor_Ueq0,tessFactor_Veq0,tessFactor_Ueq1,tessFactor_Veq1,insideTessFactor_U,insideTessFactor_V,processedTessFactors); - - if( processedTessFactors.bPatchCulled ) - { - m_NumPoints = 0; - m_NumIndices = 0; - return; - } - else if( processedTessFactors.bJustDoMinimumTessFactor ) - { - DefinePoint(/*U*/0,/*V*/0,/*pointStorageOffset*/0); - DefinePoint(/*U*/FXP_ONE,/*V*/0,/*pointStorageOffset*/1); - DefinePoint(/*U*/FXP_ONE,/*V*/FXP_ONE,/*pointStorageOffset*/2); - DefinePoint(/*U*/0,/*V*/FXP_ONE,/*pointStorageOffset*/3); - m_NumPoints = 4; - - switch(m_outputPrimitive) - { - case D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW: - case D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW: - // function orients them CCW if needed - DefineClockwiseTriangle(0,1,3,/*indexStorageOffset*/0); - DefineClockwiseTriangle(1,2,3,/*indexStorageOffset*/3); - m_NumIndices = 6; - break; - case D3D11_TESSELLATOR_OUTPUT_POINT: - DumpAllPoints(); - break; - case D3D11_TESSELLATOR_OUTPUT_LINE: - DumpAllPointsAsInOrderLineList(); - break; - } - return; - } - - QuadGeneratePoints(processedTessFactors); - - if( m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_POINT ) - { - DumpAllPoints(); - return; - } - if( m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_LINE ) - { - DumpAllPointsAsInOrderLineList(); - return; - } - - QuadGenerateConnectivity(processedTessFactors); // can be done in parallel to QuadGeneratePoints() -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::QuadProcessTessFactors -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::QuadProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1, - float insideTessFactor_U, float insideTessFactor_V, PROCESSED_TESS_FACTORS_QUAD& processedTessFactors ) -{ - // Is the patch culled? - if( !(tessFactor_Ueq0 > 0) || // NaN will pass - !(tessFactor_Veq0 > 0) || - !(tessFactor_Ueq1 > 0) || - !(tessFactor_Veq1 > 0) ) - { - processedTessFactors.bPatchCulled = true; - return; - } - else - { - processedTessFactors.bPatchCulled = false; - } - - // Clamp edge TessFactors - float lowerBound = 0.0, upperBound = 0.0; - switch(m_originalPartitioning) - { - case D3D11_TESSELLATOR_PARTITIONING_INTEGER: - case D3D11_TESSELLATOR_PARTITIONING_POW2: // don�t care about pow2 distinction for validation, just treat as integer - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR; - break; - - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: - lowerBound = D3D11_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR; - break; - - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR; - break; - } - - tessFactor_Ueq0 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Ueq0 ) ); - tessFactor_Veq0 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Veq0 ) ); - tessFactor_Ueq1 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Ueq1 ) ); - tessFactor_Veq1 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Veq1 ) ); - - if( HWIntegerPartitioning()) // pow2 or integer, round to next int (hw doesn't care about pow2 distinction) - { - tessFactor_Ueq0 = ceil(tessFactor_Ueq0); - tessFactor_Veq0 = ceil(tessFactor_Veq0); - tessFactor_Ueq1 = ceil(tessFactor_Ueq1); - tessFactor_Veq1 = ceil(tessFactor_Veq1); - } - - // Clamp inside TessFactors - if(D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD == m_originalPartitioning) - { -#define EPSILON 0.0000152587890625f // 2^(-16), min positive fixed point fraction -#define MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON (D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR + EPSILON/2) - // If any TessFactor will end up > 1 after floatToFixed conversion later, - // then force the inside TessFactors to be > 1 so there is a picture frame. - if( (tessFactor_Ueq0 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (tessFactor_Veq0 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (tessFactor_Ueq1 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (tessFactor_Veq1 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (insideTessFactor_U > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (insideTessFactor_V > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) ) - { - // Force picture frame - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR + EPSILON; - } - } - - insideTessFactor_U = tess_fmin( upperBound, tess_fmax( lowerBound, insideTessFactor_U ) ); - insideTessFactor_V = tess_fmin( upperBound, tess_fmax( lowerBound, insideTessFactor_V ) ); - // Note the above clamps map NaN to lowerBound - - - if( HWIntegerPartitioning()) // pow2 or integer, round to next int (hw doesn't care about pow2 distinction) - { - insideTessFactor_U = ceil(insideTessFactor_U); - insideTessFactor_V = ceil(insideTessFactor_V); - } - - // Reset our vertex and index buffers. We have enough storage for the max tessFactor. - m_NumPoints = 0; - m_NumIndices = 0; - - // Process tessFactors - float outsideTessFactor[QUAD_EDGES] = {tessFactor_Ueq0, tessFactor_Veq0, tessFactor_Ueq1, tessFactor_Veq1}; - float insideTessFactor[QUAD_AXES] = {insideTessFactor_U,insideTessFactor_V}; - int edge, axis; - if( HWIntegerPartitioning() ) - { - for( edge = 0; edge < QUAD_EDGES; edge++ ) - { - int edgeEven = isEven(outsideTessFactor[edge]); - processedTessFactors.outsideTessFactorParity[edge] = edgeEven ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - for( axis = 0; axis < QUAD_AXES; axis++ ) - { - processedTessFactors.insideTessFactorParity[axis] = - (isEven(insideTessFactor[axis]) || (FLOAT_ONE == insideTessFactor[axis]) ) - ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - } - else - { - for( edge = 0; edge < QUAD_EDGES; edge++ ) - { - processedTessFactors.outsideTessFactorParity[edge] = m_originalParity; - } - processedTessFactors.insideTessFactorParity[U] = processedTessFactors.insideTessFactorParity[V] = m_originalParity; - } - - // Save fixed point TessFactors - for( edge = 0; edge < QUAD_EDGES; edge++ ) - { - processedTessFactors.outsideTessFactor[edge] = floatToFixed(outsideTessFactor[edge]); - } - for( axis = 0; axis < QUAD_AXES; axis++ ) - { - processedTessFactors.insideTessFactor[axis] = floatToFixed(insideTessFactor[axis]); - } - - if( HWIntegerPartitioning() || Odd() ) - { - // Special case if all TessFactors are 1 - if( (FXP_ONE == processedTessFactors.insideTessFactor[U]) && - (FXP_ONE == processedTessFactors.insideTessFactor[V]) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Ueq0]) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Veq0]) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Ueq1]) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Veq1]) ) - { - processedTessFactors.bJustDoMinimumTessFactor = true; - return; - } - } - processedTessFactors.bJustDoMinimumTessFactor = false; - - // Compute TessFactor-specific metadata - for(int edge = 0; edge < QUAD_EDGES; edge++ ) - { - SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]); - ComputeTessFactorContext(processedTessFactors.outsideTessFactor[edge], processedTessFactors.outsideTessFactorCtx[edge]); - } - - for(int axis = 0; axis < QUAD_AXES; axis++) - { - SetTessellationParity(processedTessFactors.insideTessFactorParity[axis]); - ComputeTessFactorContext(processedTessFactors.insideTessFactor[axis], processedTessFactors.insideTessFactorCtx[axis]); - } - - // Compute some initial data. - - // outside edge offsets and storage - for(int edge = 0; edge < QUAD_EDGES; edge++ ) - { - SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]); - processedTessFactors.numPointsForOutsideEdge[edge] = NumPointsForTessFactor(processedTessFactors.outsideTessFactor[edge]); - m_NumPoints += processedTessFactors.numPointsForOutsideEdge[edge]; - } - m_NumPoints -= 4; - - // inside edge offsets - for(int axis = 0; axis < QUAD_AXES; axis++) - { - SetTessellationParity(processedTessFactors.insideTessFactorParity[axis]); - processedTessFactors.numPointsForInsideTessFactor[axis] = NumPointsForTessFactor(processedTessFactors.insideTessFactor[axis]); - int pointCountMin = ( TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[axis] ) ? 4 : 3; - // max() allows degenerate transition regions when inside TessFactor == 1 - processedTessFactors.numPointsForInsideTessFactor[axis] = max(pointCountMin,processedTessFactors.numPointsForInsideTessFactor[axis]); - } - - processedTessFactors.insideEdgePointBaseOffset = m_NumPoints; - - // inside storage, including interior edges above - int numInteriorPoints = (processedTessFactors.numPointsForInsideTessFactor[U] - 2)*(processedTessFactors.numPointsForInsideTessFactor[V]-2); - m_NumPoints += numInteriorPoints; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::QuadGeneratePoints -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::QuadGeneratePoints( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors ) -{ - // Generate exterior ring edge points, clockwise from top-left - int pointOffset = 0; - int edge; - for(edge = 0; edge < QUAD_EDGES; edge++ ) - { - int parity = edge&0x1; - int startPoint = 0; - int endPoint = processedTessFactors.numPointsForOutsideEdge[edge] - 1; - for(int p = startPoint; p < endPoint; p++,pointOffset++) // don't include end, since next edge starts with it. - { - FXP fxpParam; - int q = ((edge==1)||(edge==2)) ? p : endPoint - p; // reverse order - SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]); - PlacePointIn1D(processedTessFactors.outsideTessFactorCtx[edge],q,fxpParam); - if( parity ) - { - DefinePoint(/*U*/fxpParam, - /*V*/(edge == 3) ? FXP_ONE : 0, - /*pointStorageOffset*/pointOffset); - } - else - { - DefinePoint(/*U*/(edge == 2) ? FXP_ONE : 0, - /*V*/fxpParam, - /*pointStorageOffset*/pointOffset); - } - } - } - - // Generate interior ring points, clockwise from (U==0,V==1) (bottom-left) spiralling toward center - static const int startRing = 1; - int minNumPointsForTessFactor = min(processedTessFactors.numPointsForInsideTessFactor[U],processedTessFactors.numPointsForInsideTessFactor[V]); - int numRings = (minNumPointsForTessFactor >> 1); // note for even tess we aren't counting center point here. - for(int ring = startRing; ring < numRings; ring++) - { - int startPoint = ring; - int endPoint[QUAD_AXES] = {processedTessFactors.numPointsForInsideTessFactor[U] - 1 - startPoint, - processedTessFactors.numPointsForInsideTessFactor[V] - 1 - startPoint}; - - for(edge = 0; edge < QUAD_EDGES; edge++ ) - { - int parity[QUAD_AXES] = {edge&0x1,((edge+1)&0x1)}; - int perpendicularAxisPoint = (edge < 2) ? startPoint : endPoint[parity[0]]; - FXP fxpPerpParam; - SetTessellationParity(processedTessFactors.insideTessFactorParity[parity[0]]); - PlacePointIn1D(processedTessFactors.insideTessFactorCtx[parity[0]],perpendicularAxisPoint,fxpPerpParam); - SetTessellationParity(processedTessFactors.insideTessFactorParity[parity[1]]); - for(int p = startPoint; p < endPoint[parity[1]]; p++, pointOffset++) // don't include end: next edge starts with it. - { - FXP fxpParam; - int q = ((edge == 1)||(edge==2)) ? p : endPoint[parity[1]] - (p - startPoint); - PlacePointIn1D(processedTessFactors.insideTessFactorCtx[parity[1]],q,fxpParam); - if( parity[1] ) - { - DefinePoint(/*U*/fxpPerpParam, - /*V*/fxpParam, - /*pointStorageOffset*/pointOffset); - } - else - { - DefinePoint(/*U*/fxpParam, - /*V*/fxpPerpParam, - /*pointStorageOffset*/pointOffset); - } - } - } - } - // For even tessellation, the inner "ring" is degenerate - a row of points - if( (processedTessFactors.numPointsForInsideTessFactor[U] > processedTessFactors.numPointsForInsideTessFactor[V]) && - (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ) - { - int startPoint = numRings; - int endPoint = processedTessFactors.numPointsForInsideTessFactor[U] - 1 - startPoint; - SetTessellationParity(processedTessFactors.insideTessFactorParity[U]); - for( int p = startPoint; p <= endPoint; p++, pointOffset++ ) - { - FXP fxpParam; - PlacePointIn1D(processedTessFactors.insideTessFactorCtx[U],p,fxpParam); - DefinePoint(/*U*/fxpParam, - /*V*/FXP_ONE_HALF, // middle - /*pointStorageOffset*/pointOffset); - } - } - else if( (processedTessFactors.numPointsForInsideTessFactor[V] >= processedTessFactors.numPointsForInsideTessFactor[U]) && - (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U]) ) - { - int startPoint = numRings; - int endPoint; - FXP fxpParam; - endPoint = processedTessFactors.numPointsForInsideTessFactor[V] - 1 - startPoint; - SetTessellationParity(processedTessFactors.insideTessFactorParity[V]); - for( int p = endPoint; p >= startPoint; p--, pointOffset++ ) - { - PlacePointIn1D(processedTessFactors.insideTessFactorCtx[V],p,fxpParam); - DefinePoint(/*U*/FXP_ONE_HALF, // middle - /*V*/fxpParam, - /*pointStorageOffset*/pointOffset); - } - } -} -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::QuadGenerateConnectivity -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors ) -{ - // Generate primitives for all the concentric rings, one side at a time for each ring - static const int startRing = 1; - int numPointRowsToCenter[QUAD_AXES] = {((processedTessFactors.numPointsForInsideTessFactor[U]+1) >> 1), - ((processedTessFactors.numPointsForInsideTessFactor[V]+1) >> 1)}; // +1 is so even tess includes the center point - int numRings = min(numPointRowsToCenter[U],numPointRowsToCenter[V]); - int degeneratePointRing[QUAD_AXES] = { // Even partitioning causes degenerate row of points, - // which results in exceptions to the point ordering conventions - // when travelling around the rings counterclockwise. - (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ? numPointRowsToCenter[V] - 1 : -1, - (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U]) ? numPointRowsToCenter[U] - 1 : -1 }; - - const TESS_FACTOR_CONTEXT* outsideTessFactorCtx[QUAD_EDGES] = {&processedTessFactors.outsideTessFactorCtx[Ueq0], - &processedTessFactors.outsideTessFactorCtx[Veq0], - &processedTessFactors.outsideTessFactorCtx[Ueq1], - &processedTessFactors.outsideTessFactorCtx[Veq1]}; - TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES] = {processedTessFactors.outsideTessFactorParity[Ueq0], - processedTessFactors.outsideTessFactorParity[Veq0], - processedTessFactors.outsideTessFactorParity[Ueq1], - processedTessFactors.outsideTessFactorParity[Veq1]}; - int numPointsForOutsideEdge[QUAD_EDGES] = {processedTessFactors.numPointsForOutsideEdge[Ueq0], - processedTessFactors.numPointsForOutsideEdge[Veq0], - processedTessFactors.numPointsForOutsideEdge[Ueq1], - processedTessFactors.numPointsForOutsideEdge[Veq1]}; - - int insideEdgePointBaseOffset = processedTessFactors.insideEdgePointBaseOffset; - int outsideEdgePointBaseOffset = 0; - int edge; - for(int ring = startRing; ring < numRings; ring++) - { - int numPointsForInsideEdge[QUAD_AXES] = {processedTessFactors.numPointsForInsideTessFactor[U] - 2*ring, - processedTessFactors.numPointsForInsideTessFactor[V] - 2*ring}; - - int edge0InsidePointBaseOffset = insideEdgePointBaseOffset; - int edge0OutsidePointBaseOffset = outsideEdgePointBaseOffset; - - for(edge = 0; edge < QUAD_EDGES; edge++ ) - { - int parity = (edge+1)&0x1; - - int numTriangles = numPointsForInsideEdge[parity] + numPointsForOutsideEdge[edge] - 2; - int insideBaseOffset; - int outsideBaseOffset; - if( edge == 3 ) // We need to patch the indexing so Stitch() can think it sees - // 2 sequentially increasing rows of points, even though we have wrapped around - // to the end of the inner and outer ring's points, so the last point is really - // the first point for the ring. - // We make it so that when Stitch() calls AddIndex(), that function - // will do any necessary index adjustment. - { - if( ring == degeneratePointRing[parity] ) - { - m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset + 1; - m_IndexPatchContext2.cornerCaseBadValue = outsideEdgePointBaseOffset + numPointsForOutsideEdge[edge] - 1; - m_IndexPatchContext2.cornerCaseReplacementValue = edge0OutsidePointBaseOffset; - m_IndexPatchContext2.indexInversionEndPoint = (m_IndexPatchContext2.baseIndexToInvert << 1) - 1; - insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert; - outsideBaseOffset = outsideEdgePointBaseOffset; - SetUsingPatchedIndices2(true); - } - else - { - m_IndexPatchContext.insidePointIndexDeltaToRealValue = insideEdgePointBaseOffset; - m_IndexPatchContext.insidePointIndexBadValue = numPointsForInsideEdge[parity] - 1; - m_IndexPatchContext.insidePointIndexReplacementValue = edge0InsidePointBaseOffset; - m_IndexPatchContext.outsidePointIndexPatchBase = m_IndexPatchContext.insidePointIndexBadValue+1; // past inside patched index range - m_IndexPatchContext.outsidePointIndexDeltaToRealValue = outsideEdgePointBaseOffset - - m_IndexPatchContext.outsidePointIndexPatchBase; - m_IndexPatchContext.outsidePointIndexBadValue = m_IndexPatchContext.outsidePointIndexPatchBase - + numPointsForOutsideEdge[edge] - 1; - m_IndexPatchContext.outsidePointIndexReplacementValue = edge0OutsidePointBaseOffset; - - insideBaseOffset = 0; - outsideBaseOffset = m_IndexPatchContext.outsidePointIndexPatchBase; - SetUsingPatchedIndices(true); - } - } - else if( (edge == 2) && (ring == degeneratePointRing[parity]) ) - { - m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset; - m_IndexPatchContext2.cornerCaseBadValue = -1; // unused - m_IndexPatchContext2.cornerCaseReplacementValue = -1; // unused - m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert << 1; - insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert; - outsideBaseOffset = outsideEdgePointBaseOffset; - SetUsingPatchedIndices2(true); - } - else - { - insideBaseOffset = insideEdgePointBaseOffset; - outsideBaseOffset = outsideEdgePointBaseOffset; - } - if( ring == startRing ) - { - StitchTransition(/*baseIndexOffset: */m_NumIndices, - insideBaseOffset,processedTessFactors.insideTessFactorCtx[parity].numHalfTessFactorPoints,processedTessFactors.insideTessFactorParity[parity], - outsideBaseOffset,outsideTessFactorCtx[edge]->numHalfTessFactorPoints,outsideTessFactorParity[edge]); - } - else - { - StitchRegular(/*bTrapezoid*/true, DIAGONALS_MIRRORED, - /*baseIndexOffset: */m_NumIndices, - numPointsForInsideEdge[parity], - insideBaseOffset,outsideBaseOffset); - } - SetUsingPatchedIndices(false); - SetUsingPatchedIndices2(false); - m_NumIndices += numTriangles*3; - outsideEdgePointBaseOffset += numPointsForOutsideEdge[edge] - 1; - if( (edge == 2) && (ring == degeneratePointRing[parity]) ) - { - insideEdgePointBaseOffset -= numPointsForInsideEdge[parity] - 1; - } - else - { - insideEdgePointBaseOffset += numPointsForInsideEdge[parity] - 1; - } - numPointsForOutsideEdge[edge] = numPointsForInsideEdge[parity]; - } - if( startRing == ring ) - { - for(edge = 0; edge < QUAD_EDGES; edge++ ) - { - outsideTessFactorCtx[edge] = &processedTessFactors.insideTessFactorCtx[edge&1]; - outsideTessFactorParity[edge] = processedTessFactors.insideTessFactorParity[edge&1]; - } - } - } - - // Triangulate center - a row of quads if odd - // This triangulation may be producing diagonals that are asymmetric about - // the center of the patch in this region. - if( (processedTessFactors.numPointsForInsideTessFactor[U] > processedTessFactors.numPointsForInsideTessFactor[V]) && - (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[V] ) ) - { - SetUsingPatchedIndices2(true); - int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[U]>>1) - (processedTessFactors.numPointsForInsideTessFactor[V]>>1))<<1)+ - ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U] ) ? 2 : 1); - m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 2; - m_IndexPatchContext2.cornerCaseBadValue = m_IndexPatchContext2.baseIndexToInvert; - m_IndexPatchContext2.cornerCaseReplacementValue = outsideEdgePointBaseOffset; - m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + - m_IndexPatchContext2.baseIndexToInvert + stripNumQuads; - StitchRegular(/*bTrapezoid*/false,DIAGONALS_INSIDE_TO_OUTSIDE, - /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1, - /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert, - outsideEdgePointBaseOffset+1); - SetUsingPatchedIndices2(false); - m_NumIndices += stripNumQuads*6; - } - else if((processedTessFactors.numPointsForInsideTessFactor[V] >= processedTessFactors.numPointsForInsideTessFactor[U]) && - (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[U]) ) - { - SetUsingPatchedIndices2(true); - int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[V]>>1) - (processedTessFactors.numPointsForInsideTessFactor[U]>>1))<<1)+ - ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V] ) ? 2 : 1); - m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 1; - m_IndexPatchContext2.cornerCaseBadValue = -1; // unused - m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + - m_IndexPatchContext2.baseIndexToInvert + stripNumQuads; - DIAGONALS diag = (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ? - DIAGONALS_INSIDE_TO_OUTSIDE : DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE; - StitchRegular(/*bTrapezoid*/false,diag, - /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1, - /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert, - outsideEdgePointBaseOffset); - SetUsingPatchedIndices2(false); - m_NumIndices += stripNumQuads*6; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::TessellateTriDomain -// User calls this -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::TessellateTriDomain( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Weq0, - float insideTessFactor ) -{ - PROCESSED_TESS_FACTORS_TRI processedTessFactors; - TriProcessTessFactors(tessFactor_Ueq0,tessFactor_Veq0,tessFactor_Weq0,insideTessFactor,processedTessFactors); - - if( processedTessFactors.bPatchCulled ) - { - m_NumPoints = 0; - m_NumIndices = 0; - return; - } - else if( processedTessFactors.bJustDoMinimumTessFactor ) - { - DefinePoint(/*U*/0,/*V*/FXP_ONE,/*pointStorageOffset*/0); //V=1 (beginning of Ueq0 edge VW) - DefinePoint(/*U*/0,/*V*/0,/*pointStorageOffset*/1); //W=1 (beginning of Veq0 edge WU) - DefinePoint(/*U*/FXP_ONE,/*V*/0,/*pointStorageOffset*/2); //U=1 (beginning of Weq0 edge UV) - m_NumPoints = 3; - - switch(m_outputPrimitive) - { - case D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW: - case D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW: - // function orients them CCW if needed - DefineClockwiseTriangle(0,1,2,/*indexStorageBaseOffset*/m_NumIndices); - m_NumIndices = 3; - break; - case D3D11_TESSELLATOR_OUTPUT_POINT: - DumpAllPoints(); - break; - case D3D11_TESSELLATOR_OUTPUT_LINE: - DumpAllPointsAsInOrderLineList(); - break; - } - return; - } - - TriGeneratePoints(processedTessFactors); - - if( m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_POINT ) - { - DumpAllPoints(); - return; - } - if( m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_LINE ) - { - DumpAllPointsAsInOrderLineList(); - return; - } - - TriGenerateConnectivity(processedTessFactors); // can be done in parallel to TriGeneratePoints() -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::TriProcessTessFactors -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::TriProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Weq0, - float insideTessFactor, PROCESSED_TESS_FACTORS_TRI& processedTessFactors ) -{ - // Is the patch culled? - if( !(tessFactor_Ueq0 > 0) || // NaN will pass - !(tessFactor_Veq0 > 0) || - !(tessFactor_Weq0 > 0) ) - { - processedTessFactors.bPatchCulled = true; - return; - } - else - { - processedTessFactors.bPatchCulled = false; - } - - // Clamp edge TessFactors - float lowerBound = 0.0, upperBound = 0.0; - switch(m_originalPartitioning) - { - case D3D11_TESSELLATOR_PARTITIONING_INTEGER: - case D3D11_TESSELLATOR_PARTITIONING_POW2: // don�t care about pow2 distinction for validation, just treat as integer - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR; - break; - - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: - lowerBound = D3D11_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR; - break; - - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR; - break; - } - - tessFactor_Ueq0 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Ueq0 ) ); - tessFactor_Veq0 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Veq0 ) ); - tessFactor_Weq0 = tess_fmin( upperBound, tess_fmax( lowerBound, tessFactor_Weq0 ) ); - - if( HWIntegerPartitioning()) // pow2 or integer, round to next int (hw doesn't care about pow2 distinction) - { - tessFactor_Ueq0 = ceil(tessFactor_Ueq0); - tessFactor_Veq0 = ceil(tessFactor_Veq0); - tessFactor_Weq0 = ceil(tessFactor_Weq0); - } - - // Clamp inside TessFactors - if(D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD == m_originalPartitioning) - { - if( (tessFactor_Ueq0 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (tessFactor_Veq0 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON) || - (tessFactor_Weq0 > MIN_ODD_TESSFACTOR_PLUS_HALF_EPSILON)) - // Don't need the same check for insideTessFactor for tri patches, - // since there is only one insideTessFactor, as opposed to quad - // patches which have 2 insideTessFactors. - { - // Force picture frame - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR + EPSILON; - } - } - - insideTessFactor = tess_fmin( upperBound, tess_fmax( lowerBound, insideTessFactor ) ); - // Note the above clamps map NaN to lowerBound - - if( HWIntegerPartitioning()) // pow2 or integer, round to next int (hw doesn't care about pow2 distinction) - { - insideTessFactor = ceil(insideTessFactor); - } - - // Reset our vertex and index buffers. We have enough storage for the max tessFactor. - m_NumPoints = 0; - m_NumIndices = 0; - - // Process tessFactors - float outsideTessFactor[TRI_EDGES] = {tessFactor_Ueq0, tessFactor_Veq0, tessFactor_Weq0}; - int edge; - if( HWIntegerPartitioning() ) - { - for( edge = 0; edge < TRI_EDGES; edge++ ) - { - int edgeEven = isEven(outsideTessFactor[edge]); - processedTessFactors.outsideTessFactorParity[edge] = edgeEven ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - processedTessFactors.insideTessFactorParity = (isEven(insideTessFactor) || (FLOAT_ONE == insideTessFactor)) - ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - else - { - for( edge = 0; edge < TRI_EDGES; edge++ ) - { - processedTessFactors.outsideTessFactorParity[edge] = m_originalParity; - } - processedTessFactors.insideTessFactorParity = m_originalParity; - } - - // Save fixed point TessFactors - for( edge = 0; edge < TRI_EDGES; edge++ ) - { - processedTessFactors.outsideTessFactor[edge] = floatToFixed(outsideTessFactor[edge]); - } - processedTessFactors.insideTessFactor = floatToFixed(insideTessFactor); - - if( HWIntegerPartitioning() || Odd() ) - { - // Special case if all TessFactors are 1 - if( (FXP_ONE == processedTessFactors.insideTessFactor) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Ueq0]) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Veq0]) && - (FXP_ONE == processedTessFactors.outsideTessFactor[Weq0]) ) - { - processedTessFactors.bJustDoMinimumTessFactor = true; - return; - } - } - processedTessFactors.bJustDoMinimumTessFactor = false; - - // Compute per-TessFactor metadata - for(edge = 0; edge < TRI_EDGES; edge++ ) - { - SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]); - ComputeTessFactorContext(processedTessFactors.outsideTessFactor[edge], processedTessFactors.outsideTessFactorCtx[edge]); - } - SetTessellationParity(processedTessFactors.insideTessFactorParity); - ComputeTessFactorContext(processedTessFactors.insideTessFactor, processedTessFactors.insideTessFactorCtx); - - // Compute some initial data. - - // outside edge offsets and storage - for(edge = 0; edge < TRI_EDGES; edge++ ) - { - SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]); - processedTessFactors.numPointsForOutsideEdge[edge] = NumPointsForTessFactor(processedTessFactors.outsideTessFactor[edge]); - m_NumPoints += processedTessFactors.numPointsForOutsideEdge[edge]; - } - m_NumPoints -= 3; - - // inside edge offsets - SetTessellationParity(processedTessFactors.insideTessFactorParity); - processedTessFactors.numPointsForInsideTessFactor = NumPointsForTessFactor(processedTessFactors.insideTessFactor); - { - int pointCountMin = Odd() ? 4 : 3; - // max() allows degenerate transition regions when inside TessFactor == 1 - processedTessFactors.numPointsForInsideTessFactor = max(pointCountMin,processedTessFactors.numPointsForInsideTessFactor); - } - - processedTessFactors.insideEdgePointBaseOffset = m_NumPoints; - - // inside storage, including interior edges above - { - int numInteriorRings = (processedTessFactors.numPointsForInsideTessFactor >> 1) - 1; - int numInteriorPoints; - if( Odd() ) - { - numInteriorPoints = TRI_EDGES*(numInteriorRings*(numInteriorRings+1) - numInteriorRings); - } - else - { - numInteriorPoints = TRI_EDGES*(numInteriorRings*(numInteriorRings+1)) + 1; - } - m_NumPoints += numInteriorPoints; - } - -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::TriGeneratePoints -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors ) -{ - // Generate exterior ring edge points, clockwise starting from point V (VW, the U==0 edge) - int pointOffset = 0; - int edge; - for(edge = 0; edge < TRI_EDGES; edge++ ) - { - int parity = edge&0x1; - int startPoint = 0; - int endPoint = processedTessFactors.numPointsForOutsideEdge[edge] - 1; - for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end, since next edge starts with it. - { - FXP fxpParam; - int q = (parity) ? p : endPoint - p; // whether to reverse point order given we are defining V or U (W implicit): - // edge0, VW, has V decreasing, so reverse 1D points below - // edge1, WU, has U increasing, so don't reverse 1D points below - // edge2, UV, has U decreasing, so reverse 1D points below - SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]); - PlacePointIn1D(processedTessFactors.outsideTessFactorCtx[edge],q,fxpParam); - if( edge == 0 ) - { - DefinePoint(/*U*/0, - /*V*/fxpParam, - /*pointStorageOffset*/pointOffset); - } - else - { - DefinePoint(/*U*/fxpParam, - /*V*/(edge == 2) ? FXP_ONE - fxpParam : 0, - /*pointStorageOffset*/pointOffset); - } - } - } - - // Generate interior ring points, clockwise spiralling in - SetTessellationParity(processedTessFactors.insideTessFactorParity); - static const int startRing = 1; - int numRings = (processedTessFactors.numPointsForInsideTessFactor >> 1); - for(int ring = startRing; ring < numRings; ring++) - { - int startPoint = ring; - int endPoint = processedTessFactors.numPointsForInsideTessFactor - 1 - startPoint; - - for(edge = 0; edge < TRI_EDGES; edge++ ) - { - int parity = edge&0x1; - int perpendicularAxisPoint = startPoint; - FXP fxpPerpParam; - PlacePointIn1D(processedTessFactors.insideTessFactorCtx,perpendicularAxisPoint,fxpPerpParam); - fxpPerpParam *= FXP_TWO_THIRDS; // Map location to the right size in barycentric space. - // I (amarp) can draw a picture to explain. - // We know this fixed point math won't over/underflow - fxpPerpParam = (fxpPerpParam+FXP_ONE_HALF/*round*/)>>FXP_FRACTION_BITS; // get back to n.16 - for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end: next edge starts with it. - { - FXP fxpParam; - int q = (parity) ? p : endPoint - (p - startPoint); // whether to reverse point given we are defining V or U (W implicit): - // edge0, VW, has V decreasing, so reverse 1D points below - // edge1, WU, has U increasing, so don't reverse 1D points below - // edge2, UV, has U decreasing, so reverse 1D points below - PlacePointIn1D(processedTessFactors.insideTessFactorCtx,q,fxpParam); - // edge0 VW, has perpendicular parameter U constant - // edge1 WU, has perpendicular parameter V constant - // edge2 UV, has perpendicular parameter W constant - const unsigned int deriv = 2; // reciprocal is the rate of change of edge-parallel parameters as they are pushed into the triangle - switch(edge) - { - case 0: - DefinePoint(/*U*/fxpPerpParam, - /*V*/fxpParam - (fxpPerpParam+1/*round*/)/deriv, // we know this fixed point math won't over/underflow - /*pointStorageOffset*/pointOffset); - break; - case 1: - DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow - /*V*/fxpPerpParam, - /*pointStorageOffset*/pointOffset); - break; - case 2: - DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow - /*V*/FXP_ONE - (fxpParam - (fxpPerpParam+1/*round*/)/deriv) - fxpPerpParam,// we know this fixed point math won't over/underflow - /*pointStorageOffset*/pointOffset); - break; - } - } - } - } - if( !Odd() ) - { - // Last point is the point at the center. - DefinePoint(/*U*/FXP_ONE_THIRD, - /*V*/FXP_ONE_THIRD, - /*pointStorageOffset*/pointOffset); - } -} -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::TriGenerateConnectivity -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::TriGenerateConnectivity( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors ) -{ - // Generate primitives for all the concentric rings, one side at a time for each ring - static const int startRing = 1; - int numRings = ((processedTessFactors.numPointsForInsideTessFactor+1) >> 1); // +1 is so even tess includes the center point, which we want to now - const TESS_FACTOR_CONTEXT* outsideTessFactorCtx[TRI_EDGES] = {&processedTessFactors.outsideTessFactorCtx[Ueq0], - &processedTessFactors.outsideTessFactorCtx[Veq0], - &processedTessFactors.outsideTessFactorCtx[Weq0]}; - TESSELLATOR_PARITY outsideTessFactorParity[TRI_EDGES] = {processedTessFactors.outsideTessFactorParity[Ueq0], - processedTessFactors.outsideTessFactorParity[Veq0], - processedTessFactors.outsideTessFactorParity[Weq0]}; - int numPointsForOutsideEdge[TRI_EDGES] = {processedTessFactors.numPointsForOutsideEdge[Ueq0], - processedTessFactors.numPointsForOutsideEdge[Veq0], - processedTessFactors.numPointsForOutsideEdge[Weq0]}; - - int insideEdgePointBaseOffset = processedTessFactors.insideEdgePointBaseOffset; - int outsideEdgePointBaseOffset = 0; - int edge; - for(int ring = startRing; ring < numRings; ring++) - { - int numPointsForInsideEdge = processedTessFactors.numPointsForInsideTessFactor - 2*ring; - int edge0InsidePointBaseOffset = insideEdgePointBaseOffset; - int edge0OutsidePointBaseOffset = outsideEdgePointBaseOffset; - for(edge = 0; edge < TRI_EDGES; edge++ ) - { - int numTriangles = numPointsForInsideEdge + numPointsForOutsideEdge[edge] - 2; - - int insideBaseOffset; - int outsideBaseOffset; - if( edge == 2 ) - { - m_IndexPatchContext.insidePointIndexDeltaToRealValue = insideEdgePointBaseOffset; - m_IndexPatchContext.insidePointIndexBadValue = numPointsForInsideEdge - 1; - m_IndexPatchContext.insidePointIndexReplacementValue = edge0InsidePointBaseOffset; - m_IndexPatchContext.outsidePointIndexPatchBase = m_IndexPatchContext.insidePointIndexBadValue+1; // past inside patched index range - m_IndexPatchContext.outsidePointIndexDeltaToRealValue = outsideEdgePointBaseOffset - - m_IndexPatchContext.outsidePointIndexPatchBase; - m_IndexPatchContext.outsidePointIndexBadValue = m_IndexPatchContext.outsidePointIndexPatchBase - + numPointsForOutsideEdge[edge] - 1; - m_IndexPatchContext.outsidePointIndexReplacementValue = edge0OutsidePointBaseOffset; - SetUsingPatchedIndices(true); - insideBaseOffset = 0; - outsideBaseOffset = m_IndexPatchContext.outsidePointIndexPatchBase; - } - else - { - insideBaseOffset = insideEdgePointBaseOffset; - outsideBaseOffset = outsideEdgePointBaseOffset; - } - if( ring == startRing ) - { - StitchTransition(/*baseIndexOffset: */m_NumIndices, - insideBaseOffset,processedTessFactors.insideTessFactorCtx.numHalfTessFactorPoints,processedTessFactors.insideTessFactorParity, - outsideBaseOffset,outsideTessFactorCtx[edge]->numHalfTessFactorPoints,outsideTessFactorParity[edge]); - } - else - { - StitchRegular(/*bTrapezoid*/true, DIAGONALS_MIRRORED, - /*baseIndexOffset: */m_NumIndices, - numPointsForInsideEdge, - insideBaseOffset,outsideBaseOffset); - } - if( 2 == edge ) - { - SetUsingPatchedIndices(false); - } - m_NumIndices += numTriangles*3; - outsideEdgePointBaseOffset += numPointsForOutsideEdge[edge] - 1; - insideEdgePointBaseOffset += numPointsForInsideEdge - 1; - numPointsForOutsideEdge[edge] = numPointsForInsideEdge; - } - if( startRing == ring ) - { - for(edge = 0; edge < TRI_EDGES; edge++ ) - { - outsideTessFactorCtx[edge] = &processedTessFactors.insideTessFactorCtx; - outsideTessFactorParity[edge] = processedTessFactors.insideTessFactorParity; - } - } - } - if( Odd() ) - { - // Triangulate center (a single triangle) - DefineClockwiseTriangle(outsideEdgePointBaseOffset, outsideEdgePointBaseOffset+1, outsideEdgePointBaseOffset+2, - m_NumIndices); - m_NumIndices += 3; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::TessellateIsoLineDomain -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::TessellateIsoLineDomain( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail ) -{ - PROCESSED_TESS_FACTORS_ISOLINE processedTessFactors; - IsoLineProcessTessFactors(TessFactor_V_LineDensity,TessFactor_U_LineDetail,processedTessFactors); - if( processedTessFactors.bPatchCulled ) - { - m_NumPoints = 0; - m_NumIndices = 0; - return; - } - IsoLineGeneratePoints(processedTessFactors); - IsoLineGenerateConnectivity(processedTessFactors); // can be done in parallel to IsoLineGeneratePoints -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::IsoLineProcessTessFactors -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::IsoLineProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail, - PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors ) -{ - // Is the patch culled? - if( !(TessFactor_V_LineDensity > 0) || // NaN will pass - !(TessFactor_U_LineDetail > 0) ) - { - processedTessFactors.bPatchCulled = true; - return; - } - else - { - processedTessFactors.bPatchCulled = false; - } - - // Clamp edge TessFactors - float lowerBound = 0.0, upperBound = 0.0; - switch(m_originalPartitioning) - { - case D3D11_TESSELLATOR_PARTITIONING_INTEGER: - case D3D11_TESSELLATOR_PARTITIONING_POW2: // don�t care about pow2 distinction for validation, just treat as integer - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR; - break; - - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: - lowerBound = D3D11_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR; - break; - - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: - lowerBound = D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR; - upperBound = D3D11_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR; - break; - } - - TessFactor_V_LineDensity = tess_fmin( D3D11_TESSELLATOR_MAX_ISOLINE_DENSITY_TESSELLATION_FACTOR, - tess_fmax( D3D11_TESSELLATOR_MIN_ISOLINE_DENSITY_TESSELLATION_FACTOR, TessFactor_V_LineDensity ) ); - TessFactor_U_LineDetail = tess_fmin( upperBound, tess_fmax( lowerBound, TessFactor_U_LineDetail ) ); - - // Reset our vertex and index buffers. We have enough storage for the max tessFactor. - m_NumPoints = 0; - m_NumIndices = 0; - - // Process tessFactors - if( HWIntegerPartitioning() ) - { - TessFactor_U_LineDetail = ceil(TessFactor_U_LineDetail); - processedTessFactors.lineDetailParity = isEven(TessFactor_U_LineDetail) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - else - { - processedTessFactors.lineDetailParity = m_originalParity; - } - - FXP fxpTessFactor_U_LineDetail = floatToFixed(TessFactor_U_LineDetail); - - SetTessellationParity(processedTessFactors.lineDetailParity); - - ComputeTessFactorContext(fxpTessFactor_U_LineDetail, processedTessFactors.lineDetailTessFactorCtx); - processedTessFactors.numPointsPerLine = NumPointsForTessFactor(fxpTessFactor_U_LineDetail); - - OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING_INTEGER); - - TessFactor_V_LineDensity = ceil(TessFactor_V_LineDensity); - processedTessFactors.lineDensityParity = isEven(TessFactor_V_LineDensity) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - SetTessellationParity(processedTessFactors.lineDensityParity); - FXP fxpTessFactor_V_LineDensity = floatToFixed(TessFactor_V_LineDensity); - ComputeTessFactorContext(fxpTessFactor_V_LineDensity, processedTessFactors.lineDensityTessFactorCtx); - - processedTessFactors.numLines = NumPointsForTessFactor(fxpTessFactor_V_LineDensity) - 1; // don't draw last line at V == 1. - - RestorePartitioning(); - - // Compute some initial data. - - // outside edge offsets - m_NumPoints = processedTessFactors.numPointsPerLine * processedTessFactors.numLines; - if( m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_POINT ) - { - m_NumIndices = m_NumPoints; - } - else // line - { - m_NumIndices = processedTessFactors.numLines*(processedTessFactors.numPointsPerLine-1)*2; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::IsoLineGeneratePoints -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::IsoLineGeneratePoints( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors ) -{ - int line, pointOffset; - for(line = 0, pointOffset = 0; line < processedTessFactors.numLines; line++) - { - for(int point = 0; point < processedTessFactors.numPointsPerLine; point++) - { - FXP fxpU,fxpV; - SetTessellationParity(processedTessFactors.lineDensityParity); - PlacePointIn1D(processedTessFactors.lineDensityTessFactorCtx,line,fxpV); - - SetTessellationParity(processedTessFactors.lineDetailParity); - PlacePointIn1D(processedTessFactors.lineDetailTessFactorCtx,point,fxpU); - - DefinePoint(fxpU,fxpV,pointOffset++); - } - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::IsoLineGenerateConnectivity -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::IsoLineGenerateConnectivity( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors ) -{ - int line, pointOffset, indexOffset; - if( m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_POINT ) - { - for(line = 0, pointOffset = 0, indexOffset = 0; line < processedTessFactors.numLines; line++) - { - for(int point = 0; point < processedTessFactors.numPointsPerLine; point++) - { - DefineIndex(pointOffset++,indexOffset++); - } - } - } - else // line - { - for(line = 0, pointOffset = 0, indexOffset = 0; line < processedTessFactors.numLines; line++) - { - for(int point = 0; point < processedTessFactors.numPointsPerLine; point++) - { - if( point > 0 ) - { - DefineIndex(pointOffset-1,indexOffset++); - DefineIndex(pointOffset,indexOffset++); - } - pointOffset++; - } - } - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::GetPointCount -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -int CHWTessellator::GetPointCount() -{ - return m_NumPoints; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::GetIndexCount() -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -int CHWTessellator::GetIndexCount() -{ - return m_NumIndices; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::GetPoints() -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -DOMAIN_POINT* CHWTessellator::GetPoints() -{ - return m_Point; -} -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::GetIndices() -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -int* CHWTessellator::GetIndices() -{ - return m_Index; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::DefinePoint() -//--------------------------------------------------------------------------------------------------------------------------------- -int CHWTessellator::DefinePoint(FXP fxpU, FXP fxpV, int pointStorageOffset) -{ -// WCHAR foo[80]; -// StringCchPrintf(foo,80,L"off:%d, uv=(%f,%f)\n",pointStorageOffset,fixedToFloat(fxpU),fixedToFloat(fxpV)); -// OutputDebugString(foo); - m_Point[pointStorageOffset].u = fixedToFloat(fxpU); - m_Point[pointStorageOffset].v = fixedToFloat(fxpV); - return pointStorageOffset; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::DefineIndex() -//-------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::DefineIndex(int index, int indexStorageOffset) -{ - index = PatchIndexValue(index); -// WCHAR foo[80]; -// StringCchPrintf(foo,80,L"off:%d, idx=%d, uv=(%f,%f)\n",indexStorageOffset,index,m_Point[index].u,m_Point[index].v); -// OutputDebugString(foo); - m_Index[indexStorageOffset] = index; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::DefineClockwiseTriangle() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::DefineClockwiseTriangle(int index0, int index1, int index2, int indexStorageBaseOffset) -{ - // inputs a clockwise triangle, stores a CW or CCW triangle depending on the state - DefineIndex(index0,indexStorageBaseOffset); - bool bWantClockwise = (m_outputPrimitive == D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW) ? true : false; - if( bWantClockwise ) - { - DefineIndex(index1,indexStorageBaseOffset+1); - DefineIndex(index2,indexStorageBaseOffset+2); - } - else - { - DefineIndex(index2,indexStorageBaseOffset+1); - DefineIndex(index1,indexStorageBaseOffset+2); - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::DumpAllPoints() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::DumpAllPoints() -{ - for( int p = 0; p < m_NumPoints; p++ ) - { - DefineIndex(p,m_NumIndices++); - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::DumpAllPointsAsInOrderLineList() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::DumpAllPointsAsInOrderLineList() -{ - for( int p = 1; p < m_NumPoints; p++ ) - { - DefineIndex(p-1,m_NumIndices++); - DefineIndex(p,m_NumIndices++); - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// RemoveMSB -//--------------------------------------------------------------------------------------------------------------------------------- -int RemoveMSB(int val) -{ - int check; - if( val <= 0x0000ffff ) { check = ( val <= 0x000000ff ) ? 0x00000080 : 0x00008000; } - else { check = ( val <= 0x00ffffff ) ? 0x00800000 : 0x80000000; } - for( int i = 0; i < 8; i++, check >>= 1 ) { if( val & check ) return (val & ~check); } - return 0; -} -//--------------------------------------------------------------------------------------------------------------------------------- -// GetMSB -//--------------------------------------------------------------------------------------------------------------------------------- -int GetMSB(int val) -{ - int check; - if( val <= 0x0000ffff ) { check = ( val <= 0x000000ff ) ? 0x00000080 : 0x00008000; } - else { check = ( val <= 0x00ffffff ) ? 0x00800000 : 0x80000000; } - for( int i = 0; i < 8; i++, check >>= 1 ) { if( val & check ) return check; } - return 0; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::CleanseParameter() -//--------------------------------------------------------------------------------------------------------------------------------- -/* NOTHING TO DO FOR FIXED POINT ARITHMETIC! -void CHWTessellator::CleanseParameter(float& parameter) -{ - // Clean up [0..1] parameter to guarantee that (1 - (1 - parameter)) == parameter. - parameter = 1.0f - parameter; - parameter = 1.0f - parameter; - -} -*/ -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::NumPointsForTessFactor() -//--------------------------------------------------------------------------------------------------------------------------------- -int CHWTessellator::NumPointsForTessFactor( FXP fxpTessFactor ) -{ - int numPoints; - if( Odd() ) - { - numPoints = (fxpCeil(FXP_ONE_HALF + (fxpTessFactor+1/*round*/)/2)*2)>>FXP_FRACTION_BITS; - } - else - { - numPoints = ((fxpCeil((fxpTessFactor+1/*round*/)/2)*2)>>FXP_FRACTION_BITS)+1; - } - return numPoints; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::ComputeTessFactorContext() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::ComputeTessFactorContext( FXP fxpTessFactor, TESS_FACTOR_CONTEXT& TessFactorCtx ) -{ - FXP fxpHalfTessFactor = (fxpTessFactor+1/*round*/)/2; - if( Odd() || (fxpHalfTessFactor == FXP_ONE_HALF)) // fxpHalfTessFactor == 1/2 if TessFactor is 1, but we're pretending we are even. - { - fxpHalfTessFactor += FXP_ONE_HALF; - } - FXP fxpFloorHalfTessFactor = fxpFloor(fxpHalfTessFactor); - FXP fxpCeilHalfTessFactor = fxpCeil(fxpHalfTessFactor); - TessFactorCtx.fxpHalfTessFactorFraction = fxpHalfTessFactor - fxpFloorHalfTessFactor; - //CleanseParameter(TessFactorCtx.fxpHalfTessFactorFraction); - TessFactorCtx.numHalfTessFactorPoints = (fxpCeilHalfTessFactor>>FXP_FRACTION_BITS); // for EVEN, we don't include the point always fixed at the midpoint of the TessFactor - if( fxpCeilHalfTessFactor == fxpFloorHalfTessFactor ) - { - TessFactorCtx.splitPointOnFloorHalfTessFactor = /*pick value to cause this to be ignored*/ TessFactorCtx.numHalfTessFactorPoints+1; - } - else if( Odd() ) - { - if( fxpFloorHalfTessFactor == FXP_ONE ) - { - TessFactorCtx.splitPointOnFloorHalfTessFactor = 0; - } - else - { -#ifdef ALLOW_XBOX_360_COMPARISON - if( m_bXBox360Mode ) - TessFactorCtx.splitPointOnFloorHalfTessFactor = TessFactorCtx.numHalfTessFactorPoints-2; - else -#endif - TessFactorCtx.splitPointOnFloorHalfTessFactor = (RemoveMSB((fxpFloorHalfTessFactor>>FXP_FRACTION_BITS)-1)<<1) + 1; - } - } - else - { -#ifdef ALLOW_XBOX_360_COMPARISON - if( m_bXBox360Mode ) - TessFactorCtx.splitPointOnFloorHalfTessFactor = TessFactorCtx.numHalfTessFactorPoints-1; - else -#endif - TessFactorCtx.splitPointOnFloorHalfTessFactor = (RemoveMSB(fxpFloorHalfTessFactor>>FXP_FRACTION_BITS)<<1) + 1; - } - int numFloorSegments = (fxpFloorHalfTessFactor * 2)>>FXP_FRACTION_BITS; - int numCeilSegments = (fxpCeilHalfTessFactor * 2)>>FXP_FRACTION_BITS; - if( Odd() ) - { - numFloorSegments -= 1; - numCeilSegments -= 1; - } - TessFactorCtx.fxpInvNumSegmentsOnFloorTessFactor = s_fixedReciprocal[numFloorSegments]; - TessFactorCtx.fxpInvNumSegmentsOnCeilTessFactor = s_fixedReciprocal[numCeilSegments]; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::PlacePointIn1D() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::PlacePointIn1D( const TESS_FACTOR_CONTEXT& TessFactorCtx, int point, FXP& fxpLocation ) -{ - bool bFlip; - if( point >= TessFactorCtx.numHalfTessFactorPoints ) - { - point = (TessFactorCtx.numHalfTessFactorPoints << 1) - point; - if( Odd() ) - { - point -= 1; - } - bFlip = true; - } - else - { - bFlip = false; - } - if( point == TessFactorCtx.numHalfTessFactorPoints ) - { - fxpLocation = FXP_ONE_HALF; // special casing middle since 16 bit fixed math below can't reproduce 0.5 exactly - return; - } - unsigned int indexOnCeilHalfTessFactor = point; - unsigned int indexOnFloorHalfTessFactor = indexOnCeilHalfTessFactor; - if( point > TessFactorCtx.splitPointOnFloorHalfTessFactor ) - { - indexOnFloorHalfTessFactor -= 1; - } - // For the fixed point multiplies below, we know the results are <= 16 bits because - // the locations on the halfTessFactor are <= half the number of segments for the total TessFactor. - // So a number divided by a number that is at least twice as big will give - // a result no bigger than 0.5 (which in fixed point is 16 bits in our case) - FXP fxpLocationOnFloorHalfTessFactor = indexOnFloorHalfTessFactor * TessFactorCtx.fxpInvNumSegmentsOnFloorTessFactor; - FXP fxpLocationOnCeilHalfTessFactor = indexOnCeilHalfTessFactor * TessFactorCtx.fxpInvNumSegmentsOnCeilTessFactor; - - // Since we know the numbers calculated above are <= fixed point 0.5, and the equation - // below is just lerping between two values <= fixed point 0.5 (0x00008000), then we know - // that the final result before shifting by 16 bits is no larger than 0x80000000. Once we - // shift that down by 16, we get the result of lerping 2 numbers <= 0.5, which is obviously - // at most 0.5 (0x00008000) - fxpLocation = fxpLocationOnFloorHalfTessFactor * (FXP_ONE - TessFactorCtx.fxpHalfTessFactorFraction) + - fxpLocationOnCeilHalfTessFactor * (TessFactorCtx.fxpHalfTessFactorFraction); - fxpLocation = (fxpLocation + FXP_ONE_HALF/*round*/) >> FXP_FRACTION_BITS; // get back to n.16 - /* Commenting out floating point version. Note the parameter cleansing it does is not needed in fixed point. - if( bFlip ) - location = 1.0f - location; // complement produces cleansed result. - else - CleanseParameter(location); - */ - if( bFlip ) - { - fxpLocation = FXP_ONE - fxpLocation; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::StitchRegular -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::StitchRegular(bool bTrapezoid,DIAGONALS diagonals, - int baseIndexOffset, int numInsideEdgePoints, - int insideEdgePointBaseOffset, int outsideEdgePointBaseOffset) -{ - int insidePoint = insideEdgePointBaseOffset; - int outsidePoint = outsideEdgePointBaseOffset; - if( bTrapezoid ) - { - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; outsidePoint++; - } - int p; - switch( diagonals ) - { - case DIAGONALS_INSIDE_TO_OUTSIDE: - // Diagonals pointing from inside edge forward towards outside edge - for( p = 0; p < numInsideEdgePoints-1; p++ ) - { - DefineClockwiseTriangle(insidePoint,outsidePoint,outsidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - - DefineClockwiseTriangle(insidePoint,outsidePoint+1,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; outsidePoint++; - } - break; - case DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE: // Assumes ODD tessellation - // Diagonals pointing from outside edge forward towards inside edge - - // First half - for( p = 0; p < numInsideEdgePoints/2-1; p++ ) - { - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; - DefineClockwiseTriangle(insidePoint,outsidePoint+1,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; outsidePoint++; - } - - // Middle - DefineClockwiseTriangle(outsidePoint,insidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; outsidePoint++; p+=2; - - // Second half - for( ; p < numInsideEdgePoints; p++ ) - { - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; - DefineClockwiseTriangle(insidePoint,outsidePoint+1,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; outsidePoint++; - } - break; - case DIAGONALS_MIRRORED: - // First half, diagonals pointing from outside of outside edge to inside of inside edge - for( p = 0; p < numInsideEdgePoints/2; p++ ) - { - DefineClockwiseTriangle(outsidePoint,insidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; outsidePoint++; - } - // Second half, diagonals pointing from inside of inside edge to outside of outside edge - for( ; p < numInsideEdgePoints-1; p++ ) - { - DefineClockwiseTriangle(insidePoint,outsidePoint,outsidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - DefineClockwiseTriangle(insidePoint,outsidePoint+1,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; outsidePoint++; - } - break; - } - if( bTrapezoid ) - { - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::StitchTransition() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHWTessellator::StitchTransition(int baseIndexOffset, - int insideEdgePointBaseOffset, int insideNumHalfTessFactorPoints, - TESSELLATOR_PARITY insideEdgeTessFactorParity, - int outsideEdgePointBaseOffset, int outsideNumHalfTessFactorPoints, - TESSELLATOR_PARITY outsideTessFactorParity -) -{ - -#ifdef ALLOW_XBOX_360_COMPARISON - // Tables to assist in the stitching of 2 rows of points having arbitrary TessFactors. - // The stitching order is governed by Ruler Function vertex split ordering (see external documentation). - // - // The contents of the finalPointPositionTable are where vertex i [0..32] ends up on the half-edge - // at the max tessellation amount given ruler-function split order. - // Recall the other half of an edge is mirrored, so we only need to deal with one half. - // This table is used to decide when to advance a point on the interior or exterior. - // It supports odd TessFactor up to 65 and even TessFactor up to 64. - static const int _finalPointPositionTable[33] = - { 0, 32, 16, 8, 17, 4, 18, 9, 19, 2, 20, 10, 21, 5, 22, 11, 23, - 1, 24, 12, 25, 6, 26, 13, 27, 3, 28, 14, 29, 7, 30, 15, 31 }; - // The loopStart and loopEnd tables below just provide optimal loop bounds for the - // stitching algorithm further below, for any given halfTssFactor. - // There is probably a better way to encode this... - - // loopStart[halfTessFactor] encodes the FIRST entry other that [0] in finalPointPositionTable[] above which is - // less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop. - static const int _loopStart[33] = - {1,1,17,9,9,5,5,5,5,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - // loopStart[halfTessFactor] encodes the LAST entry in finalPointPositionTable[] above which is - // less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop. - static const int _loopEnd[33] = - {0,0,17,17,25,25,25,25,29,29,29,29,29,29,29,29,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,32}; - const int* finalPointPositionTable; - const int* loopStart; - const int* loopEnd; - if( m_bXBox360Mode ) - { - // The XBox360 vertex introduction order is always from the center of the edge. - // So the final positions of points on the half-edge are this trivial table. - static const int XBOXfinalPointPositionTable[33] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; - // loopStart and loopEnd (meaning described above) also become trivial for XBox360 splitting. - static const int XBOXloopStart[33] = - {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - static const int XBOXloopEnd[33] = - {0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; - - finalPointPositionTable = XBOXfinalPointPositionTable; - loopStart = XBOXloopStart; - loopEnd = XBOXloopEnd; - } - else - { - finalPointPositionTable = _finalPointPositionTable; - loopStart = _loopStart; - loopEnd =_loopEnd; - } -#else - // Tables to assist in the stitching of 2 rows of points having arbitrary TessFactors. - // The stitching order is governed by Ruler Function vertex split ordering (see external documentation). - // - // The contents of the finalPointPositionTable are where vertex i [0..33] ends up on the half-edge - // at the max tessellation amount given ruler-function split order. - // Recall the other half of an edge is mirrored, so we only need to deal with one half. - // This table is used to decide when to advance a point on the interior or exterior. - // It supports odd TessFactor up to 65 and even TessFactor up to 64. - static const int finalPointPositionTable[33] = - { 0, 32, 16, 8, 17, 4, 18, 9, 19, 2, 20, 10, 21, 5, 22, 11, 23, - 1, 24, 12, 25, 6, 26, 13, 27, 3, 28, 14, 29, 7, 30, 15, 31 }; - - // The loopStart and loopEnd tables below just provide optimal loop bounds for the - // stitching algorithm further below, for any given halfTssFactor. - // There is probably a better way to encode this... - - // loopStart[halfTessFactor] encodes the FIRST entry in finalPointPositionTable[] above which is - // less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop. - static const int loopStart[33] = - {1,1,17,9,9,5,5,5,5,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; - // loopStart[halfTessFactor] encodes the LAST entry in finalPointPositionTable[] above which is - // less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop. - static const int loopEnd[33] = - {0,0,17,17,25,25,25,25,29,29,29,29,29,29,29,29,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,32}; -#endif - if( TESSELLATOR_PARITY_ODD == insideEdgeTessFactorParity ) - { - insideNumHalfTessFactorPoints -= 1; - } - if( TESSELLATOR_PARITY_ODD == outsideTessFactorParity ) - { - outsideNumHalfTessFactorPoints -= 1; - } - // Walk first half - int outsidePoint = outsideEdgePointBaseOffset; - int insidePoint = insideEdgePointBaseOffset; - - // iStart,iEnd are a small optimization so the loop below doesn't have to go from 0 up to 31 - int iStart = min(loopStart[insideNumHalfTessFactorPoints],loopStart[outsideNumHalfTessFactorPoints]); - int iEnd = max(loopEnd[insideNumHalfTessFactorPoints],loopEnd[outsideNumHalfTessFactorPoints]); - - if( finalPointPositionTable[0] < outsideNumHalfTessFactorPoints ) // since we dont' start the loop at 0 below, we need a special case. - { - // Advance outside - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; outsidePoint++; - } - - for(int i = iStart; i <= iEnd; i++) - { - if( /*(i>0) && <-- not needed since iStart is never 0*/(finalPointPositionTable[i] < insideNumHalfTessFactorPoints)) - { - // Advance inside - DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; insidePoint++; - } - if((finalPointPositionTable[i] < outsideNumHalfTessFactorPoints)) - { - // Advance outside - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; outsidePoint++; - } - } - - if( (insideEdgeTessFactorParity != outsideTessFactorParity) || (insideEdgeTessFactorParity == TESSELLATOR_PARITY_ODD)) - { - if( insideEdgeTessFactorParity == outsideTessFactorParity ) - { - // Quad in the middle - DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - DefineClockwiseTriangle(insidePoint+1,outsidePoint,outsidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; - outsidePoint++; - } - else if( TESSELLATOR_PARITY_EVEN == insideEdgeTessFactorParity ) - { - // Triangle pointing inside - DefineClockwiseTriangle(insidePoint,outsidePoint,outsidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - outsidePoint++; - } - else - { - // Triangle pointing outside - DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; - insidePoint++; - } - } - - // Walk second half. - for(int i = iEnd; i >= iStart; i--) - { - if((finalPointPositionTable[i] < outsideNumHalfTessFactorPoints)) - { - // Advance outside - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; outsidePoint++; - } - if( /*(i>0) && <-- not needed since iStart is never 0*/ (finalPointPositionTable[i] < insideNumHalfTessFactorPoints)) - { - // Advance inside - DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset); - baseIndexOffset += 3; insidePoint++; - } - } - // Below case is not needed if we didn't optimize loop above and made it run from 31 down to 0. - if((finalPointPositionTable[0] < outsideNumHalfTessFactorPoints)) - { - DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset); - baseIndexOffset += 3; outsidePoint++; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHWTessellator::PatchIndexValue() -//-------------------------------------------------------------------------------------------------------------------------------- -int CHWTessellator::PatchIndexValue(int index) -{ - if( m_bUsingPatchedIndices ) - { - if( index >= m_IndexPatchContext.outsidePointIndexPatchBase ) // assumed remapped outide indices are > remapped inside vertices - { - if( index == m_IndexPatchContext.outsidePointIndexBadValue ) - index = m_IndexPatchContext.outsidePointIndexReplacementValue; - else - index += m_IndexPatchContext.outsidePointIndexDeltaToRealValue; - } - else - { - if( index == m_IndexPatchContext.insidePointIndexBadValue ) - index = m_IndexPatchContext.insidePointIndexReplacementValue; - else - index += m_IndexPatchContext.insidePointIndexDeltaToRealValue; - } - } - else if( m_bUsingPatchedIndices2 ) - { - if( index >= m_IndexPatchContext2.baseIndexToInvert ) - { - if( index == m_IndexPatchContext2.cornerCaseBadValue ) - { - index = m_IndexPatchContext2.cornerCaseReplacementValue; - } - else - { - index = m_IndexPatchContext2.indexInversionEndPoint - index; - } - } - else if( index == m_IndexPatchContext2.cornerCaseBadValue ) - { - index = m_IndexPatchContext2.cornerCaseReplacementValue; - } - } - return index; -} - - -//================================================================================================================================= -// CHLSLTessellator -//================================================================================================================================= - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::CHLSLTessellator -//--------------------------------------------------------------------------------------------------------------------------------- -CHLSLTessellator::CHLSLTessellator() -{ - m_LastComputedTessFactors[0] = m_LastComputedTessFactors[1] = m_LastComputedTessFactors[2] = - m_LastComputedTessFactors[3] = m_LastComputedTessFactors[4] = m_LastComputedTessFactors[5] = 0; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::Init -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::Init( - D3D11_TESSELLATOR_PARTITIONING partitioning, - D3D11_TESSELLATOR_REDUCTION insideTessFactorReduction, - D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS quadInsideTessFactorReductionAxis, - D3D11_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive) -{ - CHWTessellator::Init(partitioning,outputPrimitive); - m_LastComputedTessFactors[0] = m_LastComputedTessFactors[1] = m_LastComputedTessFactors[2] = - m_LastComputedTessFactors[3] = m_LastComputedTessFactors[4] = m_LastComputedTessFactors[5] = 0; - m_partitioning = partitioning; - m_originalPartitioning = partitioning; - switch( partitioning ) - { - case D3D11_TESSELLATOR_PARTITIONING_INTEGER: - default: - break; - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: - m_parity = TESSELLATOR_PARITY_ODD; - break; - case D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: - m_parity = TESSELLATOR_PARITY_EVEN; - break; - } - m_originalParity = m_parity; - m_outputPrimitive = outputPrimitive; - m_insideTessFactorReduction = insideTessFactorReduction; - m_quadInsideTessFactorReductionAxis = quadInsideTessFactorReductionAxis; -} -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::TessellateQuadDomain -// User calls this -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::TessellateQuadDomain( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1, - float insideTessFactorScaleU, float insideTessFactorScaleV ) -{ - QuadHLSLProcessTessFactors(tessFactor_Ueq0,tessFactor_Veq0,tessFactor_Ueq1,tessFactor_Veq1,insideTessFactorScaleU,insideTessFactorScaleV); - - CHWTessellator::TessellateQuadDomain(m_LastComputedTessFactors[0],m_LastComputedTessFactors[1],m_LastComputedTessFactors[2],m_LastComputedTessFactors[3], - m_LastComputedTessFactors[4],m_LastComputedTessFactors[5]); -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::QuadHLSLProcessTessFactors -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::QuadHLSLProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1, - float insideTessFactorScaleU, float insideTessFactorScaleV ) -{ - if( !(tessFactor_Ueq0 > 0) ||// NaN will pass - !(tessFactor_Veq0 > 0) || - !(tessFactor_Ueq1 > 0) || - !(tessFactor_Veq1 > 0) ) - { - m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0; - m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0; - m_LastUnRoundedComputedTessFactors[2] = tessFactor_Ueq1; - m_LastUnRoundedComputedTessFactors[3] = tessFactor_Veq1; - m_LastUnRoundedComputedTessFactors[4] = 0; - m_LastUnRoundedComputedTessFactors[5] = 0; - m_LastComputedTessFactors[0] = - m_LastComputedTessFactors[1] = - m_LastComputedTessFactors[2] = - m_LastComputedTessFactors[3] = - m_LastComputedTessFactors[4] = - m_LastComputedTessFactors[5] = 0; - return; - } - - CleanupFloatTessFactor(tessFactor_Ueq0);// clamp to [1.0f..INF], NaN->1.0f - CleanupFloatTessFactor(tessFactor_Veq0); - CleanupFloatTessFactor(tessFactor_Ueq1); - CleanupFloatTessFactor(tessFactor_Veq1); - - // Save off tessFactors so they can be returned to app - m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0; - m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0; - m_LastUnRoundedComputedTessFactors[2] = tessFactor_Ueq1; - m_LastUnRoundedComputedTessFactors[3] = tessFactor_Veq1; - - // Process outside tessFactors - float outsideTessFactor[QUAD_EDGES] = {tessFactor_Ueq0, tessFactor_Veq0, tessFactor_Ueq1, tessFactor_Veq1}; - int edge, axis; - TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES]; - if( Pow2Partitioning() || IntegerPartitioning() ) - { - for( edge = 0; edge < QUAD_EDGES; edge++ ) - { - RoundUpTessFactor(outsideTessFactor[edge]); - ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode - } - } - else - { - SetTessellationParity(m_originalParity); // ClampTessFactor needs it - for( edge = 0; edge < QUAD_EDGES; edge++ ) - { - ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode - } - } - - // Compute inside TessFactors - float insideTessFactor[QUAD_AXES]; - if( m_quadInsideTessFactorReductionAxis == D3D11_TESSELLATOR_QUAD_REDUCTION_1_AXIS ) - { - switch( m_insideTessFactorReduction ) - { - case D3D11_TESSELLATOR_REDUCTION_MIN: - insideTessFactor[U] = tess_fmin(tess_fmin(tessFactor_Veq0,tessFactor_Veq1),tess_fmin(tessFactor_Ueq0,tessFactor_Ueq1)); - break; - case D3D11_TESSELLATOR_REDUCTION_MAX: - insideTessFactor[U] = tess_fmax(tess_fmax(tessFactor_Veq0,tessFactor_Veq1),tess_fmax(tessFactor_Ueq0,tessFactor_Ueq1)); - break; - case D3D11_TESSELLATOR_REDUCTION_AVERAGE: - insideTessFactor[U] = (tessFactor_Veq0 + tessFactor_Veq1 + tessFactor_Ueq0 + tessFactor_Ueq1) / 4; - break; - } - // Scale inside tessFactor based on user scale factor. - - ClampFloatTessFactorScale(insideTessFactorScaleU); // clamp scale value to [0..1], NaN->0 - insideTessFactor[U] = insideTessFactor[U]*insideTessFactorScaleU; - - // Compute inside parity - if( Pow2Partitioning() || IntegerPartitioning() ) - { - ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app - RoundUpTessFactor(insideTessFactor[U]); - insideTessFactorParity[U] = - insideTessFactorParity[V] = - (isEven(insideTessFactor[U]) || (FLOAT_ONE == insideTessFactor[U]) ) - ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - else - { - ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app - // no parity changes for fractional tessellation - just use what the user requested - insideTessFactorParity[U] = insideTessFactorParity[V] = m_originalParity; - } - - // To prevent snapping on edges, the "picture frame" comes - // in using avg or max (and ignore inside TessFactor scaling) until it is at least 3. - if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[U]) && - (insideTessFactor[U] < FLOAT_THREE) ) - { - if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction) - { - insideTessFactor[U] = tess_fmin(FLOAT_THREE,tess_fmax(tess_fmax(tessFactor_Veq0,tessFactor_Veq1),tess_fmax(tessFactor_Ueq0,tessFactor_Ueq1))); - } - else - { - insideTessFactor[U] = tess_fmin(FLOAT_THREE,(tessFactor_Veq0 + tessFactor_Veq1 + tessFactor_Ueq0 + tessFactor_Ueq1) / 4); - } - ClampTessFactor(insideTessFactor[U]); // clamp reduction result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app - if( IntegerPartitioning()) - { - RoundUpTessFactor(insideTessFactor[U]); - insideTessFactorParity[U] = - insideTessFactorParity[V] = isEven(insideTessFactor[U]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - } - insideTessFactor[V] = insideTessFactor[U]; - } - else - { - switch( m_insideTessFactorReduction ) - { - case D3D11_TESSELLATOR_REDUCTION_MIN: - insideTessFactor[U] = tess_fmin(tessFactor_Veq0,tessFactor_Veq1); - insideTessFactor[V] = tess_fmin(tessFactor_Ueq0,tessFactor_Ueq1); - break; - case D3D11_TESSELLATOR_REDUCTION_MAX: - insideTessFactor[U] = tess_fmax(tessFactor_Veq0,tessFactor_Veq1); - insideTessFactor[V] = tess_fmax(tessFactor_Ueq0,tessFactor_Ueq1); - break; - case D3D11_TESSELLATOR_REDUCTION_AVERAGE: - insideTessFactor[U] = (tessFactor_Veq0 + tessFactor_Veq1) / 2; - insideTessFactor[V] = (tessFactor_Ueq0 + tessFactor_Ueq1) / 2; - break; - } - // Scale inside tessFactors based on user scale factor. - - ClampFloatTessFactorScale(insideTessFactorScaleU); // clamp scale value to [0..1], NaN->0 - ClampFloatTessFactorScale(insideTessFactorScaleV); - insideTessFactor[U] = insideTessFactor[U]*insideTessFactorScaleU; - insideTessFactor[V] = insideTessFactor[V]*insideTessFactorScaleV; - - // Compute inside parity - if( Pow2Partitioning() || IntegerPartitioning() ) - { - for( axis = 0; axis < QUAD_AXES; axis++ ) - { - ClampTessFactor(insideTessFactor[axis]); // clamp reduction + scale result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[4+axis] = insideTessFactor[axis]; // Save off TessFactors so they can be returned to app - RoundUpTessFactor(insideTessFactor[axis]); - insideTessFactorParity[axis] = - (isEven(insideTessFactor[axis]) || (FLOAT_ONE == insideTessFactor[axis]) ) - ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - } - else - { - ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input - ClampTessFactor(insideTessFactor[V]); // clamp reduction + scale result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[4] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app - m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[V]; // Save off TessFactors so they can be returned to app - // no parity changes for fractional tessellation - just use what the user requested - insideTessFactorParity[U] = insideTessFactorParity[V] = m_originalParity; - } - - // To prevent snapping on edges, the "picture frame" comes - // in using avg or max (and ignore inside TessFactor scaling) until it is at least 3. - if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[U]) && - (insideTessFactor[U] < FLOAT_THREE) ) - { - if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction) - { - insideTessFactor[U] = tess_fmin(FLOAT_THREE,tess_fmax(tessFactor_Veq0,tessFactor_Veq1)); - } - else - { - insideTessFactor[U] = tess_fmin(FLOAT_THREE,(tessFactor_Veq0 + tessFactor_Veq1) / 2); - } - ClampTessFactor(insideTessFactor[U]); // clamp reduction result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[4] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app - if( IntegerPartitioning()) - { - RoundUpTessFactor(insideTessFactor[U]); - insideTessFactorParity[U] = isEven(insideTessFactor[U]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - } - - if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[V]) && - (insideTessFactor[V] < FLOAT_THREE) ) - { - if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction) - { - insideTessFactor[V] = tess_fmin(FLOAT_THREE,tess_fmax(tessFactor_Ueq0,tessFactor_Ueq1)); - } - else - { - insideTessFactor[V] = tess_fmin(FLOAT_THREE,(tessFactor_Ueq0 + tessFactor_Ueq1) / 2); - } - ClampTessFactor(insideTessFactor[V]);// clamp reduction result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[V]; // Save off TessFactors so they can be returned to app - if( IntegerPartitioning()) - { - RoundUpTessFactor(insideTessFactor[V]); - insideTessFactorParity[V] = isEven(insideTessFactor[V]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - } - - for( axis = 0; axis < QUAD_AXES; axis++ ) - { - if( TESSELLATOR_PARITY_ODD == insideTessFactorParity[axis] ) - { - // Ensure the first ring ("picture frame") interpolates in on all sides - // as much as the side with the minimum TessFactor. Prevents snapping to edge. - if( (insideTessFactor[axis] < FLOAT_THREE) && (insideTessFactor[axis] < insideTessFactor[(axis+1)&0x1])) - { - insideTessFactor[axis] = tess_fmin(insideTessFactor[(axis+1)&0x1],FLOAT_THREE); - m_LastUnRoundedComputedTessFactors[4+axis] = insideTessFactor[axis]; // Save off TessFactors so they can be returned to app - } - } - } - } - - // Save off TessFactors so they can be returned to app - m_LastComputedTessFactors[0] = outsideTessFactor[Ueq0]; - m_LastComputedTessFactors[1] = outsideTessFactor[Veq0]; - m_LastComputedTessFactors[2] = outsideTessFactor[Ueq1]; - m_LastComputedTessFactors[3] = outsideTessFactor[Veq1]; - m_LastComputedTessFactors[4] = insideTessFactor[U]; - m_LastComputedTessFactors[5] = insideTessFactor[V]; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::TessellateTriDomain -// User calls this -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::TessellateTriDomain( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Weq0, - float insideTessFactorScale ) -{ - TriHLSLProcessTessFactors(tessFactor_Ueq0,tessFactor_Veq0,tessFactor_Weq0,insideTessFactorScale); - - CHWTessellator::TessellateTriDomain(m_LastComputedTessFactors[0],m_LastComputedTessFactors[1],m_LastComputedTessFactors[2],m_LastComputedTessFactors[3]); -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::TriHLSLProcessTessFactors -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::TriHLSLProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Weq0, - float insideTessFactorScale ) -{ - if( !(tessFactor_Ueq0 > 0) || // NaN will pass - !(tessFactor_Veq0 > 0) || - !(tessFactor_Weq0 > 0) ) - { - m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0; - m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0; - m_LastUnRoundedComputedTessFactors[2] = tessFactor_Weq0; - m_LastUnRoundedComputedTessFactors[3] = - m_LastComputedTessFactors[0] = - m_LastComputedTessFactors[1] = - m_LastComputedTessFactors[2] = - m_LastComputedTessFactors[3] = 0; - return; - } - - CleanupFloatTessFactor(tessFactor_Ueq0); // clamp to [1.0f..INF], NaN->1.0f - CleanupFloatTessFactor(tessFactor_Veq0); - CleanupFloatTessFactor(tessFactor_Weq0); - - // Save off TessFactors so they can be returned to app - m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0; - m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0; - m_LastUnRoundedComputedTessFactors[2] = tessFactor_Weq0; - - // Process outside TessFactors - float outsideTessFactor[TRI_EDGES] = {tessFactor_Ueq0, tessFactor_Veq0, tessFactor_Weq0}; - int edge; - if( Pow2Partitioning() || IntegerPartitioning() ) - { - for( edge = 0; edge < TRI_EDGES; edge++ ) - { - RoundUpTessFactor(outsideTessFactor[edge]); // for pow2 this rounds to pow2 - ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode - } - } - else - { - for( edge = 0; edge < TRI_EDGES; edge++ ) - { - ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode - } - } - - // Compute inside TessFactor - float insideTessFactor; - switch( m_insideTessFactorReduction ) - { - case D3D11_TESSELLATOR_REDUCTION_MIN: - insideTessFactor = tess_fmin(tess_fmin(tessFactor_Ueq0,tessFactor_Veq0),tessFactor_Weq0); - break; - case D3D11_TESSELLATOR_REDUCTION_MAX: - insideTessFactor = tess_fmax(tess_fmax(tessFactor_Ueq0,tessFactor_Veq0),tessFactor_Weq0); - break; - case D3D11_TESSELLATOR_REDUCTION_AVERAGE: - insideTessFactor = (tessFactor_Ueq0 + tessFactor_Veq0 + tessFactor_Weq0) / 3; - break; - } - - // Scale inside TessFactor based on user scale factor. - ClampFloatTessFactorScale(insideTessFactorScale); // clamp scale value to [0..1], NaN->0 - insideTessFactor = insideTessFactor*tess_fmin(FLOAT_ONE,insideTessFactorScale); - - ClampTessFactor(insideTessFactor); // clamp reduction + scale result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[3] = insideTessFactor;// Save off TessFactors so they can be returned to app - TESSELLATOR_PARITY parity; - if( Pow2Partitioning() || IntegerPartitioning() ) - { - RoundUpTessFactor(insideTessFactor); - parity = (isEven(insideTessFactor) || (FLOAT_ONE == insideTessFactor)) - ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD; - } - else - { - parity = m_originalParity; - } - - if( (TESSELLATOR_PARITY_ODD == parity) && - (insideTessFactor < FLOAT_THREE)) - { - // To prevent snapping on edges, the "picture frame" comes - // in using avg or max (and ignore inside TessFactor scaling) until it is at least 3. - if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction) - { - insideTessFactor = tess_fmin(FLOAT_THREE,tess_fmax(tessFactor_Ueq0,tess_fmax(tessFactor_Veq0,tessFactor_Weq0))); - } - else - { - insideTessFactor = tess_fmin(FLOAT_THREE,(tessFactor_Ueq0 + tessFactor_Veq0 + tessFactor_Weq0) / 3); - } - ClampTessFactor(insideTessFactor); // clamp reduction result that is based on unbounded user input - m_LastUnRoundedComputedTessFactors[3] = insideTessFactor;// Save off TessFactors so they can be returned to app - if( IntegerPartitioning()) - { - RoundUpTessFactor(insideTessFactor); - } - } - - // Save off TessFactors so they can be returned to app - m_LastComputedTessFactors[0] = outsideTessFactor[Ueq0]; - m_LastComputedTessFactors[1] = outsideTessFactor[Veq0]; - m_LastComputedTessFactors[2] = outsideTessFactor[Weq0]; - m_LastComputedTessFactors[3] = insideTessFactor; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::TessellateIsoLineDomain -// User calls this. -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::TessellateIsoLineDomain( float TessFactor_U_LineDetail, float TessFactor_V_LineDensity ) -{ - IsoLineHLSLProcessTessFactors(TessFactor_V_LineDensity,TessFactor_U_LineDetail); - CHWTessellator::TessellateIsoLineDomain(m_LastComputedTessFactors[0],m_LastComputedTessFactors[1]); -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::IsoLineHLSLProcessTessFactors -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::IsoLineHLSLProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail ) -{ - if( !(TessFactor_V_LineDensity > 0) || // NaN will pass - !(TessFactor_U_LineDetail > 0) ) - { - m_LastUnRoundedComputedTessFactors[0] = TessFactor_V_LineDensity; - m_LastUnRoundedComputedTessFactors[1] = TessFactor_U_LineDetail; - m_LastComputedTessFactors[0] = - m_LastComputedTessFactors[1] = 0; - return; - } - - CleanupFloatTessFactor(TessFactor_V_LineDensity); // clamp to [1.0f..INF], NaN->1.0f - CleanupFloatTessFactor(TessFactor_U_LineDetail); // clamp to [1.0f..INF], NaN->1.0f - - ClampTessFactor(TessFactor_U_LineDetail); // clamp unbounded user input based on tessellation mode - - m_LastUnRoundedComputedTessFactors[1] = TessFactor_U_LineDetail; // Save off TessFactors so they can be returned to app - - if(Pow2Partitioning()||IntegerPartitioning()) - { - RoundUpTessFactor(TessFactor_U_LineDetail); - } - - OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING_INTEGER); - - ClampTessFactor(TessFactor_V_LineDensity); // Clamp unbounded user input to integer - m_LastUnRoundedComputedTessFactors[0] = TessFactor_V_LineDensity; // Save off TessFactors so they can be returned to app - - RoundUpTessFactor(TessFactor_V_LineDensity); - - RestorePartitioning(); - - // Save off TessFactors so they can be returned to app - m_LastComputedTessFactors[0] = TessFactor_V_LineDensity; - m_LastComputedTessFactors[1] = TessFactor_U_LineDetail; -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::ClampTessFactor() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::ClampTessFactor(float& TessFactor) -{ - if( Pow2Partitioning() ) - { - TessFactor = tess_fmin( D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR, tess_fmax( TessFactor, D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR) ); - } - else if( IntegerPartitioning() ) - { - TessFactor = tess_fmin( D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR, tess_fmax( TessFactor, D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR) ); - } - else if( Odd() ) - { - TessFactor = tess_fmin( D3D11_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR, tess_fmax( TessFactor, D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR) ); - } - else // even - { - TessFactor = tess_fmin( D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR, tess_fmax( TessFactor, D3D11_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR) ); - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::CleanupFloatTessFactor() -//--------------------------------------------------------------------------------------------------------------------------------- -static const int exponentMask = 0x7f800000; -static const int mantissaMask = 0x007fffff; -void CHLSLTessellator::CleanupFloatTessFactor(float& input) -{ - // If input is < 1.0f or NaN, clamp to 1.0f. - // In other words, clamp input to [1.0f...+INF] - int bits = *(int*)&input; - if( ( ( ( bits & exponentMask ) == exponentMask ) && ( bits & mantissaMask ) ) ||// nan? - (input < 1.0f) ) - { - input = 1; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::ClampFloatTessFactorScale() -//--------------------------------------------------------------------------------------------------------------------------------- -void CHLSLTessellator::ClampFloatTessFactorScale(float& input) -{ - // If input is < 0.0f or NaN, clamp to 0.0f. > 1 clamps to 1. - // In other words, clamp input to [0.0f...1.0f] - int bits = *(int*)&input; - if( ( ( ( bits & exponentMask ) == exponentMask ) && ( bits & mantissaMask ) ) ||// nan? - (input < 0.0f) ) - { - input = 0; - } - else if( input > 1 ) - { - input = 1; - } -} - -//--------------------------------------------------------------------------------------------------------------------------------- -// CHLSLTessellator::RoundUpTessFactor() -//--------------------------------------------------------------------------------------------------------------------------------- -static const int exponentLSB = 0x00800000; -void CHLSLTessellator::RoundUpTessFactor(float& TessFactor) -{ - // Assume TessFactor is in [1.0f..+INF] - if( Pow2Partitioning() ) - { - int bits = *(int*)&TessFactor; - if( bits & mantissaMask ) - { - *(int*)&TessFactor = (bits & exponentMask) + exponentLSB; - } - } - else if( IntegerPartitioning() ) - { - TessFactor = ceil(TessFactor); - } -} |