From 38d5ef4764e9271ce2360f42b0759a236cddd9fe Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Mon, 2 Apr 2018 19:59:33 -0400 Subject: Feature/dx12 (#469) * Fix signed/unsigned comparison warning. * Split out d3d functions that will work across dx11 and 12. * Improve slang-test/README.md around command line options. * Make Guid comparison honor alignment for comparisons, such that mechanism work on architectures that can only do aligned accesses. * Initial setup of D3D12 Renderer, with presentFrame and clearFrame. * More support for D3D12 * Added FreeList * Added D3D12CircularResourceHeap * First attempt at createBuffer * First pass at map/unmap. * First pass binding vertex/constant buffers, and setting up InputLayout. Note that memory is not kept in scope on binding yet. * First pass of D3DDescriptorHeap * Small tidy up in render-d3d11. Added D3DDescriptorHeap to project. * First pass at D3D12 bind state. * Fix typos in D3D12Resource * Tidy up Dx11 render binding a little to match more with Dx12 style. * First pass at Dx12 BindingState * Handling of the command list d3d12. Support for submitGpuWork and waitForGpu. * First attempt at Dx12 capture of backbuffer to file. * First attempt at D3D12 binding for graphics. * D3D12 setup viewport etc - does now render triangle in render0.hlsl. * First pass at support for compute on D3D12Renderer * Use spaces over tabs in D3DUtil * Tabs to spaces in D3D12DescriptorHeap * Convert tab->spaces on render-d3d12.cpp --- source/core/slang-free-list.cpp | 216 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 source/core/slang-free-list.cpp (limited to 'source/core/slang-free-list.cpp') diff --git a/source/core/slang-free-list.cpp b/source/core/slang-free-list.cpp new file mode 100644 index 000000000..0701558aa --- /dev/null +++ b/source/core/slang-free-list.cpp @@ -0,0 +1,216 @@ +#include "slang-free-list.h" + +//#include "list.h" + +namespace Slang { + +FreeList::~FreeList() +{ + _deallocateBlocks(m_activeBlocks); + _deallocateBlocks(m_freeBlocks); +} + +void FreeList::_init() +{ + m_top = nullptr; + m_end = nullptr; + + m_activeBlocks = nullptr; + m_freeBlocks = nullptr; + + m_freeElements = nullptr; + + m_elementSize = 0; + m_alignment = 1; + m_blockSize = 0; + m_blockAllocationSize = 0; +} + +void FreeList::_init(size_t elementSize, size_t alignment, size_t elemsPerBlock) +{ + alignment = (alignment < sizeof(void*)) ? sizeof(void*) : alignment; + + // Alignment must be a power of 2 + assert(((alignment - 1) & alignment) == 0); + + // The elementSize must at least be + elementSize = (elementSize >= alignment) ? elementSize : alignment; + m_blockSize = elementSize * elemsPerBlock; + m_elementSize = elementSize; + m_alignment = alignment; + + // Calculate the block size need, correcting for alignment + const size_t alignedBlockSize = (alignment <= DEFAULT_ALIGNMENT) ? + _calcAlignedBlockSize(DEFAULT_ALIGNMENT) : + _calcAlignedBlockSize(alignment); + + // Make the block struct size aligned + m_blockAllocationSize = m_blockSize + alignedBlockSize; + + m_top = nullptr; + m_end = nullptr; + + m_activeBlocks = nullptr; + m_freeBlocks = nullptr; ///< Blocks that there are no allocations in + + m_freeElements = nullptr; +} + +void FreeList::init(size_t elementSize, size_t alignment, size_t elemsPerBlock) +{ + _deallocateBlocks(m_activeBlocks); + _deallocateBlocks(m_freeBlocks); + _init(elementSize, alignment, elemsPerBlock); +} + +void FreeList::_deallocateBlocks(Block* block) +{ + while (block) + { + Block* next = block->m_next; + +#ifdef SLANG_FREE_LIST_INIT_MEM + Memory::set(block, 0xfd, m_blockAllocationSize); +#endif + + ::free(block); // deallocate(block, m_blockAllocationSize); + block = next; + } +} + +bool FreeList::isValidAllocation(const void* dataIn) const +{ + uint8_t* data = (uint8_t*)dataIn; + + Block* block = m_activeBlocks; + while (block) + { + uint8_t* start = block->m_data; + uint8_t* end = start + m_blockSize; + + if (data >= start && data < end) + { + // Check it's aligned correctly + if ((data - start) % m_elementSize) + { + return false; + } + + // Non allocated data is between top and end + if (data >= m_top && data < m_end) + { + return false; + } + + // It can't be in the free list + Element* ele = m_freeElements; + while (ele) + { + if (ele == (Element*)data) + { + return false; + } + + ele = ele->m_next; + } + return true; + } + + block = block->m_next; + } + // It's not in an active block -> it cannot be a valid allocation + return false; +} + +void* FreeList::_allocate() +{ + Block* block = m_freeBlocks; + if (block) + { + /// Remove from the free blocks + m_freeBlocks = block->m_next; + } + else + { + //block = (Block*)m_allocator->allocate(m_blockAllocationSize); + block = (Block*)::malloc(m_blockAllocationSize); + if (!block) + { + // Allocation failed... doh + return nullptr; + } + // Do the alignment + { + size_t fix = (size_t(block) + sizeof(Block) + m_alignment - 1) & ~(m_alignment - 1); + block->m_data = (uint8_t*)fix; + } + } + + // Attach to the active blocks + block->m_next = m_activeBlocks; + m_activeBlocks = block; + + // Set up top and end + m_end = block->m_data + m_blockSize; + + // Return the first element + uint8_t* element = block->m_data; + m_top = element + m_elementSize; + + SLANG_FREE_LIST_INIT_ALLOCATE(element) + + return element; +} + +void FreeList::deallocateAll() +{ + Block* block = m_activeBlocks; + if (block) + { + // Find the end block + while (block->m_next) + { +#ifdef SLANG_FREE_LIST_INIT_MEM + Memory::set(block->m_data, 0xfd, m_blockSize); +#endif + block = block->m_next; + } + // Attach to the freeblocks + block->m_next = m_freeBlocks; + // The list is now all freelists + m_freeBlocks = m_activeBlocks; + // There are no active blocks + m_activeBlocks = nullptr; + } + + m_top = nullptr; + m_end = nullptr; +} + +void FreeList::reset() +{ + _deallocateBlocks(m_activeBlocks); + _deallocateBlocks(m_freeBlocks); + + m_top = nullptr; + m_end = nullptr; + + m_activeBlocks = nullptr; + m_freeBlocks = nullptr; + + m_freeElements = nullptr; +} + + +void FreeList::_initAllocate(void* mem) +{ + ::memset(mem, 0xcd, m_elementSize); +} + +void FreeList::_initDeallocate(void* mem) +{ + ::memset(mem, 0xfd, m_elementSize); +} + +} // namespace Slang + -- cgit v1.2.3