Update MVKSmallVector constructors, and remove unnecessary or obsolete code.

MVKSmallVector allow constructor to size with default values.
Remove obsolete MVKVector, which was long ago replaced with MVKSmallVector.
Remove unnecessary concrete implementations of template functions that are
used only within a single compilation unit.
diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
index 8ada11b..bf220a0 100644
--- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
+++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
@@ -27,13 +27,11 @@
 		2FEA0A5224902F9F00EEF3AD /* MVKLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */; };
 		2FEA0A5324902F9F00EEF3AD /* MVKQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7911C7DFB4800632CA3 /* MVKQueue.h */; };
 		2FEA0A5424902F9F00EEF3AD /* MVKFramebuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7871C7DFB4800632CA3 /* MVKFramebuffer.h */; };
-		2FEA0A5524902F9F00EEF3AD /* MVKVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A4AD2921BD75570006C935 /* MVKVectorAllocator.h */; };
 		2FEA0A5624902F9F00EEF3AD /* MVKWatermarkShaderSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A981494B1FB6A3F7005F00B4 /* MVKWatermarkShaderSource.h */; };
 		2FEA0A5724902F9F00EEF3AD /* MTLSamplerDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E53DD32100B197002781DD /* MTLSamplerDescriptor+MoltenVK.h */; };
 		2FEA0A5824902F9F00EEF3AD /* MVKSync.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB79D1C7DFB4800632CA3 /* MVKSync.h */; };
 		2FEA0A5924902F9F00EEF3AD /* MVKDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7831C7DFB4800632CA3 /* MVKDevice.h */; };
 		2FEA0A5A24902F9F00EEF3AD /* MVKSmallVector.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */; };
-		2FEA0A5B24902F9F00EEF3AD /* MVKVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A4AD2521BD75570006C935 /* MVKVector.h */; };
 		2FEA0A5C24902F9F00EEF3AD /* MVKCommandPool.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB77A1C7DFB4800632CA3 /* MVKCommandPool.h */; };
 		2FEA0A5D24902F9F00EEF3AD /* MVKShaderModule.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7971C7DFB4800632CA3 /* MVKShaderModule.h */; };
 		2FEA0A5E24902F9F00EEF3AD /* MVKVulkanAPIObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A99C91012295FAC500A061DA /* MVKVulkanAPIObject.h */; };
@@ -142,10 +140,6 @@
 		45557A5321C9EFF3008868BD /* MVKCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.cpp */; };
 		45557A5421C9EFF3008868BD /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; };
 		45557A5521C9EFF3008868BD /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; };
-		83A4AD2A21BD75570006C935 /* MVKVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A4AD2521BD75570006C935 /* MVKVector.h */; };
-		83A4AD2B21BD75570006C935 /* MVKVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A4AD2521BD75570006C935 /* MVKVector.h */; };
-		83A4AD2C21BD75570006C935 /* MVKVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A4AD2921BD75570006C935 /* MVKVectorAllocator.h */; };
-		83A4AD2D21BD75570006C935 /* MVKVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A4AD2921BD75570006C935 /* MVKVectorAllocator.h */; };
 		A9096E5E1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */; };
 		A9096E5F1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */; };
 		A909F65F213B190700FCD6BE /* MVKExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A909F65A213B190600FCD6BE /* MVKExtensions.h */; };
@@ -428,8 +422,6 @@
 		45557A4D21C9EFF3008868BD /* MVKCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKCodec.cpp; sourceTree = "<group>"; };
 		45557A5121C9EFF3008868BD /* MVKCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCodec.h; sourceTree = "<group>"; };
 		45557A5721CD83C3008868BD /* MVKDXTnCodec.def */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = MVKDXTnCodec.def; sourceTree = "<group>"; };
-		83A4AD2521BD75570006C935 /* MVKVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKVector.h; sourceTree = "<group>"; };
-		83A4AD2921BD75570006C935 /* MVKVectorAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKVectorAllocator.h; sourceTree = "<group>"; };
 		A9096E5C1F81E16300DFBEA6 /* MVKCmdDispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVKCmdDispatch.h; sourceTree = "<group>"; };
 		A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdDispatch.mm; sourceTree = "<group>"; };
 		A909F65A213B190600FCD6BE /* MVKExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKExtensions.h; sourceTree = "<group>"; };
@@ -693,8 +685,6 @@
 				A98149461FB6A3F7005F00B4 /* MVKObjectPool.h */,
 				A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */,
 				A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */,
-				83A4AD2521BD75570006C935 /* MVKVector.h */,
-				83A4AD2921BD75570006C935 /* MVKVectorAllocator.h */,
 				A98149491FB6A3F7005F00B4 /* MVKWatermark.h */,
 				A981494A1FB6A3F7005F00B4 /* MVKWatermark.mm */,
 				A981494B1FB6A3F7005F00B4 /* MVKWatermarkShaderSource.h */,
@@ -809,13 +799,11 @@
 				2FEA0A5224902F9F00EEF3AD /* MVKLogging.h in Headers */,
 				2FEA0A5324902F9F00EEF3AD /* MVKQueue.h in Headers */,
 				2FEA0A5424902F9F00EEF3AD /* MVKFramebuffer.h in Headers */,
-				2FEA0A5524902F9F00EEF3AD /* MVKVectorAllocator.h in Headers */,
 				2FEA0A5624902F9F00EEF3AD /* MVKWatermarkShaderSource.h in Headers */,
 				2FEA0A5724902F9F00EEF3AD /* MTLSamplerDescriptor+MoltenVK.h in Headers */,
 				2FEA0A5824902F9F00EEF3AD /* MVKSync.h in Headers */,
 				2FEA0A5924902F9F00EEF3AD /* MVKDevice.h in Headers */,
 				2FEA0A5A24902F9F00EEF3AD /* MVKSmallVector.h in Headers */,
-				2FEA0A5B24902F9F00EEF3AD /* MVKVector.h in Headers */,
 				2FEA0A5C24902F9F00EEF3AD /* MVKCommandPool.h in Headers */,
 				2FEA0A5D24902F9F00EEF3AD /* MVKShaderModule.h in Headers */,
 				2FEA0A5E24902F9F00EEF3AD /* MVKVulkanAPIObject.h in Headers */,
@@ -883,13 +871,11 @@
 				453638322508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */,
 				A94FB8001C7DFB4800632CA3 /* MVKQueue.h in Headers */,
 				A94FB7EC1C7DFB4800632CA3 /* MVKFramebuffer.h in Headers */,
-				83A4AD2C21BD75570006C935 /* MVKVectorAllocator.h in Headers */,
 				A98149611FB6A3F7005F00B4 /* MVKWatermarkShaderSource.h in Headers */,
 				A9E53DE32100B197002781DD /* MTLSamplerDescriptor+MoltenVK.h in Headers */,
 				A94FB8181C7DFB4800632CA3 /* MVKSync.h in Headers */,
 				A94FB7E41C7DFB4800632CA3 /* MVKDevice.h in Headers */,
 				A9F3D9DE24732A4D00745190 /* MVKSmallVector.h in Headers */,
-				83A4AD2A21BD75570006C935 /* MVKVector.h in Headers */,
 				A94FB7D41C7DFB4800632CA3 /* MVKCommandPool.h in Headers */,
 				A94FB80C1C7DFB4800632CA3 /* MVKShaderModule.h in Headers */,
 				A99C91042295FAC600A061DA /* MVKVulkanAPIObject.h in Headers */,
@@ -957,13 +943,11 @@
 				453638342508A4C7000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.h in Headers */,
 				A94FB8011C7DFB4800632CA3 /* MVKQueue.h in Headers */,
 				A94FB7ED1C7DFB4800632CA3 /* MVKFramebuffer.h in Headers */,
-				83A4AD2D21BD75570006C935 /* MVKVectorAllocator.h in Headers */,
 				A98149621FB6A3F7005F00B4 /* MVKWatermarkShaderSource.h in Headers */,
 				A9E53DE42100B197002781DD /* MTLSamplerDescriptor+MoltenVK.h in Headers */,
 				A94FB8191C7DFB4800632CA3 /* MVKSync.h in Headers */,
 				A94FB7E51C7DFB4800632CA3 /* MVKDevice.h in Headers */,
 				A9F3D9DF24732A4D00745190 /* MVKSmallVector.h in Headers */,
