blob: ccdf4bcecbda8772c8aa2ce6ce78c71e4a963543 [file] [log] [blame]
/*
* MVKBaseObject.h
*
* Copyright (c) 2014-2019 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 "mvk_vulkan.h"
#include <vulkan/vk_icd.h>
#include <string>
#include <mutex>
class MVKInstance;
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(int aslLvl, 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, int aslLvl, 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, int aslLvl, 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 MVKConfigurableObject
/**
* 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.
*/
class MVKConfigurableObject : public MVKBaseObject {
public:
/** Returns a indication of the success of the configuration of this instance. */
inline 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; }
}
/** Resets the indication of the success of the configuration of this instance back to VK_SUCCESS. */
inline void clearConfigurationResult() { _configurationResult = VK_SUCCESS; }
protected:
VkResult _configurationResult = VK_SUCCESS;
};
#pragma mark -
#pragma mark MVKVulkanAPIObject
/**
* 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.
*/
class MVKVulkanAPIObject : public MVKConfigurableObject {
public:
/** Returns the Vulkan API opaque object controlling this object. */
MVKVulkanAPIObject* getVulkanAPIObject() override { return this; };
/** Returns a reference to this object suitable for use as a Vulkan API handle. */
virtual void* getVkHandle() { return this; }
/** Returns the debug report object type of this object. */
virtual VkDebugReportObjectTypeEXT getVkDebugReportObjectType() = 0;
/** 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.
*/
void retain();
/**
* 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();
/**
* 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;
/** Construct an empty instance. Declared here to support copy constructor. */
MVKVulkanAPIObject() {}
/**
* Construct an instance from a copy. Default copy constructor disallowed due to mutex.
* Copies start with fresh reference counts.
*/
MVKVulkanAPIObject(const MVKVulkanAPIObject& other) {}
protected:
bool decrementRetainCount();
bool markDestroyed();
std::mutex _refLock;
unsigned _refCount = 0;
bool _isDestroyed = false;
};
#pragma mark -
#pragma mark MVKDispatchableVulkanAPIObject
/** Abstract class that represents a dispatchable opaque Vulkan API handle object. */
class MVKDispatchableVulkanAPIObject : public MVKVulkanAPIObject {
typedef struct {
VK_LOADER_DATA loaderData;
MVKDispatchableVulkanAPIObject* mvkObject;
} MVKDispatchableObjectICDRef;
public:
/**
* Returns a reference to this object suitable for use as a Vulkan API handle.
* This is the compliment of the getDispatchableObject() method.
*/
void* getVkHandle() override { return &_icdRef; }
/**
* Retrieves the MVKDispatchableVulkanAPIObject instance referenced by the dispatchable Vulkan handle.
* This is the compliment of the getVkHandle() method.
*/
static inline MVKDispatchableVulkanAPIObject* getDispatchableObject(void* vkHandle) {
return vkHandle ? ((MVKDispatchableObjectICDRef*)vkHandle)->mvkObject : nullptr;
}
protected:
MVKDispatchableObjectICDRef _icdRef = { ICD_LOADER_MAGIC, this };
};