Merge pull request #696 from billhollings/master

Two code structural design improvements: MVKVector & MVKLinkableMixin
This commit is contained in:
Bill Hollings 2019-08-02 10:30:42 -04:00 committed by GitHub
commit ff671179a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 184 additions and 169 deletions

View File

@ -20,7 +20,8 @@ Released TBD
- Revert to supporting host-coherent memory for linear images on macOS.
- Ensure Vulkan loader magic number is set every time before returning any dispatchable Vulkan handle.
- Consolidate the various linkable objects into a `MVKLinkableMixin` template base class.
- Use `MVKVector` whenever possible in MoltenVK, especially within render loop.
MoltenVK 1.0.36

View File

@ -50,7 +50,7 @@ typedef unsigned long MTLLanguageVersion;
*/
#define MVK_VERSION_MAJOR 1
#define MVK_VERSION_MINOR 0
#define MVK_VERSION_PATCH 36
#define MVK_VERSION_PATCH 37
#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)

View File

@ -20,7 +20,6 @@
#include "MVKCommand.h"
#include "MVKMTLResourceBindings.h"
#include <vector>
#import <Metal/Metal.h>

View File

@ -20,7 +20,6 @@
#include "MVKCommand.h"
#include "MVKVector.h"
#include <vector>
class MVKCommandBuffer;
class MVKPipeline;
@ -54,9 +53,9 @@ private:
VkPipelineStageFlags _srcStageMask;
VkPipelineStageFlags _dstStageMask;
VkDependencyFlags _dependencyFlags;
std::vector<VkMemoryBarrier> _memoryBarriers;
std::vector<VkBufferMemoryBarrier> _bufferMemoryBarriers;
std::vector<VkImageMemoryBarrier> _imageMemoryBarriers;
MVKVectorInline<VkMemoryBarrier, 4> _memoryBarriers;
MVKVectorInline<VkBufferMemoryBarrier, 4> _bufferMemoryBarriers;
MVKVectorInline<VkImageMemoryBarrier, 4> _imageMemoryBarriers;
};

View File

@ -77,7 +77,7 @@ void MVKCmdPipelineBarrier::encode(MVKCommandEncoder* cmdEncoder) {
afterStages: srcStages
beforeStages: dstStages];
}
std::vector<id<MTLResource>> resources;
MVKVectorInline<id<MTLResource>, 16> resources;
resources.reserve(_bufferMemoryBarriers.size() + _imageMemoryBarriers.size());
for (auto& mb : _bufferMemoryBarriers) {
auto* mvkBuff = (MVKBuffer*)mb.buffer;

View File

@ -20,7 +20,6 @@
#include "MVKCommand.h"
#include "MVKVector.h"
#include <vector>
#import <Metal/Metal.h>
@ -85,7 +84,7 @@ public:
#pragma mark -
#pragma mark MVKCmdExecuteCommands
/** Vulkan command to end the current render pass. */
/** Vulkan command to execute secondary command buffers. */
class MVKCmdExecuteCommands : public MVKCommand {
public:
@ -96,7 +95,7 @@ public:
MVKCmdExecuteCommands(MVKCommandTypePool<MVKCmdExecuteCommands>* pool);
private:
std::vector<MVKCommandBuffer*> _secondaryCommandBuffers;
MVKVectorInline<MVKCommandBuffer*, 64> _secondaryCommandBuffers;
};
#pragma mark -

View File

@ -22,7 +22,7 @@
#include "MVKMTLBufferAllocation.h"
#include "MVKCommandResourceFactory.h"
#include "MVKFoundation.h"
#include <vector>
#include "MVKVector.h"
#import <Metal/Metal.h>
@ -68,9 +68,9 @@ protected:
bool _isDstCompressed;
bool _canCopyFormats;
bool _useTempBuffer;
std::vector<VkImageCopy> _imageCopyRegions;
std::vector<VkBufferImageCopy> _srcTmpBuffImgCopies;
std::vector<VkBufferImageCopy> _dstTmpBuffImgCopies;
MVKVectorInline<VkImageCopy, 4> _imageCopyRegions;
MVKVectorInline<VkBufferImageCopy, 4> _srcTmpBuffImgCopies;
MVKVectorInline<VkBufferImageCopy, 4> _dstTmpBuffImgCopies;
size_t _tmpBuffSize;
MVKCommandUse _commandUse;
};
@ -117,7 +117,7 @@ protected:
MTLRenderPassDescriptor* _mtlRenderPassDescriptor;
MTLSamplerMinMagFilter _mtlFilter;
MVKRPSKeyBlitImg _blitKey;
std::vector<MVKImageBlitRender> _mvkImageBlitRenders;
MVKVectorInline<MVKImageBlitRender, 4> _mvkImageBlitRenders;
};
@ -157,11 +157,11 @@ protected:
VkImageLayout _srcLayout;
MVKImage* _dstImage;
VkImageLayout _dstLayout;
std::vector<VkImageBlit> _expansionRegions;
std::vector<VkImageCopy> _copyRegions;
MVKImageDescriptorData _transferImageData;
MTLRenderPassDescriptor* _mtlRenderPassDescriptor;
std::vector<MVKMetalResolveSlice> _mtlResolveSlices;
MVKVectorInline<VkImageBlit, 4> _expansionRegions;
MVKVectorInline<VkImageCopy, 4> _copyRegions;
MVKVectorInline<MVKMetalResolveSlice, 4> _mtlResolveSlices;
};
@ -186,7 +186,7 @@ protected:
MVKBuffer* _srcBuffer;
MVKBuffer* _dstBuffer;
std::vector<VkBufferCopy> _mtlBuffCopyRegions;
MVKVectorInline<VkBufferCopy, 4> _mtlBuffCopyRegions;
};
@ -215,7 +215,7 @@ protected:
MVKBuffer* _buffer;
MVKImage* _image;
VkImageLayout _imageLayout;
std::vector<VkBufferImageCopy> _bufferImageCopyRegions;
MVKVectorInline<VkBufferImageCopy, 4> _bufferImageCopyRegions;
bool _toImage = false;
};
@ -241,8 +241,8 @@ protected:
void populateVertices(float attWidth, float attHeight);
void populateVertices(VkClearRect& clearRect, float attWidth, float attHeight);
std::vector<VkClearRect> _clearRects;
std::vector<simd::float4> _vertices;
MVKVectorInline<VkClearRect, 4> _clearRects;
MVKVectorInline<simd::float4, (4 * 6)> _vertices;
simd::float4 _clearColors[kMVKClearAttachmentCount];
VkClearValue _vkClearValues[kMVKClearAttachmentCount];
MVKRPSKeyClearAtt _rpsKey;
@ -278,7 +278,7 @@ protected:
MVKImage* _image;
VkImageLayout _imgLayout;
std::vector<VkImageSubresourceRange> _subresourceRanges;
MVKVectorInline<VkImageSubresourceRange, 4> _subresourceRanges;
MTLClearColor _mtlColorClearValue;
double _mtlDepthClearValue;
uint32_t _mtlStencilClearValue;
@ -330,7 +330,7 @@ protected:
MVKBuffer* _dstBuffer;
VkDeviceSize _dstOffset;
VkDeviceSize _dataSize;
std::vector<uint8_t> _srcDataCache;
MVKVectorDefault<uint8_t> _srcDataCache;
};

