void CHWTessellator::TriProcessTessFactors()

in d3d/archive/images/d3d11/tessellator.cpp [1023:1187]


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, upperBound;
    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 = fmin( upperBound, fmax( lowerBound, tessFactor_Ueq0 ) );
    tessFactor_Veq0 = fmin( upperBound, fmax( lowerBound, tessFactor_Veq0 ) );
    tessFactor_Weq0 = fmin( upperBound, 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 = fmin( upperBound, 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;
    }

}