Merge pull request #1352 from billhollings/shader-config
Improvements to SPIRVToMSLConversionConfiguration
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
index 512c17a..68c5353 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
@@ -45,10 +45,10 @@
MVKVulkanAPIObject* getVulkanAPIObject() override { return _physicalDevice->getVulkanAPIObject(); }
/** Returns the index of this queue family. */
- inline uint32_t getIndex() { return _queueFamilyIndex; }
+ uint32_t getIndex() { return _queueFamilyIndex; }
/** Populates the specified properties structure. */
- inline void getProperties(VkQueueFamilyProperties* queueProperties) {
+ void getProperties(VkQueueFamilyProperties* queueProperties) {
if (queueProperties) { *queueProperties = _properties; }
}
@@ -98,13 +98,13 @@
VkResult waitIdle();
/** Return the name of this queue. */
- inline const std::string& getName() { return _name; }
+ const std::string& getName() { return _name; }
#pragma mark Metal
/** Returns the Metal queue underlying this queue. */
- inline id<MTLCommandQueue> getMTLCommandQueue() { return _mtlQueue; }
+ id<MTLCommandQueue> getMTLCommandQueue() { return _mtlQueue; }
/** Returns a Metal command buffer from the Metal queue. */
id<MTLCommandBuffer> getMTLCommandBuffer(bool retainRefs = false);
@@ -120,13 +120,13 @@
* Returns a reference to this object suitable for use as a Vulkan API handle.
* This is the compliment of the getMVKQueue() method.
*/
- inline VkQueue getVkQueue() { return (VkQueue)getVkHandle(); }
+ VkQueue getVkQueue() { return (VkQueue)getVkHandle(); }
/**
* Retrieves the MVKQueue instance referenced by the VkQueue handle.
* This is the compliment of the getVkQueue() method.
*/
- static inline MVKQueue* getMVKQueue(VkQueue vkQueue) {
+ static MVKQueue* getMVKQueue(VkQueue vkQueue) {
return (MVKQueue*)getDispatchableObject(vkQueue);
}
@@ -158,7 +158,7 @@
#pragma mark MVKQueueSubmission
/** This is an abstract class for an operation that can be submitted to an MVKQueue. */
-class MVKQueueSubmission : public MVKConfigurableObject {
+class MVKQueueSubmission : public MVKBaseObject, public MVKConfigurableMixin {
public:
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.h b/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.h
index cbb0219..837b13b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.h
@@ -20,8 +20,6 @@
#include "MVKBaseObject.h"
#include <vulkan/vk_icd.h>
-#include <string>
-#include <atomic>
#import <Foundation/NSString.h>
@@ -34,13 +32,11 @@
/**
* Abstract class that represents an opaque Vulkan API handle object.
*
- * API objects can sometimes be destroyed by the client before the GPU is done with them.
- * To support this, an object of this type will automatically be deleted iff it has been
- * destroyed by the client, and all references have been released. An object of this type
- * is therefore allowed to live past its destruction by the client, until it is no longer
- * referenced by other objects.
+ * Vulkan API objects can sometimes be destroyed by the client before the GPU is done with them.
+ * To support this, this class inherits from MVKReferenceCountingMixin to allow an instance to
+ * live past its destruction by the client, until it is no longer referenced by other objects.
*/
-class MVKVulkanAPIObject : public MVKConfigurableObject {
+class MVKVulkanAPIObject : public MVKReferenceCountingMixin<MVKBaseObject>, public MVKConfigurableMixin {
public:
@@ -59,29 +55,8 @@
/** Returns the Vulkan instance. */
virtual MVKInstance* getInstance() = 0;
- /**
- * Called when this instance has been retained as a reference by another object,
- * indicating that this instance will not be deleted until that reference is released.
- */
- inline void retain() { _refCount++; }
-
- /**
- * Called when this instance has been released as a reference from another object.
- * Once all references have been released, this object is free to be deleted.
- * If the destroy() function has already been called on this instance by the time
- * this function is called, this instance will be deleted.
- */
- inline void release() { if (--_refCount == 0) { MVKConfigurableObject::destroy(); } }
-
- /**
- * Marks this instance as destroyed. If all previous references to this instance
- * have been released, this instance will be deleted, otherwise deletion of this
- * instance will automatically be deferred until all references have been released.
- */
- void destroy() override { release(); }
-
/** Gets the debug object name of this instance. */
- inline NSString* getDebugName() { return _debugName; }
+ NSString* getDebugName() { return _debugName; }
/** Sets the debug object name of this instance. */
VkResult setDebugName(const char* pObjectName);
@@ -92,21 +67,14 @@
/** Returns the MVKVulkanAPIObject instance referenced by the object of the given type. */
static MVKVulkanAPIObject* getMVKVulkanAPIObject(VkObjectType objType, uint64_t objectHandle);
- /** Construct an empty instance. Declared here to support copy constructor. */
- MVKVulkanAPIObject() : _refCount(1) {}
-
- /** Default copy constructor disallowed due to mutex. Copy starts with fresh reference counts. */
+ MVKVulkanAPIObject() {}
MVKVulkanAPIObject(const MVKVulkanAPIObject& other);
-
- /** Default copy assignment disallowed due to mutex. Copy starts with fresh reference counts. */
MVKVulkanAPIObject& operator=(const MVKVulkanAPIObject& other);
-
~MVKVulkanAPIObject() override;
protected:
virtual void propagateDebugName() = 0;
- std::atomic<uint32_t> _refCount;
NSString* _debugName = nil;
};
@@ -143,7 +111,7 @@
*
* This is the compliment of the getVkHandle() function.
*/
- static inline MVKDispatchableVulkanAPIObject* getDispatchableObject(void* vkHandle) {
+ static MVKDispatchableVulkanAPIObject* getDispatchableObject(void* vkHandle) {
return vkHandle ? ((MVKDispatchableObjectICDRef*)vkHandle)->mvkObject : nullptr;
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.mm b/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.mm
index 5df32e1..64556b3 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKVulkanAPIObject.mm
@@ -62,13 +62,11 @@
}
MVKVulkanAPIObject::MVKVulkanAPIObject(const MVKVulkanAPIObject& other) {
- _refCount = 1;
_debugName = [other._debugName retain];
}
MVKVulkanAPIObject& MVKVulkanAPIObject::operator=(const MVKVulkanAPIObject& other) {
[_debugName release];
- _refCount = 1;
_debugName = [other._debugName retain];
return *this;
}
diff --git a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
index 44c6592..68012f3 100644
--- a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
+++ b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
@@ -20,6 +20,7 @@
#include "mvk_vulkan.h"
#include <string>
+#include <atomic>
class MVKVulkanAPIObject;
@@ -99,29 +100,94 @@
#pragma mark -
-#pragma mark MVKConfigurableObject
+#pragma mark MVKReferenceCountingMixin
-/**
- * Abstract class that represents an object whose configuration can be validated and tracked
- * as a queriable result. This is the base class of opaque Vulkan API objects, and commands.
+/**
+ * This templated mixin adds the ability for an object to track references
+ * to itself and defer destruction while existing references are alive.
+ *
+ * The BaseClass template parameter should derive from MVKBaseObject.
+ * or must otherwise declare a virtual destroy() function.
+ *
+ * To add this mixin to a class, subclass from this mixin template class, and
+ * set the template BaseClass to the nominal parent class of the class this is
+ * being added to. For example, if MySubClass nominally inherits from MyBaseClass,
+ * this mixin can be added to MySubClass by declaring MySubClass as follows:
+ *
+ * class MySubClass : public MVKReferenceCountingMixin<MyBaseClass>
+ *
+ * As noted, in this example, MyBaseClass should derive from MVKBaseObject,
+ * or must otherwise declare a virtual destroy() function
*/
-class MVKConfigurableObject : public MVKBaseObject {
+template <class BaseClass>
+class MVKReferenceCountingMixin : public BaseClass {
+
+public:
+
+ /**
+ * Called when this instance has been retained as a reference by another object,
+ * indicating that this instance will not be deleted until that reference is released.
+ */
+ void retain() { _refCount++; }
+
+ /**
+ * Called when this instance has been released as a reference from another object.
+ * Once all references have been released, this object is free to be deleted.
+ * If the destroy() function has already been called on this instance by the time
+ * this function is called, this instance will be deleted.
+ */
+ void release() { if (--_refCount == 0) { BaseClass::destroy(); } }
+
+ /**
+ * Marks this instance as destroyed. If all previous references to this instance
+ * have been released, this instance will be deleted, otherwise deletion of this
+ * instance will automatically be deferred until all references have been released.
+ */
+ void destroy() override { release(); }
+
+ MVKReferenceCountingMixin() : _refCount(1) {}
+
+ /** Copy starts with fresh reference counts. */
+ MVKReferenceCountingMixin(const MVKReferenceCountingMixin& other) {
+ _refCount = 1;
+ }
+
+ /** Copy starts with fresh reference counts. */
+ MVKReferenceCountingMixin& operator=(const MVKReferenceCountingMixin& other) {
+ _refCount = 1;
+ return *this;
+ }
+
+protected:
+ std::atomic<uint32_t> _refCount;
+
+};
+
+
+#pragma mark -
+#pragma mark MVKConfigurableMixin
+
+/**
+ * Mixin that can be added to a class whose instances are configured from Vulkan configuration
+ * info, and the result of which can be validated and tracked as a queriable Vulkan VkResult.
+ */
+class MVKConfigurableMixin {
public:
/** Returns a indication of the success of the configuration of this instance. */
- inline VkResult getConfigurationResult() { return _configurationResult; }
+ VkResult getConfigurationResult() { return _configurationResult; }
/** If the existing configuration result is VK_SUCCESS, it is set to the specified value. */
- inline void setConfigurationResult(VkResult vkResult) {
- if (_configurationResult == VK_SUCCESS) { _configurationResult = vkResult; }
- }
+ void setConfigurationResult(VkResult vkResult) {
+ if (_configurationResult == VK_SUCCESS) { _configurationResult = vkResult; }
+ }
/** Returns whether the configuration was successful. */
- inline bool wasConfigurationSuccessful() { return _configurationResult == VK_SUCCESS; }
+ bool wasConfigurationSuccessful() { return _configurationResult == VK_SUCCESS; }
- /** Resets the indication of the success of the configuration of this instance back to VK_SUCCESS. */
- inline void clearConfigurationResult() { _configurationResult = VK_SUCCESS; }
+ /** Resets the indication of the success of the configuration of this instance back to VK_SUCCESS. */
+ void clearConfigurationResult() { _configurationResult = VK_SUCCESS; }
protected:
VkResult _configurationResult = VK_SUCCESS;