summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/swr/rasterizer/core/tessellator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/swr/rasterizer/core/tessellator.cpp')
-rw-r--r--src/gallium/drivers/swr/rasterizer/core/tessellator.cpp2689
1 files changed, 0 insertions, 2689 deletions
diff --git a/src/gallium/drivers/swr/rasterizer/core/tessellator.cpp b/src/gallium/drivers/swr/rasterizer/core/tessellator.cpp
deleted file mode 100644
index 08f2bce339c..00000000000
--- a/src/gallium/drivers/swr/rasterizer/core/tessellator.cpp
+++ /dev/null
@@ -1,2689 +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(_MSC_VER)
-#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
-//---------------------------------------------------------------------------------------------------------------------------------
-static bool tess_isNaN( float a )
-{
- static const int exponentMask = 0x7f800000;
- static const int mantissaMask = 0x007fffff;
- int u = *(int*)&a;
- return ( ( ( u & exponentMask ) == exponentMask ) && ( u & 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;
- int b = (*(int*)&a) & signBitComplement; // fabs()
- if( b < minNormalizedFloat ) // UINT comparison. NaN/INF do test false here
- {
- b = signBit & (*(int*)&a);
- return *(float*)&b;
- }
- 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 ) )
- {
- return ( (*(int*)&_a) & 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 ) )
- {
- return ( (*(int*)&_b) & 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(_MSC_VER)
-#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(_MSC_VER)
-#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] = {0.0};
- 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 = 0.0;
- 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);
- }
-}