Merge branch 'master' of https://github.com/KhronosGroup/MoltenVK
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index d18ce65..2df61a3 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -12,6 +12,28 @@
For best results, use a Markdown reader.*
+MoltenVK 1.0.23
+---------------
+
+Released 2018/09/28
+
+- Add support for features:
+ - shaderStorageImageMultisample
+ - shaderStorageImageReadWithoutFormat
+ - shaderStorageImageWriteWithoutFormat
+ - shaderUniformBufferArrayDynamicIndexing
+ - shaderSampledImageArrayDynamicIndexing
+ - shaderStorageBufferArrayDynamicIndexing
+ - shaderStorageImageArrayDynamicIndexing
+- Support reduced render area
+- Support rasterization to missing attachment
+- Allocate MVKCommandBuffers from a pool within MVKCommandPool.
+- Update glslang version
+- Update to latest SPIRV-Cross version:
+ - MSL: Improve coordinate handling for buffer reads.
+ - MSL: Expand arrays of buffers passed as input.
+
+
MoltenVK 1.0.22
---------------
diff --git a/ExternalRevisions/glslang_repo_revision b/ExternalRevisions/glslang_repo_revision
index 3cf4e5d..26eb722 100644
--- a/ExternalRevisions/glslang_repo_revision
+++ b/ExternalRevisions/glslang_repo_revision
@@ -1 +1 @@
-a8453d4bc00998049db0d448764784a6a0767539
+91ac4290bcf2cb930b4fb0981f09c00c0b6797e1
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommand.h b/MoltenVK/MoltenVK/Commands/MVKCommand.h
index b3dd8f3..00ba38a 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommand.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommand.h
@@ -77,7 +77,7 @@
/**
* Instances of this class can participate in a linked list or pool. When so participating,
- * this is a reference to the next command in the linked list. This value should only be
+ * this is a reference to the next instance in the linked list. This value should only be
* managed and set by the linked list.
*/
MVKCommand* _next = nullptr;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
index 9c06290..c28a398 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
@@ -21,6 +21,7 @@
#include "MVKDevice.h"
#include "MVKCommand.h"
#include "MVKCommandEncoderState.h"
+#include "MVKMTLBufferAllocation.h"
#include "MVKCmdPipeline.h"
#include <vector>
#include <unordered_map>
@@ -90,15 +91,15 @@
/**
* Instances of this class can participate in a linked list or pool. When so participating,
- * this is a reference to the next command in the linked list. This value should only be
+ * this is a reference to the next instance in the linked list. This value should only be
* managed and set by the linked list.
*/
MVKCommandBuffer* _next;
#pragma mark Construction
-
- MVKCommandBuffer(MVKDevice* device, const VkCommandBufferAllocateInfo* pAllocateInfo);
+
+ MVKCommandBuffer(MVKDevice* device) : MVKDispatchableDeviceObject(device) {}
~MVKCommandBuffer() override;
@@ -118,7 +119,9 @@
protected:
friend class MVKCommandEncoder;
+ friend class MVKCommandPool;
+ void init(const VkCommandBufferAllocateInfo* pAllocateInfo);
bool canExecute();
bool canPrefill();
void prefill();
@@ -141,6 +144,33 @@
#pragma mark -
+#pragma mark MVKCommandBufferPool
+
+/**
+ * A pool of MVKCommandBuffer instances.
+ *
+ * To return a MVKCommandBuffer retrieved from this pool, back to this pool,
+ * call the returnToPool() function on the MVKCommandBuffer instance.
+ */
+class MVKCommandBufferPool : public MVKObjectPool<MVKCommandBuffer> {
+
+public:
+
+ /** Returns a new command instance. */
+ MVKCommandBuffer* newObject() override { return new MVKCommandBuffer(_device); }
+
+ /**
+ * Configures this instance to either use pooling, or not, depending on the
+ * value of isPooling, which defaults to true if not indicated explicitly.
+ */
+ MVKCommandBufferPool(MVKDevice* device, bool isPooling = true) : MVKObjectPool<MVKCommandBuffer>(isPooling), _device(device) {}
+
+protected:
+ MVKDevice* _device;
+};
+
+
+#pragma mark -
#pragma mark MVKCommandEncoder
// The following commands can be issued both inside and outside a renderpass and their state must
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
index 6812ceb..7c2f232 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
@@ -175,11 +175,9 @@
#pragma mark Construction
-MVKCommandBuffer::MVKCommandBuffer(MVKDevice* device,
- const VkCommandBufferAllocateInfo* pAllocateInfo) : MVKDispatchableDeviceObject(device) {
-
+// Initializes this instance after it has been created retrieved from a pool.
+void MVKCommandBuffer::init(const VkCommandBufferAllocateInfo* pAllocateInfo) {
_commandPool = (MVKCommandPool*)pAllocateInfo->commandPool;
- _commandPool->addCommandBuffer(this);
_isSecondary = (pAllocateInfo->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);
_head = nullptr;
_tail = nullptr;
@@ -190,7 +188,6 @@
MVKCommandBuffer::~MVKCommandBuffer() {
reset(0);
- _commandPool->removeCommandBuffer(this);
}
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
index ce9779d..8e54826 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
@@ -18,7 +18,8 @@
#pragma once
-#include "MVKCommandPool.h"
+#include "MVKMTLResourceBindings.h"
+#include "MVKCommandResourceFactory.h"
#include <vector>
class MVKCommandEncoder;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h
index 37c2567..1373cb0 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h
@@ -97,6 +97,9 @@
/** Returns a MTLComputePipelineState for filling a buffer. */
id<MTLComputePipelineState> getCmdFillBufferMTLComputePipelineState();
+ /** Deletes all the internal resources. */
+ void clear();
+
#pragma mark Construction
MVKCommandEncodingPool(MVKDevice* device);
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm
index 74e82d6..b1d9462 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm
@@ -105,6 +105,12 @@
MVK_ENC_REZ_ACCESS(_mtlFillBufferComputePipelineState, newCmdFillBufferMTLComputePipelineState());
}
+void MVKCommandEncodingPool::clear() {
+ lock_guard<mutex> lock(_lock);
+ destroyMetalResources();
+}
+
+
#pragma mark Construction
MVKCommandEncodingPool::MVKCommandEncodingPool(MVKDevice* device) : MVKBaseDeviceObject(device),
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
index e8278b4..5ded1d5 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
@@ -19,6 +19,7 @@
#pragma once
#include "MVKDevice.h"
+#include "MVKCommandBuffer.h"
#include "MVKCommandResourceFactory.h"
#include "MVKCommandEncodingPool.h"
#include "MVKCommand.h"
@@ -169,12 +170,10 @@
~MVKCommandPool() override;
-private:
- friend class MVKCommandBuffer;
+protected:
+ void freeCommandBuffer(MVKCommandBuffer* mvkCmdBuff);
- void addCommandBuffer(MVKCommandBuffer* cmdBuffer);
- void removeCommandBuffer(MVKCommandBuffer* cmdBuffer);
-
+ MVKCommandBufferPool _commandBufferPool;
std::unordered_set<MVKCommandBuffer*> _commandBuffers;
MVKCommandEncodingPool _commandEncodingPool;
uint32_t _queueFamilyIndex;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
index d33b9e5..559b348 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
@@ -33,9 +33,14 @@
// Reset all of the command buffers
VkResult MVKCommandPool::reset(VkCommandPoolResetFlags flags) {
- for (auto& cb : _commandBuffers) {
- cb->reset(VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
- }
+ bool releaseRez = mvkAreFlagsEnabled(flags, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
+
+ VkCommandBufferResetFlags cmdBuffFlags = releaseRez ? VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT : 0;
+
+ for (auto& cb : _commandBuffers) { cb->reset(cmdBuffFlags); }
+
+ if (releaseRez) { trim(); }
+
return VK_SUCCESS;
}
@@ -47,7 +52,9 @@
VkResult rslt = VK_SUCCESS;
uint32_t cbCnt = pAllocateInfo->commandBufferCount;
for (uint32_t cbIdx = 0; cbIdx < cbCnt; cbIdx++) {
- MVKCommandBuffer* mvkCmdBuff = new MVKCommandBuffer(_device, pAllocateInfo);
+ MVKCommandBuffer* mvkCmdBuff = _commandBufferPool.acquireObject();
+ mvkCmdBuff->init(pAllocateInfo);
+ _commandBuffers.insert(mvkCmdBuff);
pCmdBuffer[cbIdx] = mvkCmdBuff->getVkCommandBuffer();
if (rslt == VK_SUCCESS) { rslt = mvkCmdBuff->getConfigurationResult(); }
}
@@ -57,25 +64,66 @@
void MVKCommandPool::freeCommandBuffers(uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers) {
for (uint32_t cbIdx = 0; cbIdx < commandBufferCount; cbIdx++) {
- VkCommandBuffer cmdBuff = pCommandBuffers[cbIdx];
- if (cmdBuff) { MVKCommandBuffer::getMVKCommandBuffer(cmdBuff)->destroy(); }
+ freeCommandBuffer(MVKCommandBuffer::getMVKCommandBuffer(pCommandBuffers[cbIdx]));
}
}
+void MVKCommandPool::freeCommandBuffer(MVKCommandBuffer* mvkCmdBuff) {
+ if ( !mvkCmdBuff ) { return; }
+
+ mvkCmdBuff->reset(VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
+ _commandBuffers.erase(mvkCmdBuff);
+ _commandBufferPool.returnObject(mvkCmdBuff);
+}
+
id<MTLCommandBuffer> MVKCommandPool::newMTLCommandBuffer(uint32_t queueIndex) {
return [[_device->getQueue(_queueFamilyIndex, queueIndex)->getMTLCommandQueue() commandBuffer] retain];
}
void MVKCommandPool::trim() {
- // TODO: Implement.
-}
-
-void MVKCommandPool::addCommandBuffer(MVKCommandBuffer* cmdBuffer) {
- _commandBuffers.insert(cmdBuffer);
-}
-
-void MVKCommandPool::removeCommandBuffer(MVKCommandBuffer* cmdBuffer) {
- _commandBuffers.erase(cmdBuffer);
+ _commandBufferPool.clear();
+ _commandEncodingPool.clear();
+ _cmdPipelineBarrierPool.clear();
+ _cmdBindPipelinePool.clear();
+ _cmdBeginRenderPassPool.clear();
+ _cmdNextSubpassPool.clear();
+ _cmdExecuteCommandsPool.clear();
+ _cmdEndRenderPassPool.clear();
+ _cmdBindDescriptorSetsPool.clear();
+ _cmdSetViewportPool.clear();
+ _cmdSetScissorPool.clear();
+ _cmdSetLineWidthPool.clear();
+ _cmdSetDepthBiasPool.clear();
+ _cmdSetBlendConstantsPool.clear();
+ _cmdSetDepthBoundsPool.clear();
+ _cmdSetStencilCompareMaskPool.clear();
+ _cmdSetStencilWriteMaskPool.clear();
+ _cmdSetStencilReferencePool.clear();
+ _cmdBindVertexBuffersPool.clear();
+ _cmdBindIndexBufferPool.clear();
+ _cmdDrawPool.clear();
+ _cmdDrawIndexedPool.clear();
+ _cmdDrawIndirectPool.clear();
+ _cmdDrawIndexedIndirectPool.clear();
+ _cmdCopyImagePool.clear();
+ _cmdBlitImagePool.clear();
+ _cmdResolveImagePool.clear();
+ _cmdFillBufferPool.clear();
+ _cmdUpdateBufferPool.clear();
+ _cmdCopyBufferPool.clear();
+ _cmdBufferImageCopyPool.clear();
+ _cmdClearAttachmentsPool.clear();
+ _cmdClearImagePool.clear();
+ _cmdBeginQueryPool.clear();
+ _cmdEndQueryPool.clear();
+ _cmdWriteTimestampPool.clear();
+ _cmdResetQueryPoolPool.clear();
+ _cmdCopyQueryPoolResultsPool.clear();
+ _cmdPushConstantsPool.clear();
+ _cmdDispatchPool.clear();
+ _cmdDispatchIndirectPool.clear();
+ _cmdPushDescriptorSetPool.clear();
+ _cmdPushSetWithTemplatePool.clear();
}
@@ -83,6 +131,7 @@
MVKCommandPool::MVKCommandPool(MVKDevice* device,
const VkCommandPoolCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device),
+ _commandBufferPool(device),
_commandEncodingPool(device),
_queueFamilyIndex(pCreateInfo->queueFamilyIndex),
_cmdPipelineBarrierPool(this, true),
@@ -128,7 +177,8 @@
_cmdPushSetWithTemplatePool(this, true)
{}
-// TODO: Destroying a command pool implicitly destroys all command buffers and commands created from it.
-
-MVKCommandPool::~MVKCommandPool() {}
+MVKCommandPool::~MVKCommandPool() {
+ auto cmdBuffs = _commandBuffers;
+ for (auto& cb : cmdBuffs) { freeCommandBuffer(cb); }
+}
diff --git a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h
index 7bcf257..d315863 100644
--- a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h
+++ b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h
@@ -55,7 +55,7 @@
/**
* Instances of this class can participate in a linked list or pool. When so participating,
- * this is a reference to the next command in the linked list. This value should only be
+ * this is a reference to the next instance in the linked list. This value should only be
* managed and set by the linked list.
*/
MVKMTLBufferAllocation* _next = nullptr;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
index 4c9e41c..3b7efb1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
@@ -313,8 +313,8 @@
protected:
uint32_t _maxSets;
+ uint32_t _allocatedSetCount;
std::forward_list<MVKDescriptorSet*> _allocatedSets;
- size_t _allocatedSetCount;
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index 6377ce4..346dfaa 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -868,6 +868,7 @@
VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count,
const VkDescriptorSetLayout* pSetLayouts,
VkDescriptorSet* pDescriptorSets) {
+// MVKLogDebug("Descriptor pool %p allocating %d descriptor sets for total %d.", this, count, _allocatedSetCount + count);
if (_allocatedSetCount + count > _maxSets) {
if (_device->_enabledExtensions.vk_KHR_maintenance1.enabled) {
return VK_ERROR_OUT_OF_POOL_MEMORY; // Failure is an acceptable test...don't log as error.
@@ -888,6 +889,7 @@
}
VkResult MVKDescriptorPool::freeDescriptorSets(uint32_t count, const VkDescriptorSet* pDescriptorSets) {
+// MVKLogDebug("Descriptor pool %p freeing %d descriptor sets from total %d.", this, count, _allocatedSetCount);
for (uint32_t dsIdx = 0; dsIdx < count; dsIdx++) {
MVKDescriptorSet* mvkDS = (MVKDescriptorSet*)pDescriptorSets[dsIdx];
if (mvkDS) {
@@ -900,6 +902,7 @@
}
VkResult MVKDescriptorPool::reset(VkDescriptorPoolResetFlags flags) {
+// MVKLogDebug("Descriptor pool %p resetting with %d descriptor sets.", this, _allocatedSetCount);
mvkDestroyContainerContents(_allocatedSets);
_allocatedSetCount = 0;
return VK_SUCCESS;
@@ -909,12 +912,13 @@
const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
_maxSets = pCreateInfo->maxSets;
_allocatedSetCount = 0;
+// MVKLogDebug("Descriptor pool %p created with max %d sets.", this, _maxSets);
}
// TODO: Destroying a descriptor pool implicitly destroys all descriptor sets created from it.
MVKDescriptorPool::~MVKDescriptorPool() {
-// MVKLogDebug("Pool %p destroyed with %d descriptor sets.", this, _allocatedSetCount);
+// MVKLogDebug("Descriptor pool %p destroyed with %d descriptor sets.", this, _allocatedSetCount);
reset(0);
}
diff --git a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
index f15aeac..6827bf1 100644
--- a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
+++ b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
@@ -95,7 +95,7 @@
* This is the compliment of the getVkHandle() method.
*/
static inline MVKDispatchableObject* getDispatchableObject(void* vkHandle) {
- return ((MVKDispatchableObjectICDRef*)vkHandle)->mvkObject;
+ return vkHandle ? ((MVKDispatchableObjectICDRef*)vkHandle)->mvkObject : nullptr;
}
protected:
diff --git a/MoltenVK/MoltenVK/Utility/MVKObjectPool.h b/MoltenVK/MoltenVK/Utility/MVKObjectPool.h
index 4e243e4..ba0d09e 100644
--- a/MoltenVK/MoltenVK/Utility/MVKObjectPool.h
+++ b/MoltenVK/MoltenVK/Utility/MVKObjectPool.h
@@ -76,6 +76,8 @@
* aquireObject() and returnObject() must be made from the same thread.
*/
void returnObject(T* obj) {
+ if ( !obj ) { return; }
+
if (_isPooling) {
if (_tail) { _tail->_next = obj; }
obj->_next = VK_NULL_HANDLE;