mirror of
				https://github.com/intel/intel-graphics-compiler.git
				synced 2025-10-30 08:18:26 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			421 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			421 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*========================== begin_copyright_notice ============================
 | |
| 
 | |
| Copyright (C) 2019-2021 Intel Corporation
 | |
| 
 | |
| SPDX-License-Identifier: MIT
 | |
| 
 | |
| ============================= end_copyright_notice ===========================*/
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "Array.h"
 | |
| #include "Buffer.h"
 | |
| #include "utility.h"
 | |
| #include "MemCopy.h"
 | |
| 
 | |
| namespace iSTD
 | |
| {
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Class:
 | |
|     CStream
 | |
| 
 | |
| Description:
 | |
|     Allocates and manages a system memory buffer of unknown size
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| class CStream : public CObject<CAllocatorType>
 | |
| {
 | |
| public:
 | |
| 
 | |
|     CStream( void );
 | |
|     virtual ~CStream( void );
 | |
| 
 | |
|     void*   GetSpace( const DWORD dwSize );
 | |
|     void*   GetLinearAddress( void );
 | |
|     DWORD   GetUsedSpace( void ) const;
 | |
|     void    SetUsedSpace( DWORD currentSizeUsed );
 | |
|     void    PutAllSpace( void );
 | |
| 
 | |
|     void*   GetSegmentAddress( const DWORD offset, const DWORD size ) const;
 | |
| 
 | |
| protected:
 | |
| 
 | |
|     CDynamicArray<CBuffer<CAllocatorType>*,CAllocatorType> m_StreamArray;
 | |
| 
 | |
|     CBuffer<CAllocatorType>*    m_pCurrentBuffer;
 | |
|     DWORD                       m_StreamBufferCount;
 | |
|     CBuffer<CAllocatorType>*    m_pStreamBuffer;
 | |
|     DWORD                       m_dwSizeUsed;
 | |
| };
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream Constructor
 | |
| 
 | |
| Description:
 | |
|     Initializes internal data
 | |
| 
 | |
| Input:
 | |
|     none
 | |
| 
 | |
| Output:
 | |
|     none
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline CStream<CAllocatorType>::CStream( void )
 | |
|     : CObject<CAllocatorType>(),
 | |
|       m_StreamArray(0)
 | |
| {
 | |
|     m_pCurrentBuffer = NULL;
 | |
|     m_StreamBufferCount = 0;
 | |
|     m_pStreamBuffer = NULL;
 | |
|     m_dwSizeUsed = 0;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream Destructor
 | |
| 
 | |
| Description:
 | |
|     Deletes internal data
 | |
| 
 | |
| Input:
 | |
|     none
 | |
| 
 | |
| Output:
 | |
|     none
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline CStream<CAllocatorType>::~CStream( void )
 | |
| {
 | |
|     const DWORD dwCount = m_StreamArray.GetSize();
 | |
|     for( DWORD i = 0; i < dwCount; i++ )
 | |
|     {
 | |
|         CBuffer<CAllocatorType>* pBuffer = m_StreamArray.GetElement(i);
 | |
|         SafeDelete( pBuffer );
 | |
|     }
 | |
| 
 | |
|     SafeDelete( m_pStreamBuffer );
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream::GetSpace
 | |
| 
 | |
| Description:
 | |
|     Gets space from the stream
 | |
| 
 | |
| Input:
 | |
|     const DWORD dwSize - size in bytes
 | |
| 
 | |
| Output:
 | |
|     void* - linear address of space
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline void* CStream<CAllocatorType>::GetSpace( const DWORD dwSize )
 | |
| {
 | |
|     // If this is the first GetSpace call, or
 | |
|     if( ( !m_pCurrentBuffer ) ||
 | |
|         // the size requested is larger than the size available
 | |
|         ( dwSize > m_pCurrentBuffer->GetAvailableSpace() ) )
 | |
|     {
 | |
|         // Create a new buffer large enough for the requested size
 | |
|         m_pCurrentBuffer = new CBuffer<CAllocatorType>();
 | |
|         ASSERT( m_pCurrentBuffer );
 | |
| 
 | |
|         if( m_pCurrentBuffer &&
 | |
|             m_pCurrentBuffer->Allocate( Max( (DWORD)0x1000, dwSize ), sizeof(DWORD) ) )
 | |
|         {
 | |
|             // Add the buffer to the array of buffers
 | |
|             if( m_StreamArray.SetElement( m_StreamBufferCount, m_pCurrentBuffer ) )
 | |
|             {
 | |
|                 // Keep track of the number of buffers in the array
 | |
|                 m_StreamBufferCount++;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 ASSERT(0);
 | |
|                 SafeDelete( m_pCurrentBuffer );
 | |
|                 m_pCurrentBuffer = NULL;
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             ASSERT(0);
 | |
|             SafeDelete( m_pCurrentBuffer );
 | |
|             m_pCurrentBuffer = NULL;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if( m_pCurrentBuffer )
 | |
|     {
 | |
|         // Keep track of the total size of all buffers
 | |
|         m_dwSizeUsed += dwSize;
 | |
|         return m_pCurrentBuffer->GetSpace( dwSize );
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         return NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream::GetLinearAddress
 | |
| 
 | |
| Description:
 | |
|     Gets the contiguous linear address of the entire stream
 | |
| 
 | |
| Input:
 | |
|     none
 | |
| 
 | |
| Output:
 | |
|     void* - linear address
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline void* CStream<CAllocatorType>::GetLinearAddress( void )
 | |
| {
 | |
|     // If there are buffers in the array that have not yet been combined
 | |
|     if( m_StreamBufferCount )
 | |
|     {
 | |
|         // Create a new stream buffer large enough for all buffers
 | |
|         CBuffer<CAllocatorType>* pStreamBuffer = new CBuffer<CAllocatorType>();
 | |
|         ASSERT( pStreamBuffer );
 | |
| 
 | |
|         if( pStreamBuffer &&
 | |
|             pStreamBuffer->Allocate( m_dwSizeUsed, sizeof(DWORD) ) )
 | |
|         {
 | |
|             // If there already exists another stream buffer
 | |
|             if( m_pStreamBuffer )
 | |
|             {
 | |
|                 // Add the contents of the previous buffer to the new one
 | |
|                 MemCopy(
 | |
|                     pStreamBuffer->GetSpace( m_pStreamBuffer->GetUsedSpace() ),
 | |
|                     m_pStreamBuffer->GetLinearAddress(),
 | |
|                     m_pStreamBuffer->GetUsedSpace() );
 | |
| 
 | |
|                 SafeDelete( m_pStreamBuffer );
 | |
|             }
 | |
| 
 | |
|             // For each buffer in the buffer array
 | |
|             for( DWORD i = 0; i < m_StreamBufferCount; i++ )
 | |
|             {
 | |
|                 CBuffer<CAllocatorType>* pBuffer = m_StreamArray.GetElement(i);
 | |
| 
 | |
|                 if( pBuffer )
 | |
|                 {
 | |
|                     // Append the contents of the buffers to the stream buffer
 | |
|                     MemCopy(
 | |
|                         pStreamBuffer->GetSpace( pBuffer->GetUsedSpace() ),
 | |
|                         pBuffer->GetLinearAddress(),
 | |
|                         pBuffer->GetUsedSpace() );
 | |
| 
 | |
|                     SafeDelete( pBuffer );
 | |
| 
 | |
|                     // Remove the buffer from the array
 | |
|                     m_StreamArray.SetElement( i, NULL );
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             m_pCurrentBuffer = NULL;
 | |
|             m_StreamBufferCount = 0;
 | |
|             m_pStreamBuffer = pStreamBuffer;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             ASSERT(0);
 | |
|             SafeDelete( pStreamBuffer );
 | |
|             pStreamBuffer = NULL;
 | |
| 
 | |
|             // If we fail to recombine the buffers into a single linear allocation
 | |
|             // then return NULL to indicate the failure
 | |
|             return NULL;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return ( m_pStreamBuffer )
 | |
|            ? m_pStreamBuffer->GetLinearAddress()
 | |
|            : NULL;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream::GetUsedSpace
 | |
| 
 | |
| Description:
 | |
|     Gets the current size of the stream
 | |
| 
 | |
| Input:
 | |
|     none
 | |
| 
 | |
| Output:
 | |
|     DWORD - size in bytes
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline DWORD CStream<CAllocatorType>::GetUsedSpace( void ) const
 | |
| {
 | |
|     return m_dwSizeUsed;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream::SetUsedSpace
 | |
| 
 | |
| Description:
 | |
|     Sets the current size of the stream.
 | |
|     Function should be used only to sets smaller size.
 | |
| 
 | |
| Input:
 | |
|     DWORD - size in bytes
 | |
| 
 | |
| Output:
 | |
|     none
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline void CStream<CAllocatorType>::SetUsedSpace( DWORD currentSizeUsed )
 | |
| {
 | |
|     ASSERT( currentSizeUsed == 0 );
 | |
|     ASSERT( currentSizeUsed < m_dwSizeUsed );
 | |
| 
 | |
|     m_dwSizeUsed = currentSizeUsed;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream::PutAllSpace
 | |
| 
 | |
| Description:
 | |
|     Puts all space back into the CStream.  All space becomes unused.
 | |
| 
 | |
| Input:
 | |
|     none
 | |
| 
 | |
| Output:
 | |
|     none
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline void CStream<CAllocatorType>::PutAllSpace( void )
 | |
| {
 | |
|     const DWORD dwCount = m_StreamArray.GetSize();
 | |
| 
 | |
|     for( DWORD i = 0; i < dwCount; i++ )
 | |
|     {
 | |
|         CBuffer<CAllocatorType>* pBuffer = m_StreamArray.GetElement(i);
 | |
|         if( pBuffer )
 | |
|         {
 | |
|             pBuffer->PutAllSpace();
 | |
|         }
 | |
|     }
 | |
|     m_dwSizeUsed = 0;
 | |
|     
 | |
|     if( m_pStreamBuffer )
 | |
|     {
 | |
|         m_pStreamBuffer->PutAllSpace();
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*****************************************************************************\
 | |
| 
 | |
| Function:
 | |
|     CStream::GetSegmentAddress
 | |
| 
 | |
| Description:
 | |
|     Gets the contiguous linear address a segment of the stream
 | |
| 
 | |
| Input:
 | |
|     const DWORD offset - the offset in the stream of the segment
 | |
|     const DWORD size - the size in bytes of the segment
 | |
| 
 | |
| Output:
 | |
|     void* - linear address
 | |
| 
 | |
| Notes:
 | |
|     The address returned is only valid for the segment requested. It should
 | |
|     not be expected that memory access outside the returned segment is valid.
 | |
| 
 | |
|     If a segment straddles more than one stream buffer, then the request will
 | |
|     fail.  This condition will not happen as long as the user accesses segments
 | |
|     in the same location and size in which they were added to the stream using
 | |
|     GetSpace calls.
 | |
| 
 | |
| \*****************************************************************************/
 | |
| template<class CAllocatorType>
 | |
| inline void* CStream<CAllocatorType>::GetSegmentAddress(
 | |
|     const DWORD offset,
 | |
|     const DWORD size ) const
 | |
| {
 | |
|     DWORD currentOffset = offset;
 | |
| 
 | |
|     if( m_pStreamBuffer )
 | |
|     {
 | |
|         if( currentOffset < m_pStreamBuffer->GetUsedSpace() )
 | |
|         {
 | |
|             if( ( currentOffset + size ) <= m_pStreamBuffer->GetUsedSpace() )
 | |
|             {
 | |
|                 return (BYTE*)m_pStreamBuffer->GetLinearAddress() + offset;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // The offset is within the buffer, but the size requested
 | |
|                 // is too large for a contiguous address
 | |
|                 ASSERT(0);
 | |
|                 return NULL;
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             currentOffset -= m_pStreamBuffer->GetUsedSpace();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for( DWORD i = 0; i < m_StreamBufferCount; i++ )
 | |
|     {
 | |
|         CBuffer<CAllocatorType>* pBuffer = m_StreamArray.GetElement(i);
 | |
| 
 | |
|         if( pBuffer )
 | |
|         {
 | |
|             if( currentOffset < pBuffer->GetUsedSpace() )
 | |
|             {
 | |
|                 if( ( currentOffset + size ) <= pBuffer->GetUsedSpace() )
 | |
|                 {
 | |
|                     return (BYTE*)pBuffer->GetLinearAddress() + currentOffset;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     // The offset is within the buffer, but the size requested
 | |
|                     // is too large for a contiguous address
 | |
|                     ASSERT(0);
 | |
|                     return NULL;
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 currentOffset -= pBuffer->GetUsedSpace();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // offset not found
 | |
|     ASSERT(0);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| } // iSTD
 | 