-				83A4AD2B21BD75570006C935 /* MVKVector.h in Headers */,
 				A94FB7D51C7DFB4800632CA3 /* MVKCommandPool.h in Headers */,
 				A94FB80D1C7DFB4800632CA3 /* MVKShaderModule.h in Headers */,
 				A99C91052295FAC600A061DA /* MVKVulkanAPIObject.h in Headers */,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index 4b96552..609ec03 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -254,14 +254,6 @@
     }
 }
 
-// Create concrete implementations of the three variations of the write() function.
-template void MVKDescriptorSet::write<VkWriteDescriptorSet>(const VkWriteDescriptorSet* pDescriptorAction,
-															size_t stride, const void *pData);
-template void MVKDescriptorSet::write<VkCopyDescriptorSet>(const VkCopyDescriptorSet* pDescriptorAction,
-														   size_t stride, const void *pData);
-template void MVKDescriptorSet::write<VkDescriptorUpdateTemplateEntryKHR>(const VkDescriptorUpdateTemplateEntryKHR* pDescriptorAction,
-																		  size_t stride, const void *pData);
-
 void MVKDescriptorSet::read(const VkCopyDescriptorSet* pDescriptorCopy,
 							VkDescriptorImageInfo* pImageInfo,
 							VkDescriptorBufferInfo* pBufferInfo,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index aefc99a..b21afd3 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -1292,13 +1292,6 @@
 	return true;
 }
 
