summaryrefslogtreecommitdiffstats
path: root/source/core/slang-free-list.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-04-02 19:59:33 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-04-02 16:59:33 -0700
commit38d5ef4764e9271ce2360f42b0759a236cddd9fe (patch)
tree6c8eafb72eb997167dd77e3d1d5abc3582c5789a /source/core/slang-free-list.cpp
parent5a0273848aa4b854bb3c99a81701b044a8929bf8 (diff)
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
Diffstat (limited to 'source/core/slang-free-list.cpp')
-rw-r--r--source/core/slang-free-list.cpp216
1 files changed, 216 insertions, 0 deletions
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
+