mirror of
				https://github.com/intel/intel-graphics-compiler.git
				synced 2025-11-04 08:21:06 +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
 |