yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
7b570feed
master
1#include "core/slang-basic.h" 2#include "renderer-shared.h" 3 4namespace gfx 5{ 6template < typename TDevice ,typename TBufferResource > 7class StagingBufferPool 8{ 9public : 10struct StagingBufferPage 11 { 12Slang ::RefPtr < TBufferResource > resource ; 13size_t size ; 14 }; 15 16struct Allocation 17{ 18TBufferResource * resource ; 19size_t offset ; 20}; 21 22TDevice * m_device; 23MemoryType m_memoryType; 24uint32_t m_alignment; 25ResourceStateSet m_allowedStates; 26 27Slang ::List < StagingBufferPage > m_pages; 28Slang ::List < Slang::RefPtr < TBufferResource>> m_largeAllocations; 29 30Slang :: Index m_pageAllocCounter = 0 ; 31size_t m_offsetAllocCounter = 0 ; 32 33const size_t kStagingBufferDefaultPageSize = 16 * 1024 * 1024 ; 34 35void init ( 36TDevice * device, 37MemoryType memoryType, 38uint32_t alignment, 39ResourceStateSet allowedStates) 40{ 41m_device = device; 42m_memoryType = memoryType; 43m_alignment = alignment; 44m_allowedStates = allowedStates; 45} 46 47static size_t alignUp ( size_t value, uint32_t alignment) 48{ 49return (value + alignment - 1 ) / alignment * alignment; 50} 51 52void reset () 53{ 54m_pageAllocCounter = 0 ; 55m_offsetAllocCounter = 0 ; 56m_largeAllocations. clearAndDeallocate (); 57} 58 59Result newStagingBufferPage () 60{ 61StagingBufferPage page; 62size_t pageSize = kStagingBufferDefaultPageSize; 63 64Slang ::ComPtr < IBufferResource > bufferPtr; 65IBufferResource :: Desc bufferDesc; 66bufferDesc. type = IResource:: Type ::Buffer; 67bufferDesc. defaultState = ResourceState::General; 68bufferDesc. allowedStates = m_allowedStates; 69bufferDesc. memoryType = m_memoryType; 70bufferDesc. sizeInBytes = pageSize; 71SLANG_RETURN_ON_FAIL ( 72m_device -> createBufferResource (bufferDesc, nullptr , bufferPtr. writeRef ())); 73 74page. resource = static_cast < TBufferResource *> (bufferPtr. get ()); 75page. size = pageSize; 76m_pages. add (page); 77return SLANG_OK ; 78} 79 80Result newLargeBuffer ( size_t size) 81{ 82Slang ::ComPtr < IBufferResource > bufferPtr; 83IBufferResource :: Desc bufferDesc; 84bufferDesc. type = IResource:: Type ::Buffer; 85bufferDesc. defaultState = ResourceState::General; 86bufferDesc. allowedStates = m_allowedStates; 87bufferDesc. memoryType = m_memoryType; 88bufferDesc. sizeInBytes = size; 89SLANG_RETURN_ON_FAIL ( 90m_device -> createBufferResource (bufferDesc, nullptr , bufferPtr. writeRef ())); 91auto bufferImpl = static_cast < TBufferResource *> (bufferPtr. get ()); 92m_largeAllocations. add (bufferImpl); 93return SLANG_OK ; 94} 95 96Allocation allocate ( size_t size, bool forceLargePage) 97{ 98if (forceLargePage || size >= (kStagingBufferDefaultPageSize >> 2 )) 99{ 100newLargeBuffer (size); 101Allocation result; 102result. resource = m_largeAllocations. getLast (); 103result. offset = 0 ; 104return result; 105} 106 107size_t bufferAllocOffset = alignUp (m_offsetAllocCounter, m_alignment); 108Slang :: Index bufferId = -1 ; 109for ( Slang ::Index i = m_pageAllocCounter; i < m_pages. getCount (); i ++ ) 110{ 111auto cb = m_pages[i]. resource . Ptr (); 112if (bufferAllocOffset + size <= cb -> getDesc () -> sizeInBytes ) 113{ 114bufferId = i; 115break ; 116} 117bufferAllocOffset = 0 ; 118} 119// If we cannot find an existing page with sufficient free space, 120// create a new page. 121if (bufferId == -1 ) 122{ 123newStagingBufferPage (); 124bufferId = m_pages. getCount () - 1 ; 125} 126// Sub allocate from current page. 127Allocation result; 128result. resource = m_pages[bufferId]. resource . Ptr (); 129result. offset = bufferAllocOffset; 130m_pageAllocCounter = bufferId; 131m_offsetAllocCounter = bufferAllocOffset + size; 132return result; 133} 134}; 135 136template < typename TDevice, typename TBufferResource > 137class TransientResourceHeapBaseImpl : public TransientResourceHeapBase 138{ 139public : 140void breakStrongReferenceToDevice () { m_device. breakStrongReference (); } 141 142public : 143BreakableReference < TDevice > m_device; 144StagingBufferPool < TDevice, TBufferResource > m_constantBufferPool; 145StagingBufferPool < TDevice, TBufferResource > m_uploadBufferPool; 146StagingBufferPool < TDevice, TBufferResource > m_readbackBufferPool; 147 148Result init ( const ITransientResourceHeap ::Desc & desc, uint32_t alignment, TDevice * device) 149{ 150m_device = device; 151 152m_constantBufferPool. init ( 153device, 154MemoryType::Upload, 155256 , 156ResourceStateSet ( 157ResourceState::ConstantBuffer, 158ResourceState::CopySource, 159ResourceState::CopyDestination)); 160 161m_uploadBufferPool. init ( 162device, 163MemoryType::Upload, 164256 , 165ResourceStateSet (ResourceState::CopySource, ResourceState::CopyDestination)); 166 167m_readbackBufferPool. init ( 168device, 169MemoryType::ReadBack, 170256 , 171ResourceStateSet (ResourceState::CopySource, ResourceState::CopyDestination)); 172 173m_version = getVersionCounter (); 174getVersionCounter () ++ ; 175return SLANG_OK ; 176} 177 178Result allocateStagingBuffer ( 179size_t size, 180IBufferResource *& outBufferWeakPtr, 181size_t & offset, 182MemoryType memoryType, 183bool forceLargePage = false) 184{ 185switch (memoryType) 186{ 187case MemoryType ::ReadBack: 188{ 189auto allocation = m_readbackBufferPool. allocate (size, forceLargePage); 190outBufferWeakPtr = allocation. resource ; 191offset = allocation. offset ; 192} 193break; 194default : 195{ 196auto allocation = m_uploadBufferPool. allocate (size, forceLargePage); 197outBufferWeakPtr = allocation. resource ; 198offset = allocation. offset ; 199} 200break; 201} 202return SLANG_OK ; 203} 204 205Result allocateConstantBuffer ( 206size_t size, 207IBufferResource *& outBufferWeakPtr, 208size_t & outOffset) 209{ 210auto allocation = m_constantBufferPool. allocate (size, false); 211outBufferWeakPtr = allocation. resource ; 212outOffset = allocation. offset ; 213return SLANG_OK ; 214} 215 216void reset () 217{ 218m_constantBufferPool. reset (); 219m_uploadBufferPool. reset (); 220m_readbackBufferPool. reset (); 221m_version = getVersionCounter (); 222getVersionCounter () ++ ; 223} 224}; 225 226} // namespace gfx