View File

@ -33,7 +33,7 @@ template <class T> class MVKCommandTypePool;
#pragma mark MVKCommand
/** Abstract class that represents a Vulkan command. */
class MVKCommand : public MVKConfigurableObject {
class MVKCommand : public MVKConfigurableObject, public MVKLinkableMixin<MVKCommand> {
public:
@ -50,7 +50,7 @@ public:
virtual void encode(MVKCommandEncoder* cmdEncoder) = 0;
/**
* Returns this object back to the pool that created it. This will reset the value of _next member.
* Returns this object back to the pool that created it.
*
* This method is not thread-safe. Vulkan Command Pools are externally synchronized.
* For a particular MVKCommandTypePool instance, all calls to pool->aquireObject(),
@ -78,13 +78,6 @@ public:
/** Returns the underlying Metal device. */
id<MTLDevice> getMTLDevice();
/**
* Instances of this class can participate in a linked list or pool. When so participating,
* this is a reference to the next instance in the list or pool. This value should only be
* managed and set by the list or pool.
*/
MVKCommand* _next = nullptr;
protected:
MVKCommandTypePool<MVKCommand>* _pool;
MVKCommandBuffer* _commandBuffer = nullptr;

View File

@ -23,8 +23,8 @@
#include "MVKCommandEncoderState.h"
#include "MVKMTLBufferAllocation.h"
#include "MVKCmdPipeline.h"
#include "MVKQueryPool.h"
#include "MVKVector.h"
#include <vector>
#include <unordered_map>
class MVKCommandPool;
@ -50,8 +50,9 @@ typedef uint64_t MVKMTLCommandBufferID;
#pragma mark MVKCommandBuffer
/** Represents a Vulkan command pool. */
class MVKCommandBuffer : public MVKDispatchableVulkanAPIObject, public MVKDeviceTrackingMixin {
class MVKCommandBuffer : public MVKDispatchableVulkanAPIObject,
public MVKDeviceTrackingMixin,
public MVKLinkableMixin<MVKCommandBuffer> {
public:
/** Returns the Vulkan type of this object. */
@ -96,13 +97,6 @@ public:
*/
id<MTLBuffer> _initialVisibilityResultMTLBuffer;
/**
* Instances of this class can participate in a linked list or pool. When so participating,
* this is a reference to the next instance in the list or pool. This value should only be
* managed and set by the list or pool.
*/
MVKCommandBuffer* _next;
#pragma mark Constituent render pass management
/** Preps metadata for recording render pass */
@ -246,7 +240,7 @@ protected:
/*** Holds a collection of active queries for each query pool. */
typedef std::unordered_map<MVKQueryPool*, std::vector<uint32_t>> MVKActivatedQueries;
typedef std::unordered_map<MVKQueryPool*, MVKVectorInline<uint32_t, kMVKDefaultQueryCount>> MVKActivatedQueries;
/**
* MVKCommandEncoder uses a visitor design pattern iterate the commands in a MVKCommandBuffer,

View File

@ -398,7 +398,7 @@ void MVKCommandEncoder::finalizeDrawState(MVKGraphicsStage stage) {
// Clears the render area of the framebuffer attachments.
void MVKCommandEncoder::clearRenderArea() {
vector<VkClearAttachment> clearAtts;
MVKVectorInline<VkClearAttachment, kMVKDefaultAttachmentCount> clearAtts;
getSubpass()->populateClearAttachments(clearAtts, _clearValues);
uint32_t clearAttCnt = (uint32_t)clearAtts.size();

View File

@ -519,11 +519,11 @@ protected:
void resetImpl() override;
void markDirty() override;
MVKVectorDefault<MVKMTLBufferBinding> _bufferBindings;
MVKVectorDefault<MVKMTLTextureBinding> _textureBindings;
MVKVectorDefault<MVKMTLSamplerStateBinding> _samplerStateBindings;
MVKVectorDefault<uint32_t> _swizzleConstants;
MVKVectorDefault<uint32_t> _bufferSizes;
MVKVectorInline<MVKMTLBufferBinding, 4> _bufferBindings;
MVKVectorInline<MVKMTLTextureBinding, 4> _textureBindings;
MVKVectorInline<MVKMTLSamplerStateBinding, 4> _samplerStateBindings;
MVKVectorInline<uint32_t, 4> _swizzleConstants;
MVKVectorInline<uint32_t, 4> _bufferSizes;
MVKMTLBufferBinding _swizzleBufferBinding;
MVKMTLBufferBinding _bufferSizeBufferBinding;

View File

@ -123,6 +123,9 @@ void MVKCommandPool::trim() {
_cmdDispatchIndirectPool.clear();
_cmdPushDescriptorSetPool.clear();
_cmdPushSetWithTemplatePool.clear();
_cmdDebugMarkerBeginPool.clear();
_cmdDebugMarkerEndPool.clear();
_cmdDebugMarkerInsertPool.clear();
}
@ -131,9 +134,9 @@ void MVKCommandPool::trim() {
MVKCommandPool::MVKCommandPool(MVKDevice* device,
const VkCommandPoolCreateInfo* pCreateInfo) :
MVKVulkanAPIDeviceObject(device),
_queueFamilyIndex(pCreateInfo->queueFamilyIndex),
_commandBufferPool(device),
_commandEncodingPool(this),
_queueFamilyIndex(pCreateInfo->queueFamilyIndex),
_cmdPipelineBarrierPool(this),
_cmdBindPipelinePool(this),
_cmdBeginRenderPassPool(this),
@ -143,13 +146,13 @@ MVKCommandPool::MVKCommandPool(MVKDevice* device,
_cmdBindDescriptorSetsPool(this),
_cmdSetViewportPool(this),
_cmdSetScissorPool(this),
_cmdSetLineWidthPool(this),
_cmdSetDepthBiasPool(this),
_cmdSetBlendConstantsPool(this),
_cmdSetDepthBoundsPool(this),
_cmdSetStencilCompareMaskPool(this),
_cmdSetStencilWriteMaskPool(this),
_cmdSetStencilReferencePool(this),
_cmdSetLineWidthPool(this),
_cmdSetDepthBiasPool(this),
_cmdSetBlendConstantsPool(this),
_cmdSetDepthBoundsPool(this),
_cmdSetStencilCompareMaskPool(this),
_cmdSetStencilWriteMaskPool(this),
_cmdSetStencilReferencePool(this),
_cmdBindVertexBuffersPool(this),
_cmdBindIndexBufferPool(this),
_cmdDrawPool(this),
@ -158,26 +161,27 @@ MVKCommandPool::MVKCommandPool(MVKDevice* device,
_cmdDrawIndexedIndirectPool(this),
_cmdCopyImagePool(this),
_cmdBlitImagePool(this),
_cmdResolveImagePool(this),
_cmdFillBufferPool(this),
_cmdUpdateBufferPool(this),
_cmdResolveImagePool(this),
_cmdFillBufferPool(this),
_cmdUpdateBufferPool(this),
_cmdCopyBufferPool(this),
_cmdBufferImageCopyPool(this),
_cmdBufferImageCopyPool(this),
_cmdClearAttachmentsPool(this),
_cmdClearImagePool(this),
_cmdBeginQueryPool(this),
_cmdEndQueryPool(this),
_cmdBeginQueryPool(this),
_cmdEndQueryPool(this),
_cmdWriteTimestampPool(this),
_cmdResetQueryPoolPool(this),
_cmdCopyQueryPoolResultsPool(this),
_cmdResetQueryPoolPool(this),
_cmdCopyQueryPoolResultsPool(this),
_cmdPushConstantsPool(this),
_cmdDispatchPool(this),
_cmdDispatchIndirectPool(this),
_cmdPushDescriptorSetPool(this),
_cmdPushSetWithTemplatePool(this),
_cmdDispatchPool(this),
_cmdDispatchIndirectPool(this),
_cmdPushDescriptorSetPool(this),
_cmdPushSetWithTemplatePool(this),
_cmdDebugMarkerBeginPool(this),
_cmdDebugMarkerEndPool(this),
_cmdDebugMarkerInsertPool(this)
// when extending be sure to add to trim() as well
{}
MVKCommandPool::~MVKCommandPool() {

View File

@ -22,7 +22,7 @@
#include "MVKFoundation.h"
#include "MVKObjectPool.h"
#include "MVKDevice.h"
#include <vector>
#include "MVKVector.h"
class MVKMTLBufferAllocationPool;
@ -31,7 +31,7 @@ class MVKMTLBufferAllocationPool;
#pragma mark MVKMTLBufferAllocation
/** Defines a contiguous region of bytes within a MTLBuffer. */
class MVKMTLBufferAllocation : public MVKBaseObject {
class MVKMTLBufferAllocation : public MVKBaseObject, public MVKLinkableMixin<MVKMTLBufferAllocation> {
public:
id<MTLBuffer> _mtlBuffer;
@ -50,7 +50,7 @@ public:
/** Returns the pool whence this object was created. */
MVKMTLBufferAllocationPool* getPool() const { return _pool; }
/** Returns this object back to the pool that created it. This will reset the value of _next member. */
/** Returns this object back to the pool that created it. */
void returnToPool();
/** Constructs this instance with the specified pool as its origin. */
@ -59,13 +59,6 @@ public:
NSUInteger offset,
NSUInteger length) : _pool(pool), _mtlBuffer(mtlBuffer), _offset(offset), _length(length) {}
/**
* Instances of this class can participate in a linked list or pool. When so participating,
* this is a reference to the next instance in the list or pool. This value should only be
* managed and set by the list or pool.
*/
MVKMTLBufferAllocation* _next = nullptr;
protected:
MVKMTLBufferAllocationPool* _pool;
@ -104,7 +97,7 @@ protected:
NSUInteger _nextOffset;
NSUInteger _allocationLength;
NSUInteger _mtlBufferLength;
std::vector<id<MTLBuffer>> _mtlBuffers;
MVKVectorInline<id<MTLBuffer>, 64> _mtlBuffers;
MVKDevice* _device;
};
@ -149,7 +142,7 @@ public:
~MVKMTLBufferAllocator() override;
protected:
std::vector<MVKMTLBufferAllocationPool*> _regionPools;
MVKVectorInline<MVKMTLBufferAllocationPool*, 32> _regionPools;
NSUInteger _maxAllocationLength;
bool _makeThreadSafe;

View File

@ -24,7 +24,6 @@
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
#include <unordered_set>
#include <unordered_map>
#include <vector>
class MVKDescriptorPool;
class MVKDescriptorBinding;
@ -118,7 +117,7 @@ protected:
MVKDescriptorSetLayout* _layout;
VkDescriptorSetLayoutBinding _info;
std::vector<MVKSampler*> _immutableSamplers;
MVKVectorInline<MVKSampler*, 16> _immutableSamplers;
MVKShaderResourceBinding _mtlResourceIndexOffsets;
bool _applyToStage[kMVKShaderStageMax];
};
@ -272,13 +271,13 @@ protected:
MVKDescriptorSet* _pDescSet;
MVKDescriptorSetLayoutBinding* _pBindingLayout;
std::vector<VkDescriptorImageInfo> _imageBindings;
std::vector<VkDescriptorBufferInfo> _bufferBindings;
std::vector<VkBufferView> _texelBufferBindings;
std::vector<id<MTLBuffer>> _mtlBuffers;
std::vector<NSUInteger> _mtlBufferOffsets;
std::vector<id<MTLTexture>> _mtlTextures;
std::vector<id<MTLSamplerState>> _mtlSamplers;
MVKVectorInline<VkDescriptorImageInfo, 1> _imageBindings;
MVKVectorInline<VkDescriptorBufferInfo, 1> _bufferBindings;
MVKVectorInline<VkBufferView, 1> _texelBufferBindings;
MVKVectorInline<id<MTLBuffer>, 1> _mtlBuffers;
MVKVectorInline<NSUInteger, 1> _mtlBufferOffsets;
MVKVectorInline<id<MTLTexture>, 1> _mtlTextures;
MVKVectorInline<id<MTLSamplerState>, 1> _mtlSamplers;
bool _hasDynamicSamplers;
};
@ -287,7 +286,7 @@ protected:
#pragma mark MVKDescriptorSet
/** Represents a Vulkan descriptor set. */
class MVKDescriptorSet : public MVKVulkanAPIDeviceObject {
class MVKDescriptorSet : public MVKVulkanAPIDeviceObject, public MVKLinkableMixin<MVKDescriptorSet> {
public:
@ -313,13 +312,6 @@ public:
VkDescriptorBufferInfo* pBufferInfo,
VkBufferView* pTexelBufferView);
/**
* Instances of this class can participate in a linked list or pool. When so participating,
* this is a reference to the next instance in the list or pool. This value should only be
* managed and set by the list or pool.
*/
MVKDescriptorSet* _next;
MVKDescriptorSet(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {}
protected:
@ -331,7 +323,7 @@ protected:
MVKDescriptorBinding* getBinding(uint32_t binding);
MVKDescriptorSetLayout* _pLayout = nullptr;
std::vector<MVKDescriptorBinding> _bindings;
MVKVectorInline<MVKDescriptorBinding, 8> _bindings;
};
@ -415,7 +407,7 @@ protected:
void propogateDebugName() override {}
VkDescriptorUpdateTemplateTypeKHR _type;
std::vector<VkDescriptorUpdateTemplateEntryKHR> _entries;
MVKVectorInline<VkDescriptorUpdateTemplateEntryKHR, 4> _entries;
};
#pragma mark -

View File

@ -22,9 +22,9 @@
#include "MVKVulkanAPIObject.h"
#include "MVKLayers.h"
#include "MVKObjectPool.h"
#include "MVKVector.h"
#include "mvk_datatypes.hpp"
#include "vk_mvk_moltenvk.h"
#include <vector>
#include <string>
#include <mutex>
@ -67,6 +67,10 @@ class MVKCommandResourceFactory;
const static uint32_t kMVKVertexContentBufferIndex = 0;
// Parameters to define the sizing of inline collections
const static uint32_t kMVKQueueFamilyCount = 4;
const static uint32_t kMVKQueueCountPerQueueFamily = 1; // Must be 1. See comments in MVKPhysicalDevice::getQueueFamilies()
const static uint32_t kMVKMinSwapchainImageCount = 2;
const static uint32_t kMVKMaxSwapchainImageCount = 3;
const static uint32_t kMVKCachedViewportScissorCount = 16;
const static uint32_t kMVKCachedColorAttachmentCount = 8;
@ -328,7 +332,7 @@ protected:
void initMemoryProperties();
void initExtensions();
MVKExtensionList* getSupportedExtensions(const char* pLayerName = nullptr);
std::vector<MVKQueueFamily*>& getQueueFamilies();
MVKVector<MVKQueueFamily*>& getQueueFamilies();
void initPipelineCacheUUID();
MTLFeatureSet getHighestMTLFeatureSet();
uint64_t getSpirvCrossRevision();
@ -343,7 +347,7 @@ protected:
VkPhysicalDeviceProperties _properties;
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT _texelBuffAlignProperties;
VkPhysicalDeviceMemoryProperties _memoryProperties;
std::vector<MVKQueueFamily*> _queueFamilies;
MVKVectorInline<MVKQueueFamily*, kMVKQueueFamilyCount> _queueFamilies;
uint32_t _allMemoryTypes;
uint32_t _hostVisibleMemoryTypes;
uint32_t _hostCoherentMemoryTypes;
@ -677,8 +681,8 @@ protected:
MVKPhysicalDevice* _physicalDevice;
MVKCommandResourceFactory* _commandResourceFactory;
MTLCompileOptions* _mtlCompileOptions;
std::vector<std::vector<MVKQueue*>> _queuesByQueueFamilyIndex;
std::vector<MVKResource*> _resources;
MVKVectorInline<MVKVectorInline<MVKQueue*, kMVKQueueCountPerQueueFamily>, kMVKQueueFamilyCount> _queuesByQueueFamilyIndex;
MVKVectorInline<MVKResource*, 256> _resources;
std::mutex _rezLock;
std::mutex _perfLock;
id<MTLBuffer> _globalVisibilityResultMTLBuffer;

View File

@ -606,16 +606,16 @@ VkResult MVKPhysicalDevice::getPresentRectangles(MVKSurface* surface,
// Metal does not distinguish functionality between queues, which would normally lead us
// to create only only one general-purpose queue family. However, Vulkan associates command
// buffers with a queue family, whereas Metal associates command buffers with a Metal queue.
// In order to allow a Metal command buffer to be prefilled before is is formally submitted to
// In order to allow a Metal command buffer to be prefilled before it is formally submitted to
// a Vulkan queue, we need to enforce that each Vulkan queue family can have only one Metal queue.
// In order to provide parallel queue operations, we therefore provide multiple queue families.
vector<MVKQueueFamily*>& MVKPhysicalDevice::getQueueFamilies() {
MVKVector<MVKQueueFamily*>& MVKPhysicalDevice::getQueueFamilies() {
if (_queueFamilies.empty()) {
VkQueueFamilyProperties qfProps;
bool specialize = _mvkInstance->getMoltenVKConfiguration()->specializedQueueFamilies;
uint32_t qfIdx = 0;
qfProps.queueCount = 1; // Each queue family must have a single Metal queue (see above)
qfProps.queueCount = kMVKQueueCountPerQueueFamily;
qfProps.timestampValidBits = 64;
qfProps.minImageTransferGranularity = { 1, 1, 1};
@ -634,6 +634,8 @@ vector<MVKQueueFamily*>& MVKPhysicalDevice::getQueueFamilies() {
// Dedicated transfer queue family...or another general-purpose queue family.
if (specialize) { qfProps.queueFlags = VK_QUEUE_TRANSFER_BIT; }
_queueFamilies.push_back(new MVKQueueFamily(this, qfIdx++, &qfProps));
MVKAssert(kMVKQueueFamilyCount >= _queueFamilies.size(), "Adjust value of kMVKQueueFamilyCount.");
}
return _queueFamilies;
}
@ -641,7 +643,7 @@ vector<MVKQueueFamily*>& MVKPhysicalDevice::getQueueFamilies() {
VkResult MVKPhysicalDevice::getQueueFamilyProperties(uint32_t* pCount,
VkQueueFamilyProperties* pQueueFamilyProperties) {
vector<MVKQueueFamily*> qFams = getQueueFamilies();
auto& qFams = getQueueFamilies();
uint32_t qfCnt = uint32_t(qFams.size());
// If properties aren't actually being requested yet, simply update the returned count
@ -750,8 +752,8 @@ void MVKPhysicalDevice::initMetalFeatures() {
_metalFeatures.ioSurfaces = MVK_SUPPORT_IOSURFACE_BOOL;
// Metal supports 2 or 3 concurrent CAMetalLayer drawables.
_metalFeatures.minSwapchainImageCount = 2;
_metalFeatures.maxSwapchainImageCount = 3;
_metalFeatures.minSwapchainImageCount = kMVKMinSwapchainImageCount;
_metalFeatures.maxSwapchainImageCount = kMVKMaxSwapchainImageCount;
#if MVK_IOS
_metalFeatures.mslVersionEnum = MTLLanguageVersion1_0;
@ -2088,14 +2090,14 @@ void MVKDevice::freeMemory(MVKDeviceMemory* mvkDevMem,
mvkDevMem->destroy();
}
/** Adds the specified resource for tracking, and returns the added resource. */
// Adds the specified resource for tracking, and returns the added resource.
MVKResource* MVKDevice::addResource(MVKResource* rez) {
lock_guard<mutex> lock(_rezLock);
_resources.push_back(rez);
return rez;
}
/** Removes the specified resource for tracking and returns the removed resource. */
// Removes the specified resource for tracking and returns the removed resource.
MVKResource* MVKDevice::removeResource(MVKResource* rez) {
lock_guard<mutex> lock(_rezLock);
mvkRemoveFirstOccurance(_resources, rez);
@ -2488,7 +2490,7 @@ void MVKDevice::enableExtensions(const VkDeviceCreateInfo* pCreateInfo) {
// Create the command queues
void MVKDevice::initQueues(const VkDeviceCreateInfo* pCreateInfo) {
vector<MVKQueueFamily*> qFams = _physicalDevice->getQueueFamilies();
auto& qFams = _physicalDevice->getQueueFamilies();
uint32_t qrCnt = pCreateInfo->queueCreateInfoCount;
for (uint32_t qrIdx = 0; qrIdx < qrCnt; qrIdx++) {
const VkDeviceQueueCreateInfo* pQFInfo = &pCreateInfo->pQueueCreateInfos[qrIdx];

View File

@ -19,7 +19,7 @@
#pragma once
#include "MVKDevice.h"
#include <vector>
#include "MVKVector.h"
#include <mutex>
#import <Metal/Metal.h>
@ -128,8 +128,8 @@ protected:
void freeHostMemory();
MVKResource* getDedicatedResource();
std::vector<MVKBuffer*> _buffers;
std::vector<MVKImage*> _images;
MVKVectorInline<MVKBuffer*, 4> _buffers;
MVKVectorInline<MVKImage*, 4> _images;
std::mutex _rezLock;
VkDeviceSize _allocationSize = 0;
VkDeviceSize _mapOffset = 0;

View File

@ -20,7 +20,7 @@
#include "MVKDevice.h"
#include "MVKImage.h"
#include <vector>
#include "MVKVector.h"
#pragma mark MVKFramebuffer
@ -56,6 +56,6 @@ protected:
VkExtent2D _extent;
uint32_t _layerCount;
std::vector<MVKImageView*> _attachments;
MVKVectorInline<MVKImageView*, 8> _attachments;
};

View File

@ -257,7 +257,7 @@ protected:
VkPipelineStageFlags dstStageMask,
VkImageMemoryBarrier* pImageMemoryBarrier);
std::vector<MVKImageSubresource> _subresources;
MVKVectorInline<MVKImageSubresource, 4> _subresources;
std::unordered_map<NSUInteger, id<MTLTexture>> _mtlTextureViews;
VkExtent3D _extent;
uint32_t _mipLevels;

View File

@ -21,8 +21,8 @@
#include "MVKEnvironment.h"
#include "MVKLayers.h"
#include "MVKVulkanAPIObject.h"
#include "MVKVector.h"
#include "vk_mvk_moltenvk.h"
#include <vector>
#include <unordered_map>
#include <string>
#include <mutex>
@ -100,7 +100,7 @@ public:
VkResult getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps);
/** Returns the driver layer. */
MVKLayer* getDriverLayer() { return MVKLayerManager::globalManager()->getDriverLayer(); }
MVKLayer* getDriverLayer() { return getLayerManager()->getDriverLayer(); }
MVKSurface* createSurface(const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
@ -187,10 +187,10 @@ protected:
MVKConfiguration _mvkConfig;
VkApplicationInfo _appInfo;
std::vector<MVKPhysicalDevice*> _physicalDevices;
MVKVectorInline<MVKPhysicalDevice*, 4> _physicalDevices;
MVKVectorInline<MVKDebugReportCallback*, 4> _debugReportCallbacks;
MVKVectorInline<MVKDebugUtilsMessenger*, 4> _debugUtilMessengers;
std::unordered_map<std::string, MVKEntryPoint> _entryPoints;
std::vector<MVKDebugReportCallback*> _debugReportCallbacks;
std::vector<MVKDebugUtilsMessenger*> _debugUtilMessengers;
std::mutex _dcbLock;
bool _hasDebugReportCallbacks;
bool _hasDebugUtilsMessengers;

View File

@ -666,7 +666,7 @@ void MVKInstance::initConfig() {
VkResult MVKInstance::verifyLayers(uint32_t count, const char* const* names) {
VkResult result = VK_SUCCESS;
for (uint32_t i = 0; i < count; i++) {
if ( !MVKLayerManager::globalManager()->getLayerNamed(names[i]) ) {
if ( !getLayerManager()->getLayerNamed(names[i]) ) {
result = reportError(VK_ERROR_LAYER_NOT_PRESENT, "Vulkan layer %s is not supported.", names[i]);
}
}

View File

@ -20,7 +20,6 @@
#include "MVKDevice.h"
#include "MVKVector.h"
#include <vector>
#include <mutex>
#include <condition_variable>
@ -29,7 +28,8 @@ class MVKCommandBuffer;
class MVKCommandEncoder;
// The size of one query slot in bytes
#define kMVKQuerySlotSizeInBytes sizeof(uint64_t)
#define kMVKQuerySlotSizeInBytes sizeof(uint64_t)
#define kMVKDefaultQueryCount 64
#pragma mark -
@ -57,7 +57,7 @@ public:
virtual void endQuery(uint32_t query, MVKCommandEncoder* cmdEncoder);
/** Finishes the specified queries and marks them as available. */
virtual void finishQueries(std::vector<uint32_t>& queries);
virtual void finishQueries(MVKVector<uint32_t>& queries);
/** Resets the results and availability status of the specified queries. */
virtual void resetResults(uint32_t firstQuery, uint32_t queryCount, MVKCommandEncoder* cmdEncoder);
@ -101,7 +101,7 @@ public:
MVKQueryPool(MVKDevice* device,
const VkQueryPoolCreateInfo* pCreateInfo,
const uint32_t queryElementCount) : MVKVulkanAPIDeviceObject(device),
_availability(pCreateInfo->queryCount),
_availability(pCreateInfo->queryCount, Initial),
_queryElementCount(queryElementCount) {}
protected:
@ -127,12 +127,12 @@ protected:
Available /**< Query is available to the host. */
};
std::vector<Status> _availability;
MVKVectorInline<Status, kMVKDefaultQueryCount> _availability;
MVKVectorInline<DeferredCopy, 4> _deferredCopies;
uint32_t _queryElementCount;
std::mutex _availabilityLock;
std::condition_variable _availabilityBlocker;
std::mutex _deferredCopiesLock;
MVKVectorInline<DeferredCopy, 2> _deferredCopies;
};
@ -143,7 +143,7 @@ protected:
class MVKTimestampQueryPool : public MVKQueryPool {
public:
void finishQueries(std::vector<uint32_t>& queries) override;
void finishQueries(MVKVector<uint32_t>& queries) override;
#pragma mark Construction
@ -156,7 +156,7 @@ protected:
id<MTLBuffer> getResultBuffer(MVKCommandEncoder* cmdEncoder, uint32_t firstQuery, uint32_t queryCount, NSUInteger& offset) override;
void encodeSetResultBuffer(MVKCommandEncoder* cmdEncoder, uint32_t firstQuery, uint32_t queryCount, uint32_t index) override;
std::vector<uint64_t> _timestamps;
MVKVectorInline<uint64_t, kMVKDefaultQueryCount> _timestamps;
};

View File

@ -47,7 +47,7 @@ void MVKQueryPool::endQuery(uint32_t query, MVKCommandEncoder* cmdEncoder) {
}
// Mark queries as available
void MVKQueryPool::finishQueries(vector<uint32_t>& queries) {
void MVKQueryPool::finishQueries(MVKVector<uint32_t>& queries) {
lock_guard<mutex> lock(_availabilityLock);
for (uint32_t qry : queries) { _availability[qry] = Available; }
_availabilityBlocker.notify_all(); // Predicate of each wait() call will check whether all required queries are available
@ -184,7 +184,7 @@ void MVKQueryPool::deferCopyResults(uint32_t firstQuery,
#pragma mark MVKTimestampQueryPool
// Update timestamp values, then mark queries as available
void MVKTimestampQueryPool::finishQueries(vector<uint32_t>& queries) {
void MVKTimestampQueryPool::finishQueries(MVKVector<uint32_t>& queries) {
uint64_t ts = mvkGetTimestamp();
for (uint32_t qry : queries) { _timestamps[qry] = ts; }
@ -215,7 +215,8 @@ void MVKTimestampQueryPool::encodeSetResultBuffer(MVKCommandEncoder* cmdEncoder,
#pragma mark Construction
MVKTimestampQueryPool::MVKTimestampQueryPool(MVKDevice* device,
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1), _timestamps(pCreateInfo->queryCount) {
const VkQueryPoolCreateInfo* pCreateInfo) :
MVKQueryPool(device, pCreateInfo, 1), _timestamps(pCreateInfo->queryCount, 0) {
}

View File

@ -23,7 +23,6 @@
#include "MVKImage.h"
#include "MVKSync.h"
#include "MVKVector.h"
#include <vector>
#include <mutex>
#import <Metal/Metal.h>
@ -65,7 +64,7 @@ protected:
MVKPhysicalDevice* _physicalDevice;
uint32_t _queueFamilyIndex;
VkQueueFamilyProperties _properties;
std::vector<id<MTLCommandQueue>> _mtlQueues;
MVKVectorInline<id<MTLCommandQueue>, kMVKQueueCountPerQueueFamily> _mtlQueues;
std::mutex _qLock;
};
@ -180,8 +179,6 @@ protected:
friend class MVKQueue;
MVKQueue* _queue;
MVKQueueSubmission* _prev;
MVKQueueSubmission* _next;
MVKVectorInline<MVKSemaphore*, 8> _waitSemaphores;
bool _isAwaitingSemaphores;
bool _trackPerformance;

View File

@ -202,8 +202,6 @@ MVKQueueSubmission::MVKQueueSubmission(MVKQueue* queue,
uint32_t waitSemaphoreCount,
const VkSemaphore* pWaitSemaphores) {
_queue = queue;
_prev = nullptr;
_next = nullptr;
_trackPerformance = _queue->_device->_pMVKConfig->performanceTracking;
_isAwaitingSemaphores = waitSemaphoreCount > 0;

View File

@ -20,7 +20,6 @@
#include "MVKDevice.h"
#include "MVKVector.h"
#include <vector>
#import <Metal/Metal.h>
@ -28,6 +27,10 @@ class MVKRenderPass;
class MVKFramebuffer;
// Parameters to define the sizing of inline collections
const static uint32_t kMVKDefaultAttachmentCount = 8;
#pragma mark -
#pragma mark MVKRenderSubpass
@ -70,7 +73,7 @@ public:
* Populates the specified vector with the attachments that need to be cleared
* when the render area is smaller than the full framebuffer size.
*/
void populateClearAttachments(std::vector<VkClearAttachment>& clearAtts,
void populateClearAttachments(MVKVector<VkClearAttachment>& clearAtts,
MVKVector<VkClearValue>& clearValues);
/** Constructs an instance for the specified parent renderpass. */
@ -85,10 +88,10 @@ private:
MVKRenderPass* _renderPass;
uint32_t _subpassIndex;
std::vector<VkAttachmentReference> _inputAttachments;
std::vector<VkAttachmentReference> _colorAttachments;
std::vector<VkAttachmentReference> _resolveAttachments;
std::vector<uint32_t> _preserveAttachments;
MVKVectorInline<VkAttachmentReference, kMVKDefaultAttachmentCount> _inputAttachments;
MVKVectorInline<VkAttachmentReference, kMVKDefaultAttachmentCount> _colorAttachments;
MVKVectorInline<VkAttachmentReference, kMVKDefaultAttachmentCount> _resolveAttachments;
MVKVectorInline<uint32_t, kMVKDefaultAttachmentCount> _preserveAttachments;
VkAttachmentReference _depthStencilAttachment;
id<MTLTexture> _mtlDummyTex = nil;
};
@ -168,9 +171,9 @@ protected:
void propogateDebugName() override {}
std::vector<MVKRenderSubpass> _subpasses;
std::vector<MVKRenderPassAttachment> _attachments;
std::vector<VkSubpassDependency> _subpassDependencies;
MVKVectorInline<MVKRenderPassAttachment, kMVKDefaultAttachmentCount> _attachments;
MVKVectorInline<MVKRenderSubpass, 4> _subpasses;
MVKVectorInline<VkSubpassDependency, 4 * 2> _subpassDependencies;
};

View File

@ -165,7 +165,7 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
}
}
void MVKRenderSubpass::populateClearAttachments(vector<VkClearAttachment>& clearAtts,
void MVKRenderSubpass::populateClearAttachments(MVKVector<VkClearAttachment>& clearAtts,
MVKVector<VkClearValue>& clearValues) {
VkClearAttachment cAtt;

View File

@ -20,9 +20,9 @@
#include "MVKDevice.h"
#include "MVKSync.h"
#include "MVKVector.h"
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
#include <MoltenVKGLSLToSPIRVConverter/GLSLToSPIRVConverter.h>
#include <vector>
#include <mutex>
#import <Metal/Metal.h>
@ -151,7 +151,7 @@ protected:
void merge(MVKShaderLibraryCache* other);
MVKVulkanAPIDeviceObject* _owner;
std::vector<std::pair<SPIRVToMSLConversionConfiguration, MVKShaderLibrary*>> _shaderLibraries;
MVKVectorInline<std::pair<SPIRVToMSLConversionConfiguration, MVKShaderLibrary*>, 4> _shaderLibraries;
};

View File

@ -19,7 +19,7 @@
#pragma once
#include "MVKDevice.h"
#include <vector>
#include "MVKVector.h"
class MVKSwapchainImage;
class MVKWatermark;
@ -111,7 +111,7 @@ protected:
CAMetalLayer* _mtlLayer;
MVKWatermark* _licenseWatermark;
std::vector<MVKSwapchainImage*> _surfaceImages;
MVKVectorInline<MVKSwapchainImage*, kMVKMaxSwapchainImageCount> _surfaceImages;
std::atomic<uint64_t> _currentAcquisitionID;
CGSize _mtlLayerOrigDrawSize;
MVKSwapchainPerformance _performanceStatistics;

View File

@ -23,7 +23,6 @@
#include <mutex>
#include <condition_variable>
#include <unordered_set>
#include <vector>
class MVKFenceSitter;

View File

@ -20,7 +20,7 @@
#include "MVKBaseObject.h"
#include "MVKExtensions.h"
#include <vector>
#include "MVKVector.h"
#pragma mark MVKLayer
@ -115,7 +115,7 @@ public:
static MVKLayerManager* globalManager();
protected:
std::vector<MVKLayer> _layers;
MVKVectorInline<MVKLayer, 1> _layers;
};

View File

@ -23,14 +23,36 @@
#include <mutex>
/**
* Instances of sublcasses of this mixin can participate in a typed linked list or pool.
* A simple implementation of the CRTP (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
*/
template <class T>
class MVKLinkableMixin {
public:
/**
* When participating in a linked list or pool, this is a reference to the next instance
* in the list or pool. This value should only be managed and set by the list or pool.
*/
T* _next = nullptr;
protected:
friend T;
MVKLinkableMixin() {};
};
#pragma mark -
#pragma mark MVKObjectPool
/**
* Manages a pool of instances of a particular object type.
*
* The objects managed by this pool must have public member variable named "_next",
* of the same object type, which is used by this pool to create a linked list of objects.
* The objects managed by this pool should derive from MVKLinkableMixin, or otherwise
* support a public member variable named "_next", of the same object type, which is
* used by this pool to create a linked list of objects.
*
* When this pool is destroyed, any objects contained in the pool are also destroyed.
*

View File

@ -42,8 +42,7 @@ using MVKVector = std::vector<T>;
// 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.
// If C++17 will be the default in the future, code can be simplified quite a bit.
//
// Example:
//
@ -55,8 +54,7 @@ using MVKVector = std::vector<T>;
// 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
// 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
@ -182,6 +180,7 @@ public:
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;
@ -670,7 +669,7 @@ 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 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;
@ -830,6 +829,7 @@ public:
const Type * const back() const override { return alc.ptr[alc.num_elements_used - 1]; }
Type * &back() override { return alc.ptr[alc.num_elements_used - 1]; }
const Type * const *data() const override { return &alc.ptr[0]; }
Type * *data() override { return &alc.ptr[0]; }
size_t size() const override { return alc.num_elements_used; }
bool empty() const override { return alc.num_elements_used == 0; }
@ -931,6 +931,21 @@ public:
}
}
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 )
{