//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: This is a helper class for the situation where you want to build lists of // things that fall into buckets, and effeciently keep up with which buckets have // been used since flush. // //=============================================================================// #ifndef MATERIALBUCKETS_H #define MATERIALBUCKETS_H #ifdef _WIN32 #pragma once #endif // FLASHLIGHTFIXME: Make all of the buckets share the same m_Elements (ie. make m_Elements static) template class CMaterialsBuckets { public: typedef unsigned short SortIDHandle_t; typedef unsigned short ElementHandle_t; CMaterialsBuckets() { m_FlushCount = -1; } // Set the number of buckets that are needed. This should get called every time // a level is loaded. void SetNumMaterialSortIDs( int n ) { m_MaterialSortInfoArray.Purge(); m_MaterialSortInfoArray.SetCount( n ); m_Elements.Purge(); m_UsedSortIDs.Purge(); } // Clear out all buckets. This should get called once a frame. void Flush( void ) { m_FlushCount++; m_Elements.RemoveAll(); m_UsedSortIDs.RemoveAll(); } // // These functions are used to get at the list of used buckets. // SortIDHandle_t GetFirstUsedSortID() { return m_UsedSortIDs.Head(); } SortIDHandle_t GetNextUsedSortID( SortIDHandle_t prevSortID ) { return m_UsedSortIDs.Next( prevSortID ); } int GetSortID( SortIDHandle_t handle ) { return m_UsedSortIDs[handle]; } SortIDHandle_t InvalidSortIDHandle() { return m_UsedSortIDs.InvalidIndex(); } // // These functions are used to get at the list of elements for each sortID. // ElementHandle_t GetElementListHead( int sortID ) { return m_MaterialSortInfoArray[sortID].m_Head; } ElementHandle_t GetElementListNext( ElementHandle_t h ) { return m_Elements.Next( h ); } Element_t GetElement( ElementHandle_t h ) { return m_Elements[h]; } ElementHandle_t InvalidElementHandle() { return m_Elements.InvalidIndex(); } // Add an element to the the bucket specified by sortID void AddElement( int sortID, Element_t elem ) { // Allocate an element to stick this in. unsigned short elemID = m_Elements.Alloc( true ); m_Elements[elemID] = elem; if( m_MaterialSortInfoArray[sortID].m_FlushCount != m_FlushCount ) { // This is the first element that has used this sort id since flush. // FLASHLIGHTFIXME: need to sort these by vertex format when shoving // them into this list! // Mark this sortID as having been used since the last flush. m_MaterialSortInfoArray[sortID].m_FlushCount = m_FlushCount; // Add this sortID to the list of sortIDs used since flush. m_UsedSortIDs.AddToTail( sortID ); // Set the head pointer for this sort id to this element. m_MaterialSortInfoArray[sortID].m_Head = elemID; } else { // We already have an element in this sort id since flush, so chain // into thelist of elements for this sort id. m_Elements.LinkBefore( m_MaterialSortInfoArray[sortID].m_Head, elemID ); m_MaterialSortInfoArray[sortID].m_Head = elemID; } } private: struct MaterialSortInfo_t { MaterialSortInfo_t() : m_FlushCount( -1 ), m_Head( (unsigned short)-1 ) // i.e., InvalidIndex() { } int m_FlushCount; unsigned short m_Head; }; // This is a list of material sort info ids that have been used since flush. CUtlLinkedList m_UsedSortIDs; // This is m_NumMaterialSortIDs big. CUtlVector m_MaterialSortInfoArray; // This is used in multilist mode to make elements that belong in the multiple lists of CUtlLinkedList m_Elements; int m_FlushCount; }; #endif // MATERIALBUCKETS_H