context/llpcGraphicsContext.cpp
void GraphicsContext::DoUserDataNodeMerge()
{
    uint32_t stageMask = GetShaderStageMask();
    SmallVector<ResourceMappingNode, 8> allNodes;

    // No need to merge if there is only one shader stage.
    if (isPowerOf2_32(stageMask))
    {
        return;
    }

    // Collect user data nodes from all shader stages into one big table.
    for (uint32_t stage = 0; stage < ShaderStageNativeStageCount; ++stage)
    {
        if ((stageMask >> stage) & 1)
        {
            auto pShaderInfo = GetPipelineShaderInfo(ShaderStage(stage));
            for (const ResourceMappingNode& node : ArrayRef<ResourceMappingNode>(pShaderInfo->pUserDataNodes,
                                                                                 pShaderInfo->userDataNodeCount))
            {
                allNodes.push_back(node);
            }
        }
    }

    // Sort and merge.
    ArrayRef<ResourceMappingNode> mergedNodes = MergeUserDataNodeTable(allNodes);

    // Collect descriptor range values (immutable descriptors) from all shader stages into one big table.
    SmallVector<DescriptorRangeValue, 8> allRangeValues;
    for (uint32_t stage = 0; stage < ShaderStageNativeStageCount; ++stage)
    {
        if ((stageMask >> stage) & 1)
        {
            auto pShaderInfo = GetPipelineShaderInfo(ShaderStage(stage));
            for (const DescriptorRangeValue& rangeValue :
                        ArrayRef<DescriptorRangeValue>(pShaderInfo->pDescriptorRangeValues,
                                                       pShaderInfo->descriptorRangeValueCount))
            {
                allRangeValues.push_back(rangeValue);
            }
        }
    }

    // Sort them by set and binding, so we can spot duplicates.
    std::sort(allRangeValues.begin(),
              allRangeValues.end(),
              [](const DescriptorRangeValue& left, const DescriptorRangeValue& right)
              {
                  if (left.set != right.set)
                  {
                      return left.set < right.set;
                  }
                  return left.binding < right.binding;
              });

    if (allRangeValues.empty() == false)
    {
        // Create a new table with merged duplicates.
        m_allocDescriptorRangeValues = make_unique<SmallVector<DescriptorRangeValue, 8>>();
        auto &mergedRangeValues = *m_allocDescriptorRangeValues;
        ArrayRef<DescriptorRangeValue> rangeValues = allRangeValues;

        while (rangeValues.empty() == false)
        {
            // Find the next block of duplicate rangeValues.
            uint32_t duplicateCount = 1;
            for (; duplicateCount != rangeValues.size(); ++duplicateCount)
            {
                if ((rangeValues[0].set != rangeValues[duplicateCount].set) || (rangeValues[0].binding != rangeValues[duplicateCount].binding))
                {
                    break;
                }
                LLPC_ASSERT((rangeValues[0].type == rangeValues[duplicateCount].type) &&
                            "Descriptor range value merge conflict: type");
                LLPC_ASSERT((rangeValues[0].arraySize == rangeValues[duplicateCount].arraySize) &&
                            "Descriptor range value merge conflict: arraySize");
                LLPC_ASSERT((memcmp(rangeValues[0].pValue,
                                    rangeValues[duplicateCount].pValue,
                                    rangeValues[0].arraySize * sizeof(uint32_t)) == 0) &&
                            "Descriptor range value merge conflict: value");
            }

            // Keep the merged range.
            mergedRangeValues.push_back(rangeValues[0]);
            rangeValues = rangeValues.slice(duplicateCount);
        }
    }

    // Point each shader stage at the merged user data nodes and descriptor range values.
    for (uint32_t stage = 0; stage < ShaderStageNativeStageCount; ++stage)
    {
        if ((stageMask >> stage) & 1)
        {
            auto pShaderInfo = const_cast<PipelineShaderInfo*>(GetPipelineShaderInfo(ShaderStage(stage)));
            pShaderInfo->pUserDataNodes = mergedNodes.data();
            pShaderInfo->userDataNodeCount = mergedNodes.size();
            if (m_allocDescriptorRangeValues)
            {
                pShaderInfo->pDescriptorRangeValues = m_allocDescriptorRangeValues->data();
                pShaderInfo->descriptorRangeValueCount = m_allocDescriptorRangeValues->size();
            }
        }
    }
}
// =====================================================================================================================
// Does user data node merging for all shader stages
Does user data node merging for all shader stages
Does user data node merging for all shader stages
void GraphicsContext::DoUserDataNodeMerge()
{
    uint32_t stageMask = GetShaderStageMask();
    SmallVector<ResourceMappingNode, 8> allNodes;
    if (isPowerOf2_32(stageMask))
    {
        return;
    }
    for (uint32_t stage = 0; stage < ShaderStageNativeStageCount; ++stage)
    {
        if ((stageMask >> stage) & 1)
        {
            auto pShaderInfo = GetPipelineShaderInfo(ShaderStage(stage));
            for (const ResourceMappingNode& node : ArrayRef<ResourceMappingNode>(pShaderInfo->pUserDataNodes,
                                                                                 pShaderInfo->userDataNodeCount))
            {
                allNodes.push_back(node);
            }
        }
    }
    ArrayRef<ResourceMappingNode> mergedNodes = MergeUserDataNodeTable(allNodes);
    SmallVector<DescriptorRangeValue, 8> allRangeValues;
    for (uint32_t stage = 0; stage < ShaderStageNativeStageCount; ++stage)
    {
        if ((stageMask >> stage) & 1)
        {
            auto pShaderInfo = GetPipelineShaderInfo(ShaderStage(stage));
            for (const DescriptorRangeValue& rangeValue :
                        ArrayRef<DescriptorRangeValue>(pShaderInfo->pDescriptorRangeValues,
                                                       pShaderInfo->descriptorRangeValueCount))
            {
                allRangeValues.push_back(rangeValue);
            }
        }
    }
    std::sort(allRangeValues.begin(),
              allRangeValues.end(),
              [](const DescriptorRangeValue& left, const DescriptorRangeValue& right)
              {
                  if (left.set != right.set)
                  {
                      return left.set < right.set;
                  }
                  return left.binding < right.binding;
              });
    if (allRangeValues.empty() == false)
    {
        m_allocDescriptorRangeValues = make_unique<SmallVector<DescriptorRangeValue, 8>>();
        auto &mergedRangeValues = *m_allocDescriptorRangeValues;
        ArrayRef<DescriptorRangeValue> rangeValues = allRangeValues;
        while (rangeValues.empty() == false)
        {
            uint32_t duplicateCount = 1;
            for (; duplicateCount != rangeValues.size(); ++duplicateCount)
            {
                if ((rangeValues[0].set != rangeValues[duplicateCount].set) || (rangeValues[0].binding != rangeValues[duplicateCount].binding))
                {
                    break;
                }
                LLPC_ASSERT((rangeValues[0].type == rangeValues[duplicateCount].type) &&
                            "Descriptor range value merge conflict: type");
                LLPC_ASSERT((rangeValues[0].arraySize == rangeValues[duplicateCount].arraySize) &&
                            "Descriptor range value merge conflict: arraySize");
                LLPC_ASSERT((memcmp(rangeValues[0].pValue,
                                    rangeValues[duplicateCount].pValue,
                                    rangeValues[0].arraySize * sizeof(uint32_t)) == 0) &&
                            "Descriptor range value merge conflict: value");
            }
            mergedRangeValues.push_back(rangeValues[0]);
            rangeValues = rangeValues.slice(duplicateCount);
        }
    }
    for (uint32_t stage = 0; stage < ShaderStageNativeStageCount; ++stage)
    {
        if ((stageMask >> stage) & 1)
        {
            auto pShaderInfo = const_cast<PipelineShaderInfo*>(GetPipelineShaderInfo(ShaderStage(stage)));
            pShaderInfo->pUserDataNodes = mergedNodes.data();
            pShaderInfo->userDataNodeCount = mergedNodes.size();
            if (m_allocDescriptorRangeValues)
            {
                pShaderInfo->pDescriptorRangeValues = m_allocDescriptorRangeValues->data();
                pShaderInfo->descriptorRangeValueCount = m_allocDescriptorRangeValues->size();
            }
        }
    }
}
void GraphicsContext :: DoUserDataNodeMerge ( ) { uint32_t stageMask = GetShaderStageMask ( ) ; SmallVector < ResourceMappingNode , 8 > allNodes ; if ( isPowerOf2_32 ( stageMask ) ) { return ; } for ( uint32_t stage = 0 ; stage < ShaderStageNativeStageCount ; ++ stage ) { if ( ( stageMask >> stage ) & 1 ) { auto pShaderInfo = GetPipelineShaderInfo ( ShaderStage ( stage ) ) ; for ( const ResourceMappingNode & node : ArrayRef < ResourceMappingNode > ( pShaderInfo -> pUserDataNodes , pShaderInfo -> userDataNodeCount ) ) { allNodes . push_back ( node ) ; } } } ArrayRef < ResourceMappingNode > mergedNodes = MergeUserDataNodeTable ( allNodes ) ; SmallVector < DescriptorRangeValue , 8 > allRangeValues ; for ( uint32_t stage = 0 ; stage < ShaderStageNativeStageCount ; ++ stage ) { if ( ( stageMask >> stage ) & 1 ) { auto pShaderInfo = GetPipelineShaderInfo ( ShaderStage ( stage ) ) ; for ( const DescriptorRangeValue & rangeValue : ArrayRef < DescriptorRangeValue > ( pShaderInfo -> pDescriptorRangeValues , pShaderInfo -> descriptorRangeValueCount ) ) { allRangeValues . push_back ( rangeValue ) ; } } } std :: sort ( allRangeValues . begin ( ) , allRangeValues . end ( ) , [ ] ( const DescriptorRangeValue & left , const DescriptorRangeValue & right ) { if ( left . set != right . set ) { return left . set < right . set ; } return left . binding < right . binding ; } ) ; if ( allRangeValues . empty ( ) == false ) { m_allocDescriptorRangeValues = make_unique < SmallVector < DescriptorRangeValue , 8 > > ( ) ; auto & mergedRangeValues = * m_allocDescriptorRangeValues ; ArrayRef < DescriptorRangeValue > rangeValues = allRangeValues ; while ( rangeValues . empty ( ) == false ) { uint32_t duplicateCount = 1 ; for ( ; duplicateCount != rangeValues . size ( ) ; ++ duplicateCount ) { if ( ( rangeValues [ 0 ] . set != rangeValues [ duplicateCount ] . set ) || ( rangeValues [ 0 ] . binding != rangeValues [ duplicateCount ] . binding ) ) { break ; } LLPC_ASSERT ( ( rangeValues [ 0 ] . type == rangeValues [ duplicateCount ] . type ) && " " ) ; LLPC_ASSERT ( ( rangeValues [ 0 ] . arraySize == rangeValues [ duplicateCount ] . arraySize ) && " " ) ; LLPC_ASSERT ( ( memcmp ( rangeValues [ 0 ] . pValue , rangeValues [ duplicateCount ] . pValue , rangeValues [ 0 ] . arraySize * sizeof ( uint32_t ) ) == 0 ) && " " ) ; } mergedRangeValues . push_back ( rangeValues [ 0 ] ) ; rangeValues = rangeValues . slice ( duplicateCount ) ; } } for ( uint32_t stage = 0 ; stage < ShaderStageNativeStageCount ; ++ stage ) { if ( ( stageMask >> stage ) & 1 ) { auto pShaderInfo = const_cast < PipelineShaderInfo * > ( GetPipelineShaderInfo ( ShaderStage ( stage ) ) ) ; pShaderInfo -> pUserDataNodes = mergedNodes . data ( ) ; pShaderInfo -> userDataNodeCount = mergedNodes . size ( ) ; if ( m_allocDescriptorRangeValues ) { pShaderInfo -> pDescriptorRangeValues = m_allocDescriptorRangeValues -> data ( ) ; pShaderInfo -> descriptorRangeValueCount = m_allocDescriptorRangeValues -> size ( ) ; } } } }
Does user data node merging for all shader stages
Does user data node merging for all shader stages
// No need to merge if there is only one shader stage. // Collect user data nodes from all shader stages into one big table. // Sort and merge. // Collect descriptor range values (immutable descriptors) from all shader stages into one big table. // Sort them by set and binding, so we can spot duplicates. // Create a new table with merged duplicates. // Find the next block of duplicate rangeValues. // Keep the merged range. // Point each shader stage at the merged user data nodes and descriptor range values.