context/llpcGraphicsContext.cpp
ArrayRef<ResourceMappingNode> GraphicsContext::MergeUserDataNodeTable(
    SmallVectorImpl<ResourceMappingNode>& allNodes)   // Table of nodes
{
    // Sort the nodes by offset, so we can spot duplicates.
    std::sort(allNodes.begin(),
              allNodes.end(),
              [](const ResourceMappingNode& left, const ResourceMappingNode& right)
              {
                  return left.offsetInDwords < right.offsetInDwords;
              });

    // Merge duplicates.
    m_allocUserDataNodes.push_back(make_unique<SmallVector<ResourceMappingNode, 8>>());
    auto& mergedNodes = *m_allocUserDataNodes.back();
    ArrayRef<ResourceMappingNode> nodes = allNodes;

    while (nodes.empty() == false)
    {
        // Find the next block of duplicate nodes.
        uint32_t duplicatesCount = 1;
        for (; duplicatesCount != nodes.size(); ++duplicatesCount)
        {
            if (nodes[0].offsetInDwords != nodes[duplicatesCount].offsetInDwords)
            {
                break;
            }
            LLPC_ASSERT((nodes[0].type == nodes[duplicatesCount].type) && "User data merge conflict: type");
            LLPC_ASSERT((nodes[0].sizeInDwords == nodes[duplicatesCount].sizeInDwords) &&
                        "User data merge conflict: size");
            LLPC_ASSERT((nodes[0].type != ResourceMappingNodeType::IndirectUserDataVaPtr) &&
                        "User data merge conflict: only one shader stage expected to have vertex buffer");
            LLPC_ASSERT((nodes[0].type != ResourceMappingNodeType::StreamOutTableVaPtr) &&
                        "User data merge conflict: only one shader stage expected to have stream out");
            if (nodes[0].type != ResourceMappingNodeType::DescriptorTableVaPtr)
            {
                LLPC_ASSERT((nodes[0].srdRange.set == nodes[duplicatesCount].srdRange.set) &&
                            (nodes[0].srdRange.binding == nodes[duplicatesCount].srdRange.binding) &&
                            "User data merge conflict: set or binding");
            }
        }

        if ((duplicatesCount == 1) || (nodes[0].type != ResourceMappingNodeType::DescriptorTableVaPtr))
        {
            // Keep the merged node.
            mergedNodes.push_back(nodes[0]);
        }
        else
        {
            // Merge the inner tables too. First collect nodes from all inner tables.
            SmallVector<ResourceMappingNode, 8> allInnerNodes;

            for (uint32_t i = 0; i != duplicatesCount; ++i)
            {
                const auto& node = nodes[0];
                ArrayRef<ResourceMappingNode> innerTable(node.tablePtr.pNext, node.tablePtr.nodeCount);
                allInnerNodes.insert(allInnerNodes.end(), innerTable.begin(), innerTable.end());
            }

            // Call recursively to sort and merge.
            auto mergedInnerNodes = MergeUserDataNodeTable(allInnerNodes);

            // Finished merging the inner tables. Keep the merged DescriptorTableVaPtr node.
            ResourceMappingNode modifiedNode = nodes[0];
            modifiedNode.tablePtr.nodeCount = mergedInnerNodes.size();
            modifiedNode.tablePtr.pNext = &mergedInnerNodes[0];
            mergedNodes.push_back(modifiedNode);
        }

        nodes = nodes.slice(duplicatesCount);
    }
    return mergedNodes;
}
// =====================================================================================================================
// Merge user data nodes that have been collected into one big table
Merge user data nodes that have been collected into one big table
Merge user data nodes that have been collected into one big table
ArrayRef<ResourceMappingNode> GraphicsContext::MergeUserDataNodeTable(
    SmallVectorImpl<ResourceMappingNode>& allNodes)   
{
    std::sort(allNodes.begin(),
              allNodes.end(),
              [](const ResourceMappingNode& left, const ResourceMappingNode& right)
              {
                  return left.offsetInDwords < right.offsetInDwords;
              });
    m_allocUserDataNodes.push_back(make_unique<SmallVector<ResourceMappingNode, 8>>());
    auto& mergedNodes = *m_allocUserDataNodes.back();
    ArrayRef<ResourceMappingNode> nodes = allNodes;
    while (nodes.empty() == false)
    {
        uint32_t duplicatesCount = 1;
        for (; duplicatesCount != nodes.size(); ++duplicatesCount)
        {
            if (nodes[0].offsetInDwords != nodes[duplicatesCount].offsetInDwords)
            {
                break;
            }
            LLPC_ASSERT((nodes[0].type == nodes[duplicatesCount].type) && "User data merge conflict: type");
            LLPC_ASSERT((nodes[0].sizeInDwords == nodes[duplicatesCount].sizeInDwords) &&
                        "User data merge conflict: size");
            LLPC_ASSERT((nodes[0].type != ResourceMappingNodeType::IndirectUserDataVaPtr) &&
                        "User data merge conflict: only one shader stage expected to have vertex buffer");
            LLPC_ASSERT((nodes[0].type != ResourceMappingNodeType::StreamOutTableVaPtr) &&
                        "User data merge conflict: only one shader stage expected to have stream out");
            if (nodes[0].type != ResourceMappingNodeType::DescriptorTableVaPtr)
            {
                LLPC_ASSERT((nodes[0].srdRange.set == nodes[duplicatesCount].srdRange.set) &&
                            (nodes[0].srdRange.binding == nodes[duplicatesCount].srdRange.binding) &&
                            "User data merge conflict: set or binding");
            }
        }
        if ((duplicatesCount == 1) || (nodes[0].type != ResourceMappingNodeType::DescriptorTableVaPtr))
        {
            mergedNodes.push_back(nodes[0]);
        }
        else
        {
            SmallVector<ResourceMappingNode, 8> allInnerNodes;
            for (uint32_t i = 0; i != duplicatesCount; ++i)
            {
                const auto& node = nodes[0];
                ArrayRef<ResourceMappingNode> innerTable(node.tablePtr.pNext, node.tablePtr.nodeCount);
                allInnerNodes.insert(allInnerNodes.end(), innerTable.begin(), innerTable.end());
            }
            auto mergedInnerNodes = MergeUserDataNodeTable(allInnerNodes);
            ResourceMappingNode modifiedNode = nodes[0];
            modifiedNode.tablePtr.nodeCount = mergedInnerNodes.size();
            modifiedNode.tablePtr.pNext = &mergedInnerNodes[0];
            mergedNodes.push_back(modifiedNode);
        }
        nodes = nodes.slice(duplicatesCount);
    }
    return mergedNodes;
}
ArrayRef < ResourceMappingNode > GraphicsContext :: MergeUserDataNodeTable ( SmallVectorImpl < ResourceMappingNode > & allNodes ) { std :: sort ( allNodes . begin ( ) , allNodes . end ( ) , [ ] ( const ResourceMappingNode & left , const ResourceMappingNode & right ) { return left . offsetInDwords < right . offsetInDwords ; } ) ; m_allocUserDataNodes . push_back ( make_unique < SmallVector < ResourceMappingNode , 8 > > ( ) ) ; auto & mergedNodes = * m_allocUserDataNodes . back ( ) ; ArrayRef < ResourceMappingNode > nodes = allNodes ; while ( nodes . empty ( ) == false ) { uint32_t duplicatesCount = 1 ; for ( ; duplicatesCount != nodes . size ( ) ; ++ duplicatesCount ) { if ( nodes [ 0 ] . offsetInDwords != nodes [ duplicatesCount ] . offsetInDwords ) { break ; } LLPC_ASSERT ( ( nodes [ 0 ] . type == nodes [ duplicatesCount ] . type ) && " " ) ; LLPC_ASSERT ( ( nodes [ 0 ] . sizeInDwords == nodes [ duplicatesCount ] . sizeInDwords ) && " " ) ; LLPC_ASSERT ( ( nodes [ 0 ] . type != ResourceMappingNodeType :: IndirectUserDataVaPtr ) && " " ) ; LLPC_ASSERT ( ( nodes [ 0 ] . type != ResourceMappingNodeType :: StreamOutTableVaPtr ) && " " ) ; if ( nodes [ 0 ] . type != ResourceMappingNodeType :: DescriptorTableVaPtr ) { LLPC_ASSERT ( ( nodes [ 0 ] . srdRange . set == nodes [ duplicatesCount ] . srdRange . set ) && ( nodes [ 0 ] . srdRange . binding == nodes [ duplicatesCount ] . srdRange . binding ) && " " ) ; } } if ( ( duplicatesCount == 1 ) || ( nodes [ 0 ] . type != ResourceMappingNodeType :: DescriptorTableVaPtr ) ) { mergedNodes . push_back ( nodes [ 0 ] ) ; } else { SmallVector < ResourceMappingNode , 8 > allInnerNodes ; for ( uint32_t i = 0 ; i != duplicatesCount ; ++ i ) { const auto & node = nodes [ 0 ] ; ArrayRef < ResourceMappingNode > innerTable ( node . tablePtr . pNext , node . tablePtr . nodeCount ) ; allInnerNodes . insert ( allInnerNodes . end ( ) , innerTable . begin ( ) , innerTable . end ( ) ) ; } auto mergedInnerNodes = MergeUserDataNodeTable ( allInnerNodes ) ; ResourceMappingNode modifiedNode = nodes [ 0 ] ; modifiedNode . tablePtr . nodeCount = mergedInnerNodes . size ( ) ; modifiedNode . tablePtr . pNext = & mergedInnerNodes [ 0 ] ; mergedNodes . push_back ( modifiedNode ) ; } nodes = nodes . slice ( duplicatesCount ) ; } return mergedNodes ; }
Merge user data nodes that have been collected into one big table
Merge user data nodes that have been collected into one big table
// Table of nodes // Sort the nodes by offset, so we can spot duplicates. // Merge duplicates. // Find the next block of duplicate nodes. // Keep the merged node. // Merge the inner tables too. First collect nodes from all inner tables. // Call recursively to sort and merge. // Finished merging the inner tables. Keep the merged DescriptorTableVaPtr node.