| /* |
| * MVKBaseObject.h |
| * |
| * Copyright (c) 2015-2022 The Brenwill Workshop Ltd. (http://www.brenwill.com) |
| * |
| * 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 "vk_mvk_moltenvk.h" |
| #include <string> |
| #include <atomic> |
| |
| class MVKVulkanAPIObject; |
| |
| |
| #pragma mark - |
| #pragma mark MVKBaseObject |
| |
| /** |
| * An abstract base class for all MoltenVK C++ classes, to allow common object |
| * behaviour, and common custom allocation and deallocation behaviour. |
| */ |
| class MVKBaseObject { |
| |
| public: |
| |
| /** Returns the name of the class of which this object is an instance. */ |
| std::string getClassName(); |
| |
| /** Returns the Vulkan API opaque object controlling this object. */ |
| virtual MVKVulkanAPIObject* getVulkanAPIObject() = 0; |
| |
| /** |
| * Report a message. This includes logging to a standard system logging stream, |
| * and some subclasses will also forward the message to their VkInstance for |
| * output to the Vulkan debug report messaging API. |
| */ |
| void reportMessage(MVKConfigLogLevel logLevel, const char* format, ...) __printflike(3, 4); |
| |
| /** |
| * Report a Vulkan error message, on behalf of the object, which may be nil. |
| * Reporting includes logging to a standard system logging stream, and if the object |
| * is not nil and has access to the VkInstance, the message will also be forwarded |
| * to the VkInstance for output to the Vulkan debug report messaging API. |
| */ |
| static void reportMessage(MVKBaseObject* mvkObj, MVKConfigLogLevel logLevel, const char* format, ...) __printflike(3, 4); |
| |
| /** |
| * Report a Vulkan error message, on behalf of the object, which may be nil. |
| * Reporting includes logging to a standard system logging stream, and if the object |
| * is not nil and has access to the VkInstance, the message will also be forwarded |
| * to the VkInstance for output to the Vulkan debug report messaging API. |
| * |
| * This is the core reporting implementation. Other similar functions delegate here. |
| */ |
| static void reportMessage(MVKBaseObject* mvkObj, MVKConfigLogLevel logLevel, const char* format, va_list args) __printflike(3, 0); |
| |
| /** |
| * Report a Vulkan error message. This includes logging to a standard system logging stream, |
| * and some subclasses will also forward the message to their VkInstance for output to the |
| * Vulkan debug report messaging API. |
| */ |
| VkResult reportError(VkResult vkErr, const char* format, ...) __printflike(3, 4); |
| |
| /** |
| * Report a Vulkan error message, on behalf of the object. which may be nil. |
| * Reporting includes logging to a standard system logging stream, and if the object |
| * is not nil and has access to the VkInstance, the message will also be forwarded |
| * to the VkInstance for output to the Vulkan debug report messaging API. |
| */ |
| static VkResult reportError(MVKBaseObject* mvkObj, VkResult vkErr, const char* format, ...) __printflike(3, 4); |
| |
| /** |
| * Report a Vulkan error message, on behalf of the object. which may be nil. |
| * Reporting includes logging to a standard system logging stream, and if the object |
| * is not nil and has access to the VkInstance, the message will also be forwarded |
| * to the VkInstance for output to the Vulkan debug report messaging API. |
| * |
| * This is the core reporting implementation. Other similar functions delegate here. |
| */ |
| static VkResult reportError(MVKBaseObject* mvkObj, VkResult vkErr, const char* format, va_list args) __printflike(3, 0); |
| |
| /** Destroys this object. Default behaviour simply deletes it. Subclasses may override to delay deletion. */ |
| virtual void destroy() { delete this; } |
| |
| virtual ~MVKBaseObject() {} |
| }; |
| |
| |
| #pragma mark - |
| #pragma mark MVKReferenceCountingMixin |
| |
| /** |
| * 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 |
| */ |
| 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. |
| * |
| * Note that the destroy() function is called on the BaseClass. |
| * Releasing will not call any overridden destroy() function in a descendant class. |
| */ |
| 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. */ |
| VkResult getConfigurationResult() { return _configurationResult; } |
| |
| /** If the existing configuration result is VK_SUCCESS, it is set to the specified value. */ |
| void setConfigurationResult(VkResult vkResult) { |
| if (_configurationResult == VK_SUCCESS) { _configurationResult = vkResult; } |
| } |
| |
| /** Returns whether the configuration was successful. */ |
| bool wasConfigurationSuccessful() { return _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; |
| }; |