-template bool MVKGraphicsPipeline::addVertexInputToPipeline<MTLVertexDescriptor>(MTLVertexDescriptor* inputDesc,
-																				 const VkPipelineVertexInputStateCreateInfo* pVI,
-																				 const SPIRVToMSLConversionConfiguration& shaderContext);
-template bool MVKGraphicsPipeline::addVertexInputToPipeline<MTLStageInputOutputDescriptor>(MTLStageInputOutputDescriptor* inputDesc,
-																						   const VkPipelineVertexInputStateCreateInfo* pVI,
-																						   const SPIRVToMSLConversionConfiguration& shaderContext);
-
 // Adjusts step rates for per-instance vertex buffers based on the number of views to be drawn.
 void MVKGraphicsPipeline::adjustVertexInputForMultiview(MTLVertexDescriptor* inputDesc, const VkPipelineVertexInputStateCreateInfo* pVI, uint32_t viewCount, uint32_t oldViewCount) {
 	uint32_t vbCnt = pVI->vertexBindingDescriptionCount;
diff --git a/MoltenVK/MoltenVK/Utility/MVKSmallVector.h b/MoltenVK/MoltenVK/Utility/MVKSmallVector.h
index 895bb6e..4648d19 100755
--- a/MoltenVK/MoltenVK/Utility/MVKSmallVector.h
+++ b/MoltenVK/MoltenVK/Utility/MVKSmallVector.h
@@ -43,11 +43,11 @@
 // If you don't need any inline storage use:

 //  MVKSmallVector<int> v;   // this is essentially the same as using std::vector

 //

-// The per-instance memory overhead of MVKSmallVector (16 bytes) is smaller than MVKVector (40 bytes)

-// and std::vector (24 bytes), but MVKSmallVector lacks the polymorphism of MVKVector (or std::vector),

-// that allows them to be passed around to functions without reference to the pre-allocation size.

-// MVKSmallVector supports the contents() function to derive an MVKArrayRef from its contents,

-// which can be passed around without reference to the pre-allocaton size.

+// The per-instance memory overhead of MVKSmallVector (16 bytes) is smaller than std::vector

+// (24 bytes), but MVKSmallVector lacks the polymorphism of std::vector, that allows it to

+// be passed to functions without reference to the pre-allocation size. MVKSmallVector

+// supports the contents() function to derive an MVKArrayRef from its contents, which can

+// be passed to functions without reference to the MVKSmallVector pre-allocaton size.

 

 #include "MVKSmallVectorAllocator.h"

 #include "MVKFoundation.h"

@@ -138,7 +138,7 @@
   {

   }

 

-  MVKSmallVectorImpl( const size_t n, const Type t )

+  MVKSmallVectorImpl( const size_t n, const Type t = { } )

   {

     if( n > 0 )

     {

@@ -590,7 +590,7 @@
   {

   }

 

-  MVKSmallVectorImpl( const size_t n, const Type *t )

+  MVKSmallVectorImpl( const size_t n, Type *t = nullptr )

   {

     if ( n > 0 )

     {

diff --git a/MoltenVK/MoltenVK/Utility/MVKVector.h b/MoltenVK/MoltenVK/Utility/MVKVector.h
deleted file mode 100755
index 70bb415..0000000
--- a/MoltenVK/MoltenVK/Utility/MVKVector.h
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*

- * MVKVector.h

- *

- * Copyright (c) 2012-2021 Dr. Torsten Hans (hans@ipacs.de)

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- * 

- *     http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-#pragma once

-

-//

-// in case MVKVector should use std::vector

-//

-#if 0

-

-template<typename T, size_t N = 0>

-using MVKVectorInline = std::vector<T>;

-

-template<typename T>

-using MVKVectorDefault = std::vector<T>;

-

-template<typename T>

-using MVKVector = std::vector<T>;

-

-#else

-

-//

-// MVKVector.h is a sequence container that (optionally) implements a small

-// buffer optimization.

-// It behaves similarly to std::vector, except until a certain number of

-// elements are reserved, it does not use the heap.

-// Like std::vector, MVKVector is guaranteed to use contiguous memory, so if the

-// preallocated number of elements are exceeded, all elements are then in heap.

-// MVKVector supports just the necessary members to be compatible with MoltenVK

-// If C++17 will be the default in the future, code can be simplified quite a bit.

-//

-// Example:

-//

-//  MVKVectorInline<int, 3> vector;

-//  vector.emplace_back( 1 );

-//  vector.emplace_back( 2 );

-//  vector.emplace_back( 3 );

-//  // adding another element now reserves memory from heap

-//  vector.emplace_back( 4 );

-//

-// If you don't need any inline storage use

-//  MVKVectorDefault<int> vector;   // this is essentially the same as using std::vector

-//

-// Passing MVKVectorInline to a function would require to use the same template

-// parameters that have been used for declaration. To avoid this MVKVectorInline

-// is derived from MVKVector. If you want to pass MVKVectorInline to a function

-// use MVKVector.

-//

-#include "MVKVectorAllocator.h"

-#include "MVKFoundation.h"

-#include <type_traits>

-#include <initializer_list>

-#include <utility>

-

-

-template<class Type> class MVKVector

-{

-  mvk_vector_allocator_base<Type> *alc_ptr;

-

-public:

-  class iterator : public std::iterator<std::forward_iterator_tag, Type>

-  {

-    const MVKVector *vector;

-    size_t           index;

-

-  public:

-    iterator() = delete;

-    iterator( const size_t _index, const MVKVector &_vector ) : vector{ &_vector }, index{ _index } { }

-    iterator &operator=( const iterator &it ) = delete;

-

-    Type *operator->() const { return &vector->alc_ptr->ptr[index]; }

-    Type &operator*()  const { return  vector->alc_ptr->ptr[index]; }

-    operator Type*( )  const { return &vector->alc_ptr->ptr[index]; }

-

-    bool operator==( const iterator &it ) const { return vector == it.vector && index == it.index; }

-    bool operator!=( const iterator &it ) const { return vector != it.vector || index != it.index; }

-

-    iterator& operator++()      {                 ++index; return *this; }

-    iterator  operator++( int ) { auto t = *this; ++index; return t; }

-

-    bool   is_valid()     const { return index < vector->size(); }

-    size_t get_position() const { return index; }

-  };

-

-public:

-  typedef Type value_type;

-

-  MVKVector() = delete;

-  MVKVector( mvk_vector_allocator_base<Type> *a ) : alc_ptr{ a } { }

-  virtual ~MVKVector() { }

-

-  iterator begin() const { return iterator( 0,               *this ); }

-  iterator end()   const { return iterator( alc_ptr->size(), *this ); }

-

-  const MVKArrayRef<Type> contents() const { return MVKArrayRef<Type>(data(), size()); }

-        MVKArrayRef<Type> contents()       { return MVKArrayRef<Type>(data(), size()); }

-

-  virtual const Type &operator[]( const size_t i ) const                  = 0;

-  virtual       Type &operator[]( const size_t i )                        = 0;

-  virtual const Type &at( const size_t i ) const                          = 0;

-  virtual       Type &at( const size_t i )                                = 0;

-  virtual const Type &front() const                                       = 0;

-  virtual       Type &front()                                             = 0;

-  virtual const Type &back() const                                        = 0;

-  virtual       Type &back()                                              = 0;

-  virtual const Type *data() const                                        = 0;

-  virtual       Type *data()                                              = 0;

-

-  virtual size_t      size()     const                                    = 0;

-  virtual bool        empty()    const                                    = 0;

-  virtual size_t      capacity() const                                    = 0;

-

-  virtual void        pop_back()                                          = 0;

-  virtual void        clear()                                             = 0;

-  virtual void        reset()                                             = 0;

-  virtual void        reserve( const size_t new_size )                    = 0;

-  virtual void        assign( const size_t new_size, const Type &t )      = 0;

-  virtual void        resize( const size_t new_size, const Type t = { } ) = 0;

-  virtual void        shrink_to_fit()                                     = 0;

-  virtual void        push_back( const Type &t )                          = 0;

-  virtual void        push_back( Type &&t )                               = 0;

-};

-

-

-template<class Type> class MVKVector<Type *>

-{

-  mvk_vector_allocator_base<Type*> *alc_ptr;

-

-  class iterator : public std::iterator<std::forward_iterator_tag, Type*>

-  {

-    const MVKVector *vector;

-    size_t           index;

-

-  public:

-    iterator() = delete;

-    iterator( const size_t _index, const MVKVector &_vector ) : vector{ &_vector }, index{ _index } { }

-    iterator &operator=( const iterator &it ) = delete;

-

-    Type *operator->() const { return vector->alc_ptr->ptr[index]; }

-    Type *&operator*()       { return vector->alc_ptr->ptr[index]; }

-    operator Type*&()  const { return &vector->alc_ptr->ptr[index]; }

-

-    bool operator==( const iterator &it ) const { return vector == it.vector && index == it.index; }

-    bool operator!=( const iterator &it ) const { return vector != it.vector || index != it.index; }

-

-    iterator& operator++()      {                 ++index; return *this; }

-    iterator  operator++( int ) { auto t = *this; ++index; return t; }

-

-    bool   is_valid()     const { return index < vector->size(); }

-    size_t get_position() const { return index; }

-  };

-

-public:

-  typedef Type* value_type;

-

-  MVKVector() = delete;

-  MVKVector( mvk_vector_allocator_base<Type*> *a ) : alc_ptr{ a } { }

-  virtual ~MVKVector() { }

-

-  iterator begin() const { return iterator( 0,               *this ); }

-  iterator end()   const { return iterator( alc_ptr->size(), *this ); }

-

-  const MVKArrayRef<Type*> contents() const { return MVKArrayRef<Type*>(data(), size()); }

-        MVKArrayRef<Type*> contents()       { return MVKArrayRef<Type*>(data(), size()); }

-

-  virtual const Type * const  operator[]( const size_t i ) const             = 0;

-  virtual       Type *       &operator[]( const size_t i )                   = 0;

-  virtual const Type * const  at( const size_t i ) const                     = 0;

-  virtual       Type *       &at( const size_t i )                           = 0;

-  virtual const Type * const  front() const                                  = 0;

-  virtual       Type *       &front()                                        = 0;

-  virtual const Type * const  back() const                                   = 0;

-  virtual       Type *       &back()                                         = 0;

-  virtual const Type * const *data() const                                   = 0;

-  virtual       Type *       *data()                                         = 0;

-

-  virtual size_t              size() const                                   = 0;

-  virtual bool                empty() const                                  = 0;

-  virtual size_t              capacity() const                               = 0;

-

-  virtual void                pop_back()                                     = 0;

-  virtual void                clear()                                        = 0;

-  virtual void                reset()                                        = 0;

-  virtual void                reserve( const size_t new_size )               = 0;

-  virtual void                assign( const size_t new_size, const Type *t ) = 0;

-  virtual void                resize( const size_t new_size, const Type *t = nullptr ) = 0;

-  virtual void                shrink_to_fit()                                = 0;

-  virtual void                push_back( const Type *t )                     = 0;

-};

-

-

-// this is the actual implementation of MVKVector

-template<class Type, typename Allocator = mvk_vector_allocator_default<Type>> class MVKVectorImpl : public MVKVector<Type>

-{

-  friend class MVKVectorImpl;

-

-  Allocator  alc;

-  

-public:

-  class iterator : public std::iterator<std::forward_iterator_tag, Type>

-  {

-    const MVKVectorImpl *vector;

-    size_t               index;

-

-  public:

-    iterator() = delete;

-    iterator( const size_t _index, const MVKVectorImpl &_vector ) : vector{ &_vector }, index{ _index } { }

-

-    iterator &operator=( const iterator &it )

-    {

-      vector = it.vector;

-      index  = it.index;

-      return *this;

-    }

-

-    Type *operator->() { return &vector->alc.ptr[index]; }

-    Type &operator*()  { return  vector->alc.ptr[index]; }

-    operator Type*()   { return &vector->alc.ptr[index]; }

-

-    bool operator==( const iterator &it ) const { return vector == it.vector && index == it.index; }

-    bool operator!=( const iterator &it ) const { return vector != it.vector || index != it.index; }

-

-    iterator& operator++()      {                 ++index; return *this; }

-    iterator  operator++( int ) { auto t = *this; ++index; return t; }

-

-    bool   is_valid()     const { return index < vector->alc.size(); }

-    size_t get_position() const { return index; }

-  };

-

-private:

-  // this is the growth strategy -> adjust to your needs

-  size_t vector_GetNextCapacity() const

-  {

-    constexpr auto ELEMENTS_FOR_64_BYTES = 64 / sizeof( Type );

-    constexpr auto MINIMUM_CAPACITY = ELEMENTS_FOR_64_BYTES > 4 ? ELEMENTS_FOR_64_BYTES : 4;

-    const auto current_capacity = capacity();

-    return MINIMUM_CAPACITY + ( 3 * current_capacity ) / 2;

-  }

-

-  void vector_Allocate( const size_t s )

-  {

-    const auto new_reserved_size = s > size() ? s : size();

-

-    alc.allocate( new_reserved_size );

-  }

-

-  void vector_ReAllocate( const size_t s )

-  {

-    alc.re_allocate( s );

-  }

-

-public:

-  MVKVectorImpl() : MVKVector<Type>{ &alc }

-  {

-  }

-

-  MVKVectorImpl( const size_t n, const Type t ) : MVKVector<Type>{ &alc }

-  {

-    if( n > 0 )

-    {

-      alc.allocate( n );

-

-      for( size_t i = 0; i < n; ++i )

-      {

-        alc.construct( &alc.ptr[i], t );

-      }

-

-      alc.num_elements_used = n;

-    }

-  }

-

-  MVKVectorImpl( const MVKVectorImpl &a ) : MVKVector<Type>{ &alc }

-  {

-    const size_t n = a.size();

-

-    if( n > 0 )

-    {

-      alc.allocate( n );

-

-      for( size_t i = 0; i < n; ++i )

-      {

-        alc.construct( &alc.ptr[i], a.alc.ptr[i] );

-      }

-

-      alc.num_elements_used = n;

-    }

-  }

-

-  template<typename U>

-  MVKVectorImpl( const U &a ) : MVKVector<Type>{ &alc }

-  {

-    const size_t n = a.size();

-

-    if( n > 0 )

-    {

-      alc.allocate( n );

-

-      for( size_t i = 0; i < n; ++i )

-      {

-        alc.construct( &alc.ptr[i], a[i] );

-      }

-

-      alc.num_elements_used = n;

-    }

-  }

-

-  MVKVectorImpl( MVKVectorImpl &&a ) : MVKVector<Type>{ &alc }, alc{ std::move( a.alc ) }

-  {

-  }

-

-  MVKVectorImpl( std::initializer_list<Type> vector ) : MVKVector<Type>{ &alc }

-  {

-    if( vector.size() > capacity() )

-    {

-      vector_Allocate( vector.size() );

-    }

-

-    // std::initializer_list does not yet support std::move, we use it anyway but it has no effect

-    for( auto &&element : vector )

-    {

-      alc.construct( &alc.ptr[alc.num_elements_used], std::move( element ) );

-      ++alc.num_elements_used;

-    }

-  }

-

-  ~MVKVectorImpl()

-  {

-  }

-

-  template<typename U>

-  MVKVectorImpl& operator=( const U &a )

-  {

-    static_assert( std::is_base_of<MVKVector<Type>, U>::value, "argument is not of type MVKVector" );

-

-    if( this != reinterpret_cast<const MVKVector<Type>*>( &a ) )

-    {

-      const auto n = a.size();

-

-      if( alc.num_elements_used == n )

-      {

-        for( size_t i = 0; i < n; ++i )

-        {

-          alc.ptr[i] = a.alc.ptr[i];

-        }

-      }

-      else

-      {

-        if( n > capacity() )

-        {

-          vector_ReAllocate( n );

-        }

-        else

-        {

-          alc.template destruct_all<Type>();

-        }

-

-        for( size_t i = 0; i < n; ++i )

-        {

-          alc.construct( &alc.ptr[i], a[i] );

-        }

-

-        alc.num_elements_used = n;

-      }

-    }

-

-    return *this;

-  }

-

-  MVKVectorImpl& operator=( MVKVectorImpl &&a )

-  {

-    alc.swap( a.alc );

-    return *this;

-  }

-

-  bool operator==( const MVKVectorImpl &a ) const

-  {

-    if( alc.num_elements_used != a.alc.num_elements_used )

-      return false;

-    for( size_t i = 0; i < alc.num_elements_used; ++i )

-    {

-      if( alc[i] != a.alc[i] )

-        return false;

-    }

-    return true;

-  }

-

-  bool operator!=( const MVKVectorImpl &a ) const

-  {

-    if( alc.num_elements_used != a.alc.num_elements_used )

-      return true;

-    for( size_t i = 0; i < alc.num_elements_used; ++i )

-    {

-      if( alc.ptr[i] != a.alc[i] )

-        return true;

-    }

-    return false;

-  }

-

-  void swap( MVKVectorImpl &a )

-  {

-    alc.swap( a.alc );

-  }

-

-  iterator begin() const { return iterator( 0, *this ); }

-  iterator end()   const { return iterator( alc.num_elements_used, *this ); }

-

-  const Type &operator[]( const size_t i ) const override { return alc[i]; }

-        Type &operator[]( const size_t i )       override { return alc[i]; }

-  const Type &at( const size_t i )         const override { return alc[i]; }

-        Type &at( const size_t i )               override { return alc[i]; }

-  const Type &front()                      const override { return alc[0]; }

-        Type &front()                            override { return alc[0]; }

-  const Type &back()                       const override { return alc[alc.num_elements_used - 1]; }

-        Type &back()                             override { return alc[alc.num_elements_used - 1]; }

-  const Type *data()                       const override { return alc.ptr; }

-        Type *data()                             override { return alc.ptr; }

-

-  size_t      size()                       const override { return alc.num_elements_used; }

-  bool        empty()                      const override { return alc.num_elements_used == 0; }

-  size_t      capacity()                   const override { return alc.get_capacity(); }

-

-  void pop_back() override

-  {

-    if( alc.num_elements_used > 0 )

-    {

-      --alc.num_elements_used;

-      alc.destruct( &alc.ptr[alc.num_elements_used] );

-    }

-  }

-

-  void clear() override

-  {

-    alc.template destruct_all<Type>();

-  }

-

-  void reset() override

-  {

-    alc.deallocate();

-  }

-

-  void reserve( const size_t new_size ) override

-  {

-    if( new_size > capacity() )

-    {

-      vector_ReAllocate( new_size );

-    }

-  }

-

-  void assign( const size_t new_size, const Type &t ) override

-  {

-    if( new_size <= capacity() )

-    {

-      clear();

-    }

-    else

-    {

-      vector_Allocate( new_size );

-    }

-

-    for( size_t i = 0; i < new_size; ++i )

-    {

-      alc.construct( &alc.ptr[i], t );

-    }

-

-    alc.num_elements_used = new_size;

-  }

-

-  template <class InputIterator>

-  void assign( InputIterator first, InputIterator last )

-  {

-    clear();

-

-    while( first != last )

-    {

-      emplace_back( *first );

-      ++first;

-    }

-  }

-

-  void resize( const size_t new_size, const Type t = { } ) override

-  {

-    if( new_size == alc.num_elements_used )

-    {

-      return;

-    }

-

-    if( new_size == 0 )

-    {

-      clear();

-      return;

-    }

-

-    if( new_size > alc.num_elements_used )

-    {

-      if( new_size > capacity() )

-      {

-        vector_ReAllocate( new_size );

-      }

-

-      while( alc.num_elements_used < new_size )

-      {

-        alc.construct( &alc.ptr[alc.num_elements_used], t );

-        ++alc.num_elements_used;

-      }

-    }

-    else

-    {

-      //if constexpr( !std::is_trivially_destructible<Type>::value )

-      {

-        while( alc.num_elements_used > new_size )

-        {

-          --alc.num_elements_used;

-          alc.destruct( &alc.ptr[alc.num_elements_used] );

-        }

-      }

-      //else

-      //{

-      //  alc.num_elements_used = new_size;

-      //}

-    }

-  }

-

-  // trims the capacity of the slist to the number of alc.ptr

-  void shrink_to_fit() override

-  {

-    alc.shrink_to_fit();

-  }

-

-  void erase( const iterator it )

-  {

-    if( it.is_valid() )

-    {

-      --alc.num_elements_used;

-

-      for( size_t i = it.get_position(); i < alc.num_elements_used; ++i )

-      {

-        alc.ptr[i] = std::move( alc.ptr[i + 1] );

-      }

-

-      // this is required for types with a destructor

-      alc.destruct( &alc.ptr[alc.num_elements_used] );

-    }

-  }

-

-  void erase( const iterator first, const iterator last )

-  {

-    if( first.is_valid() )

-    {

-      size_t last_pos = last.is_valid() ? last.get_position() : size();

-      size_t n = last_pos - first.get_position();

-      alc.num_elements_used -= n;

-

-      for( size_t i = first.get_position(), e = last_pos; i < alc.num_elements_used && e < alc.num_elements_used + n; ++i, ++e )

-      {

-        alc.ptr[i] = std::move( alc.ptr[e] );

-      }

-

-      // this is required for types with a destructor

-      for( size_t i = alc.num_elements_used; i < alc.num_elements_used + n; ++i )

-      {

-        alc.destruct( &alc.ptr[i] );

-      }

-    }

-  }

-

-  // adds t before it and automatically resizes vector if necessary

-  void insert( const iterator it, Type t )

-  {

-    if( !it.is_valid() || alc.num_elements_used == 0 )

-    {

-      push_back( std::move( t ) );

-    }

-    else

-    {

-      if( alc.num_elements_used == capacity() )

-        vector_ReAllocate( vector_GetNextCapacity() );

-

-      // move construct last element

-      alc.construct( &alc.ptr[alc.num_elements_used], std::move( alc.ptr[alc.num_elements_used - 1] ) );

-

-      // move the remaining elements

-      const size_t it_position = it.get_position();

-      for( size_t i = alc.num_elements_used - 1; i > it_position; --i )

-      {

-        alc.ptr[i] = std::move( alc.ptr[i - 1] );

-      }

-

-      alc.ptr[it_position] = std::move( t );

-      ++alc.num_elements_used;

-    }

-  }

-

-  void push_back( const Type &t ) override

-  {

-    if( alc.num_elements_used == capacity() )

-      vector_ReAllocate( vector_GetNextCapacity() );

-

-    alc.construct( &alc.ptr[alc.num_elements_used], t );

-    ++alc.num_elements_used;

-  }

-

-  void push_back( Type &&t ) override

-  {

-    if( alc.num_elements_used == capacity() )

-      vector_ReAllocate( vector_GetNextCapacity() );

-

-    alc.construct( &alc.ptr[alc.num_elements_used], std::forward<Type>( t ) );

-    ++alc.num_elements_used;

-  }

-

-  template<class... Args>

-  Type &emplace_back( Args&&... args )

-  {

-    if( alc.num_elements_used == capacity() )

-      vector_ReAllocate( vector_GetNextCapacity() );

-

-    alc.construct( &alc.ptr[alc.num_elements_used], std::forward<Args>( args )... );

-    ++alc.num_elements_used;

-

-    return alc.ptr[alc.num_elements_used - 1];

-  }

-};

-

-// specialization for pointer types

-template<class Type, typename Allocator> class MVKVectorImpl<Type*, Allocator> : public MVKVector<Type*>

-{

-  friend class MVKVectorImpl;

-

-  Allocator  alc;

-

-public:

-  class iterator : public std::iterator<std::forward_iterator_tag, Type*>

-  {

-    MVKVectorImpl *vector;

-    size_t         index;

-

-  public:

-    iterator() = delete;

-    iterator( const size_t _index, MVKVectorImpl &_vector ) : vector{ &_vector }, index{ _index } { }

-

-    iterator &operator=( const iterator &it )

-    {

-      vector = it.vector;

-      index = it.index;

-      return *this;

-    }

-

-    Type *&operator*() { return vector->alc[index]; }

-

-    bool operator==( const iterator &it ) const { return vector == it.vector && index == it.index; }

-    bool operator!=( const iterator &it ) const { return vector != it.vector || index != it.index; }

-

-    iterator& operator++() { ++index; return *this; }

-    iterator  operator++( int ) { auto t = *this; ++index; return t; }

-

-    bool   is_valid()     const { return index < vector->alc.size(); }

-    size_t get_position() const { return index; }

-  };

-

-private:

-  // this is the growth strategy -> adjust to your needs

-  size_t vector_GetNextCapacity() const

-  {

-    constexpr auto ELEMENTS_FOR_64_BYTES = 64 / sizeof( Type* );

-    constexpr auto MINIMUM_CAPACITY = ELEMENTS_FOR_64_BYTES > 4 ? ELEMENTS_FOR_64_BYTES : 4;

-    const auto current_capacity = capacity();

-    return MINIMUM_CAPACITY + ( 3 * current_capacity ) / 2;

-  }

-

-  void vector_Allocate( const size_t s )

-  {

-    const auto new_reserved_size = s > size() ? s : size();

-

-    alc.allocate( new_reserved_size );

-  }

-

-  void vector_ReAllocate( const size_t s )

-  {

-    alc.re_allocate( s );

-  }

-

-public:

-  MVKVectorImpl() : MVKVector<Type*>{ &alc }

-  {

-  }

-

-  MVKVectorImpl( const size_t n, const Type *t ) : MVKVector<Type*>{ &alc }

-  {

-    if ( n > 0 )

-    {

-      alc.allocate( n );

-

-      for ( size_t i = 0; i < n; ++i )

-      {

-        alc.ptr[i] = t;

-      }

-

-      alc.num_elements_used = n;

-    }

-  }

-

-  MVKVectorImpl( const MVKVectorImpl &a ) : MVKVector<Type*>{ &alc }

-  {

-    const size_t n = a.size();

-

-    if ( n > 0 )

-    {

-      alc.allocate( n );

-

-      for ( size_t i = 0; i < n; ++i )

-      {

-        alc.ptr[i] = a.alc.ptr[i];

-      }

-

-      alc.num_elements_used = n;

-    }

-  }

-

-  MVKVectorImpl( MVKVectorImpl &&a ) : MVKVector<Type*>{ &alc }, alc{ std::move( a.alc ) }

-  {

-  }

-

-  MVKVectorImpl( std::initializer_list<Type*> vector ) : MVKVector<Type*>{ &alc }

-  {

-    if ( vector.size() > capacity() )

-    {

-      vector_Allocate( vector.size() );

-    }

-

-    // std::initializer_list does not yet support std::move, we use it anyway but it has no effect

-    for ( auto element : vector )

-    {

-      alc.ptr[alc.num_elements_used] = element;

-      ++alc.num_elements_used;

-    }

-  }

-

-  ~MVKVectorImpl()

-  {

-  }

-

-  template<typename U>

-  MVKVectorImpl& operator=( const U &a )

-  {

-    static_assert( std::is_base_of<MVKVector<U>, U>::value, "argument is not of type MVKVector" );

-

-    if ( this != reinterpret_cast< const MVKVector<Type>* >( &a ) )

-    {

-      const auto n = a.size();

-

-      if ( alc.num_elements_used == n )

-      {

-        for ( size_t i = 0; i < n; ++i )

-        {

-          alc.ptr[i] = a.alc.ptr[i];

-        }

-      }

-      else

-      {

-        if ( n > capacity() )

-        {

-          vector_ReAllocate( n );

-        }

-

-        for ( size_t i = 0; i < n; ++i )

-        {

-          alc.ptr[i] = a[i];

-        }

-

-        alc.num_elements_used = n;

-      }

-    }

-

-    return *this;

-  }

-

-  MVKVectorImpl& operator=( MVKVectorImpl &&a )

-  {

-    alc.swap( a.alc );

-    return *this;

-  }

-

-  bool operator==( const MVKVectorImpl &a ) const

-  {

-    if ( alc.num_elements_used != a.alc.num_elements_used )

-      return false;

-    for ( size_t i = 0; i < alc.num_elements_used; ++i )

-    {

-      if ( alc[i] != a.alc[i] )

-        return false;

-    }

-    return true;

-  }

-

-  bool operator!=( const MVKVectorImpl &a ) const

-  {

-    if ( alc.num_elements_used != a.alc.num_elements_used )

-      return true;

-    for ( size_t i = 0; i < alc.num_elements_used; ++i )

-    {

-      if ( alc.ptr[i] != a.alc[i] )

-        return true;

-    }

-    return false;

-  }

-

-  void swap( MVKVectorImpl &a )

-  {

-    alc.swap( a.alc );

-  }

-

-  iterator begin()        { return iterator( 0, *this ); }

-  iterator end()          { return iterator( alc.num_elements_used, *this ); }

-

-  const Type * const  at( const size_t i )         const override { return alc[i]; }

-        Type *       &at( const size_t i )               override { return alc[i]; }

-  const Type * const  operator[]( const size_t i ) const override { return alc[i]; }

-        Type *       &operator[]( const size_t i )       override { return alc[i]; }

-  const Type * const  front()                      const override { return alc[0]; }

-        Type *       &front()                            override { return alc[0]; }

-  const Type * const  back()                       const override { return alc[alc.num_elements_used - 1]; }

-        Type *       &back()                             override { return alc[alc.num_elements_used - 1]; }

-  const Type * const *data()                       const override { return alc.ptr; }

-        Type *       *data()                             override { return alc.ptr; }

-

-  size_t   size()                                  const override { return alc.num_elements_used; }

-  bool     empty()                                 const override { return alc.num_elements_used == 0; }

-  size_t   capacity()                              const override { return alc.get_capacity(); }

-

-  void pop_back() override

-  {

-    if ( alc.num_elements_used > 0 )

-    {

-      --alc.num_elements_used;

-    }

-  }

-

-  void clear() override

-  {

-    alc.num_elements_used = 0;

-  }

-

-  void reset() override

-  {

-    alc.deallocate();

-  }

-

-  void reserve( const size_t new_size ) override

-  {

-    if ( new_size > capacity() )

-    {

-      vector_ReAllocate( new_size );

-    }

-  }

-

-  void assign( const size_t new_size, const Type *t ) override

-  {

-    if ( new_size <= capacity() )

-    {

-      clear();

-    }

-    else

-    {

-      vector_Allocate( new_size );

-    }

-

-    for ( size_t i = 0; i < new_size; ++i )

-    {

-      alc.ptr[i] = const_cast< Type* >( t );

-    }

-

-    alc.num_elements_used = new_size;

-  }

-

-  void resize( const size_t new_size, const Type *t = nullptr ) override

-  {

-    if ( new_size == alc.num_elements_used )

-    {

-      return;

-    }

-

-    if ( new_size == 0 )

-    {

-      clear();

-      return;

-    }

-

-    if ( new_size > alc.num_elements_used )

-    {

-      if ( new_size > capacity() )

-      {

-        vector_ReAllocate( new_size );

-      }

-

-      while ( alc.num_elements_used < new_size )

-      {

-        alc.ptr[alc.num_elements_used] = const_cast< Type* >( t );

-        ++alc.num_elements_used;

-      }

-    }

-    else

-    {

-      alc.num_elements_used = new_size;

-    }

-  }

-

-  // trims the capacity of the MVKVector to the number of used elements

-  void shrink_to_fit() override

-  {

-    alc.shrink_to_fit();

-  }

-

-  void erase( const iterator it )

-  {

-    if ( it.is_valid() )

-    {

-      --alc.num_elements_used;

-

-      for ( size_t i = it.get_position(); i < alc.num_elements_used; ++i )

-      {

-        alc.ptr[i] = alc.ptr[i + 1];

-      }

-    }

-  }

-

-  void erase( const iterator first, const iterator last )

-  {

-    if( first.is_valid() )

-    {

-      size_t last_pos = last.is_valid() ? last.get_position() : size();

-      size_t n = last_pos - first.get_position();

-      alc.num_elements_used -= n;

-

-      for( size_t i = first.get_position(), e = last_pos; i < alc.num_elements_used && e < alc.num_elements_used + n; ++i, ++e )

-      {

-        alc.ptr[i] = alc.ptr[e];

-      }

-    }

-  }

-

-  // adds t before position it and automatically resizes vector if necessary

-  void insert( const iterator it, const Type *t )

-  {

-    if ( !it.is_valid() || alc.num_elements_used == 0 )

-    {

-      push_back( t );

-    }

-    else

-    {

-      if ( alc.num_elements_used == capacity() )

-        vector_ReAllocate( vector_GetNextCapacity() );

-

-      // move the remaining elements

-      const size_t it_position = it.get_position();

-      for ( size_t i = alc.num_elements_used; i > it_position; --i )

-      {

-        alc.ptr[i] = alc.ptr[i - 1];

-      }

-

-      alc.ptr[it_position] = const_cast< Type* >( t );

-      ++alc.num_elements_used;

-    }

-  }

-

-  void push_back( const Type *t ) override

-  {

-    if ( alc.num_elements_used == capacity() )

-      vector_ReAllocate( vector_GetNextCapacity() );

-

-    alc.ptr[alc.num_elements_used] = const_cast< Type* >( t );

-    ++alc.num_elements_used;

-  }

-};

-

-

-template<typename Type>

-using MVKVectorDefault = MVKVectorImpl<Type, mvk_vector_allocator_default<Type>>;

-

-template<typename Type, size_t N = 8>

-using MVKVectorInline  = MVKVectorImpl<Type, mvk_vector_allocator_with_stack<Type, N>>;

-

-

-#endif

-

-

diff --git a/MoltenVK/MoltenVK/Utility/MVKVectorAllocator.h b/MoltenVK/MoltenVK/Utility/MVKVectorAllocator.h
deleted file mode 100755
index 6fd5e93..0000000
--- a/MoltenVK/MoltenVK/Utility/MVKVectorAllocator.h
+++ /dev/null
@@ -1,552 +0,0 @@
-/*

- * MVKVectorAllocator.h

- *

- * Copyright (c) 2012-2021 Dr. Torsten Hans (hans@ipacs.de)

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- * 

- *     http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-#pragma once

-

-#include <new>

-#include <type_traits>

-

-

-#define MVK_VECTOR_CHECK_BOUNDS if (i >= num_elements_used) { throw std::out_of_range("Index out of range"); }

-

-

-namespace mvk_memory_allocator

-{

-  inline char *alloc( const size_t num_bytes )

-  {

-    return new char[num_bytes];

-  }

-

-  inline void free( void *ptr )

-  {

-    delete[] (char*)ptr;

-  }

-};

-

-

-//////////////////////////////////////////////////////////////////////////////////////////

-//

-// mvk_vector_allocator_base -> base class so we can use MVKVector with template parameter

-//

-//////////////////////////////////////////////////////////////////////////////////////////

-template<typename T>

-class mvk_vector_allocator_base

-{

-public:

-  typedef T value_type;

-  T      *ptr;

-  size_t  num_elements_used;

-

-public:

-  mvk_vector_allocator_base()                                           : ptr{ nullptr }, num_elements_used{ 0 }                  { }

-  mvk_vector_allocator_base( T *_ptr, const size_t _num_elements_used ) : ptr{ _ptr },    num_elements_used{ _num_elements_used } { }

-  virtual ~mvk_vector_allocator_base() { }

-

-  const T &operator[]( const size_t i ) const { MVK_VECTOR_CHECK_BOUNDS return ptr[i]; }

-  T       &operator[]( const size_t i )       { MVK_VECTOR_CHECK_BOUNDS return ptr[i]; }

-

-  size_t size() const { return num_elements_used; }

-

-  virtual size_t get_capacity() const = 0;

-  virtual void   allocate( const size_t num_elements_to_reserve ) = 0;

-  virtual void   re_allocate( const size_t num_elements_to_reserve ) = 0;

-  virtual void   shrink_to_fit() = 0;

-  virtual void   deallocate() = 0;

-};

-

-

-//////////////////////////////////////////////////////////////////////////////////////////

-//

-// mvk_vector_allocator_default -> malloc based allocator for MVKVector

-//

-//////////////////////////////////////////////////////////////////////////////////////////

-template <typename T>

-class mvk_vector_allocator_default final : public mvk_vector_allocator_base<T>

-{

-private:

-  size_t  num_elements_reserved;

-

-public:

-  template<class S, class... Args> typename std::enable_if< !std::is_trivially_constructible<S>::value >::type

-    construct( S *_ptr, Args&&... _args )

-  {

-    new ( _ptr ) S( std::forward<Args>( _args )... );

-  }

-

-  template<class S, class... Args> typename std::enable_if< std::is_trivially_constructible<S>::value >::type

-    construct( S *_ptr, Args&&... _args )

-  {

-    *_ptr = S( std::forward<Args>( _args )... );

-  }

-

-  template<class S> typename std::enable_if< !std::is_trivially_destructible<S>::value >::type

-    destruct( S *_ptr )

-  {

-    _ptr->~S();

-  }

-

-  template<class S> typename std::enable_if< std::is_trivially_destructible<S>::value >::type

-    destruct( S *_ptr )

-  {

-  }

-

-  template<class S> typename std::enable_if< !std::is_trivially_destructible<S>::value >::type

-    destruct_all()

-  {

-    for( size_t i = 0; i < mvk_vector_allocator_base<S>::num_elements_used; ++i )

-    {

-      mvk_vector_allocator_base<S>::ptr[i].~S();

-    }

-

-    mvk_vector_allocator_base<S>::num_elements_used = 0;

-  }

-

-  template<class S> typename std::enable_if< std::is_trivially_destructible<S>::value >::type

-    destruct_all()

-  {

-    mvk_vector_allocator_base<T>::num_elements_used = 0;

-  }

-

-public:

-  constexpr mvk_vector_allocator_default() : mvk_vector_allocator_base<T>{}, num_elements_reserved{ 0 }

-  {

-  }

-

-  mvk_vector_allocator_default( mvk_vector_allocator_default &&a ) : mvk_vector_allocator_base<T>{ a.ptr, a.num_elements_used }, num_elements_reserved{ a.num_elements_reserved }

-  {

-    a.ptr                   = nullptr;

-    a.num_elements_used     = 0;

-    a.num_elements_reserved = 0;

-  }

-

-  virtual ~mvk_vector_allocator_default()

-  {

-    deallocate();

-  }

-

-  size_t get_capacity() const override

-  {

-    return num_elements_reserved;

-  }

-

-  void swap( mvk_vector_allocator_default &a )

-  {

-    const auto copy_ptr                   = a.ptr;

-    const auto copy_num_elements_used     = a.num_elements_used;

-    const auto copy_num_elements_reserved = a.num_elements_reserved;

-

-    a.ptr                   = mvk_vector_allocator_base<T>::ptr;

-    a.num_elements_used     = mvk_vector_allocator_base<T>::num_elements_used;

-    a.num_elements_reserved = num_elements_reserved;

-

-    mvk_vector_allocator_base<T>::ptr                = copy_ptr;

-    mvk_vector_allocator_base<T>::num_elements_used  = copy_num_elements_used;

-    num_elements_reserved = copy_num_elements_reserved;

-  }

-

-  void allocate( const size_t num_elements_to_reserve ) override

-  {

-    deallocate();

-

-    mvk_vector_allocator_base<T>::ptr                = reinterpret_cast< T* >( mvk_memory_allocator::alloc( num_elements_to_reserve * sizeof( T ) ) );

-    mvk_vector_allocator_base<T>::num_elements_used  = 0;

-    num_elements_reserved = num_elements_to_reserve;

-  }

-

-  void re_allocate( const size_t num_elements_to_reserve ) override

-  {

-    //if constexpr( std::is_trivially_copyable<T>::value )

-    //{

-    //  ptr = reinterpret_cast< T* >( mvk_memory_allocator::tm_memrealloc( ptr, num_elements_to_reserve * sizeof( T ) );

-    //}

-    //else

-    {

-      auto *new_ptr = reinterpret_cast< T* >( mvk_memory_allocator::alloc( num_elements_to_reserve * sizeof( T ) ) );

-

-      for( size_t i = 0; i < mvk_vector_allocator_base<T>::num_elements_used; ++i )

-      {

-        construct( &new_ptr[i], std::move( mvk_vector_allocator_base<T>::ptr[i] ) );

-        destruct( &mvk_vector_allocator_base<T>::ptr[i] );

-      }

-

-      //if ( ptr != nullptr )

-      {

-        mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-      }

-

-      mvk_vector_allocator_base<T>::ptr = new_ptr;

-    }

-

-    num_elements_reserved = num_elements_to_reserve;

-  }

-

-  void shrink_to_fit() override

-  {

-    if( mvk_vector_allocator_base<T>::num_elements_used == 0 )

-    {

-      deallocate();

-    }

-    else

-    {

-      auto *new_ptr = reinterpret_cast< T* >( mvk_memory_allocator::alloc( mvk_vector_allocator_base<T>::num_elements_used * sizeof( T ) ) );

-

-      for( size_t i = 0; i < mvk_vector_allocator_base<T>::num_elements_used; ++i )

-      {

-        construct( &new_ptr[i], std::move( mvk_vector_allocator_base<T>::ptr[i] ) );

-        destruct( &mvk_vector_allocator_base<T>::ptr[i] );

-      }

-

-      mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-

-      mvk_vector_allocator_base<T>::ptr = new_ptr;

-      num_elements_reserved = mvk_vector_allocator_base<T>::num_elements_used;

-    }

-  }

-

-  void deallocate() override

-  {

-    destruct_all<T>();

-

-    mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-

-    mvk_vector_allocator_base<T>::ptr = nullptr;

-    num_elements_reserved = 0;

-  }

-};

-

-

-//////////////////////////////////////////////////////////////////////////////////////////

-//

-// mvk_vector_allocator_with_stack -> malloc based MVKVector allocator with preallocated storage

-//

-//////////////////////////////////////////////////////////////////////////////////////////

-template <typename T, int N>

-class mvk_vector_allocator_with_stack final : public mvk_vector_allocator_base<T>

-{

-private:

-  //size_t  num_elements_reserved; // uhh, num_elements_reserved is mapped onto the stack elements, let the fun begin

-  alignas( alignof( T ) ) unsigned char   elements_stack[N * sizeof( T )];

-

-  static_assert( N * sizeof( T ) >= sizeof( size_t ), "Initial static allocation must be at least 8 bytes. Increase the count of pre-allocated elements." );

-

-  void set_num_elements_reserved( const size_t num_elements_reserved )

-  {

-    *reinterpret_cast<size_t*>( &elements_stack[0] ) = num_elements_reserved;

-  }

-

-public:

-  //

-  // faster element construction and destruction using type traits

-  //

-  template<class S, class... Args> typename std::enable_if< !std::is_trivially_constructible<S, Args...>::value >::type

-    construct( S *_ptr, Args&&... _args )

-  {

-    new ( _ptr ) S( std::forward<Args>( _args )... );

-  }

-

-  template<class S, class... Args> typename std::enable_if< std::is_trivially_constructible<S, Args...>::value >::type

-    construct( S *_ptr, Args&&... _args )

-  {

-    *_ptr = S( std::forward<Args>( _args )... );

-  }

-

-  template<class S> typename std::enable_if< !std::is_trivially_destructible<S>::value >::type

-    destruct( S *_ptr )

-  {

-    _ptr->~S();

-  }

-

-  template<class S> typename std::enable_if< std::is_trivially_destructible<S>::value >::type

-    destruct( S *_ptr )

-  {

-  }

-

-  template<class S> typename std::enable_if< !std::is_trivially_destructible<S>::value >::type

-    destruct_all()

-  {

-    for( size_t i = 0; i < mvk_vector_allocator_base<S>::num_elements_used; ++i )

-    {

-      mvk_vector_allocator_base<S>::ptr[i].~S();

-    }

-

-    mvk_vector_allocator_base<S>::num_elements_used = 0;

-  }

-

-  template<class S> typename std::enable_if< std::is_trivially_destructible<S>::value >::type

-    destruct_all()

-  {

-    mvk_vector_allocator_base<S>::num_elements_used = 0;

-  }

-

-  template<class S> typename std::enable_if< !std::is_trivially_destructible<S>::value >::type

-    swap_stack( mvk_vector_allocator_with_stack &a )

-  {

-    T stack_copy[N];

-

-    for( size_t i = 0; i < mvk_vector_allocator_base<S>::num_elements_used; ++i )

-    {

-      construct( &stack_copy[i], std::move( S::ptr[i] ) );

-      destruct( &mvk_vector_allocator_base<S>::ptr[i] );

-    }

-

-    for( size_t i = 0; i < a.num_elements_used; ++i )

-    {

-      construct( &mvk_vector_allocator_base<S>::ptr[i], std::move( a.ptr[i] ) );

-      destruct( &mvk_vector_allocator_base<S>::ptr[i] );

-    }

-

-    for( size_t i = 0; i < mvk_vector_allocator_base<S>::num_elements_used; ++i )

-    {

-      construct( &a.ptr[i], std::move( stack_copy[i] ) );

-      destruct( &stack_copy[i] );

-    }

-  }

-

-  template<class S> typename std::enable_if< std::is_trivially_destructible<S>::value >::type

-    swap_stack( mvk_vector_allocator_with_stack &a )

-  {

-    constexpr int STACK_SIZE = N * sizeof( T );

-    for( int i = 0; i < STACK_SIZE; ++i )

-    {

-      const auto v = elements_stack[i];

-      elements_stack[i] = a.elements_stack[i];

-      a.elements_stack[i] = v;

-    }

-  }

-

-public:

-  mvk_vector_allocator_with_stack() : mvk_vector_allocator_base<T>{ reinterpret_cast<T*>( &elements_stack[0] ), 0 }

-  {

-  }

-

-  mvk_vector_allocator_with_stack( mvk_vector_allocator_with_stack &&a ) : mvk_vector_allocator_base<T>{ nullptr, a.num_elements_used }

-  {

-    // is a heap based -> steal ptr from a

-    if( !a.get_data_on_stack() )

-    {

-      mvk_vector_allocator_base<T>::ptr = a.ptr;

-      set_num_elements_reserved( a.get_capacity() );

-

-      a.ptr = a.get_default_ptr();

-    }

-    else

-    {

-      mvk_vector_allocator_base<T>::ptr = get_default_ptr();

-      for( size_t i = 0; i < a.num_elements_used; ++i )

-      {

-        construct( &mvk_vector_allocator_base<T>::ptr[i], std::move( a.ptr[i] ) );

-        destruct( &a.ptr[i] );

-      }

-    }

-

-    a.num_elements_used = 0;

-  }

-

-  ~mvk_vector_allocator_with_stack()

-  {

-    deallocate();

-  }

-

-  size_t get_capacity() const override

-  {

-    return get_data_on_stack() ? N : *reinterpret_cast<const size_t*>( &elements_stack[0] );

-  }

-

-  constexpr T *get_default_ptr() const

-  {

-    return reinterpret_cast< T* >( const_cast< unsigned char * >( &elements_stack[0] ) );

-  }

-

-  bool get_data_on_stack() const

-  {

-    return mvk_vector_allocator_base<T>::ptr == get_default_ptr();

-  }

-

-  void swap( mvk_vector_allocator_with_stack &a )

-  {

-    // both allocators on heap -> easy case

-    if( !get_data_on_stack() && !a.get_data_on_stack() )

-    {

-      auto copy_ptr = mvk_vector_allocator_base<T>::ptr;

-      auto copy_num_elements_reserved = get_capacity();

-      mvk_vector_allocator_base<T>::ptr = a.ptr;

-      set_num_elements_reserved( a.get_capacity() );

-      a.ptr = copy_ptr;

-      a.set_num_elements_reserved( copy_num_elements_reserved );

-    }

-    // both allocators on stack -> just switch the stack contents

-    else if( get_data_on_stack() && a.get_data_on_stack() )

-    {

-      swap_stack<T>( a );

-    }

-    else if( get_data_on_stack() && !a.get_data_on_stack() )

-    {

-      auto copy_ptr = a.ptr;

-      auto copy_num_elements_reserved = a.get_capacity();

-

-      a.ptr = a.get_default_ptr();

-      for( size_t i = 0; i < mvk_vector_allocator_base<T>::num_elements_used; ++i )

-      {

-        construct( &a.ptr[i], std::move( mvk_vector_allocator_base<T>::ptr[i] ) );

-        destruct( &mvk_vector_allocator_base<T>::ptr[i] );

-      }

-

-      mvk_vector_allocator_base<T>::ptr = copy_ptr;

-      set_num_elements_reserved( copy_num_elements_reserved );

-    }

-    else if( !get_data_on_stack() && a.get_data_on_stack() )

-    {

-      auto copy_ptr = mvk_vector_allocator_base<T>::ptr;

-      auto copy_num_elements_reserved = get_capacity();

-

-      mvk_vector_allocator_base<T>::ptr = get_default_ptr();

-      for( size_t i = 0; i < a.num_elements_used; ++i )

-      {

-        construct( &mvk_vector_allocator_base<T>::ptr[i], std::move( a.ptr[i] ) );

-        destruct( &a.ptr[i] );

-      }

-

-      a.ptr = copy_ptr;

-      a.set_num_elements_reserved( copy_num_elements_reserved );

-    }

-

-    auto copy_num_elements_used = mvk_vector_allocator_base<T>::num_elements_used;

-    mvk_vector_allocator_base<T>::num_elements_used = a.num_elements_used;

-    a.num_elements_used = copy_num_elements_used;

-  }

-

-  //

-  // allocates rounded up to the defined alignment the number of bytes / if the system cannot allocate the specified amount of memory then a null block is returned

-  //

-  void allocate( const size_t num_elements_to_reserve ) override

-  {

-    deallocate();

-

-    // check if enough memory on stack space is left

-    if( num_elements_to_reserve <= N )

-    {

-      return;

-    }

-

-    mvk_vector_allocator_base<T>::ptr               = reinterpret_cast< T* >( mvk_memory_allocator::alloc( num_elements_to_reserve * sizeof( T ) ) );

-    mvk_vector_allocator_base<T>::num_elements_used = 0;

-    set_num_elements_reserved( num_elements_to_reserve );

-  }

-

-  //template<class S> typename std::enable_if< !std::is_trivially_copyable<S>::value >::type

-  void _re_allocate( const size_t num_elements_to_reserve )

-  {

-    auto *new_ptr = reinterpret_cast< T* >( mvk_memory_allocator::alloc( num_elements_to_reserve * sizeof( T ) ) );

-

-    for( size_t i = 0; i < mvk_vector_allocator_base<T>::num_elements_used; ++i )

-    {

-      construct( &new_ptr[i], std::move( mvk_vector_allocator_base<T>::ptr[i] ) );

-      destruct( &mvk_vector_allocator_base<T>::ptr[i] );

-    }

-

-    if( mvk_vector_allocator_base<T>::ptr != get_default_ptr() )

-    {

-      mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-    }

-

-    mvk_vector_allocator_base<T>::ptr = new_ptr;

-    set_num_elements_reserved( num_elements_to_reserve );

-  }

-

-  //template<class S> typename std::enable_if< std::is_trivially_copyable<S>::value >::type

-  //  _re_allocate( const size_t num_elements_to_reserve )

-  //{

-  //  const bool data_is_on_stack = get_data_on_stack();

-  //

-  //  auto *new_ptr = reinterpret_cast< S* >( mvk_memory_allocator::tm_memrealloc( data_is_on_stack ? nullptr : ptr, num_elements_to_reserve * sizeof( S ) ) );

-  //  if( data_is_on_stack )

-  //  {

-  //    for( int i = 0; i < N; ++i )

-  //    {

-  //      new_ptr[i] = ptr[i];

-  //    }

-  //  }

-  //

-  //  ptr = new_ptr;

-  //  set_num_elements_reserved( num_elements_to_reserve );

-  //}

-

-  void re_allocate( const size_t num_elements_to_reserve ) override

-  {

-    //TM_ASSERT( num_elements_to_reserve > get_capacity() );

-

-    if( num_elements_to_reserve > N )

-    {

-      _re_allocate( num_elements_to_reserve );

-    }

-  }

-

-  void shrink_to_fit() override

-  {

-    // nothing to do if data is on stack already

-    if( get_data_on_stack() )

-      return;

-

-    // move elements to stack space

-    if( mvk_vector_allocator_base<T>::num_elements_used <= N )

-    {

-      //const auto num_elements_reserved = get_capacity();

-

-      auto *stack_ptr = get_default_ptr();

-      for( size_t i = 0; i < mvk_vector_allocator_base<T>::num_elements_used; ++i )

-      {

-        construct( &stack_ptr[i], std::move( mvk_vector_allocator_base<T>::ptr[i] ) );

-        destruct( &mvk_vector_allocator_base<T>::ptr[i] );

-      }

-

-      mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-

-      mvk_vector_allocator_base<T>::ptr = stack_ptr;

-    }

-    else

-    {

-      auto *new_ptr = reinterpret_cast< T* >( mvk_memory_allocator::alloc( mvk_vector_allocator_base<T>::num_elements_used * sizeof( T ) ) );

-

-      for( size_t i = 0; i < mvk_vector_allocator_base<T>::num_elements_used; ++i )

-      {

-        construct( &new_ptr[i], std::move( mvk_vector_allocator_base<T>::ptr[i] ) );

-        destruct( &mvk_vector_allocator_base<T>::ptr[i] );

-      }

-

-      mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-

-      mvk_vector_allocator_base<T>::ptr = new_ptr;

-      set_num_elements_reserved( mvk_vector_allocator_base<T>::num_elements_used );

-    }

-  }

-

-  void deallocate() override

-  {

-    destruct_all<T>();

-

-    if( !get_data_on_stack() )

-    {

-      mvk_memory_allocator::free( mvk_vector_allocator_base<T>::ptr );

-    }

-

-    mvk_vector_allocator_base<T>::ptr = get_default_ptr();

-    mvk_vector_allocator_base<T>::num_elements_used = 0;

-  }

-};

-

-