blob: d8758ee63c489cb65dfe2d7dbc9010b5889864c4 [file] [log] [blame]
/*
* MVKInstance.h
*
* Copyright (c) 2015-2021 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 "MVKEnvironment.h"
#include "MVKLayers.h"
#include "MVKVulkanAPIObject.h"
#include "MVKSmallVector.h"
#include <unordered_map>
#include <string>
#include <mutex>
class MVKPhysicalDevice;
class MVKDevice;
class MVKSurface;
class MVKDebugReportCallback;
class MVKDebugUtilsMessenger;
/** Tracks info about entry point function pointer addresses. */
typedef struct MVKEntryPoint {
PFN_vkVoidFunction functionPointer;
uint32_t apiVersion;
const char* ext1Name;
const char* ext2Name;
bool isDevice;
bool isCore() { return !ext1Name && !ext2Name; }
bool isEnabled(uint32_t enabledVersion, const MVKExtensionList& extList) {
return ((isCore() && MVK_VULKAN_API_VERSION_CONFORM(enabledVersion) >= apiVersion) ||
extList.isEnabled(ext1Name) || extList.isEnabled(ext2Name));
}
} MVKEntryPoint;
#pragma mark -
#pragma mark MVKInstance
/** Represents a Vulkan instance. */
class MVKInstance : public MVKDispatchableVulkanAPIObject {
public:
/** Returns the Vulkan type of this object. */
VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_INSTANCE; }
/** Returns the debug report object type of this object. */
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; }
/** Returns a pointer to the Vulkan instance. */
MVKInstance* getInstance() override { return this; }
/** Returns the maximum version of Vulkan the application supports. */
inline uint32_t getAPIVersion() { return _appInfo.apiVersion; }
/** Returns a pointer to the layer manager. */
inline MVKLayerManager* getLayerManager() { return MVKLayerManager::globalManager(); }
/** Returns the function pointer corresponding to the named entry point, or NULL if it doesn't exist. */
PFN_vkVoidFunction getProcAddr(const char* pName);
/** Returns the number of available physical devices. */
uint32_t getPhysicalDeviceCount() { return (uint32_t)_physicalDevices.size(); }
/**
* If pPhysicalDevices is null, the value of pCount is updated with the number of
* physical devices supported by this instance.
*
* If pPhysicalDevices is not null, then pCount physical devices are copied into the array.
* If the number of available physical devices is less than pCount, the value of pCount is
* updated to indicate the number of physical devices actually returned in the array.
*
* Returns VK_SUCCESS if successful. Returns VK_INCOMPLETE if the number of physical
* devices available in this instance is larger than the specified pCount. Returns other
* values if an error occurs.
*/
VkResult getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPhysicalDevices);
/**
* If pPhysicalDeviceGroups is null, the value of pCount is updated with the number of
* physical device groups supported by this instance.
*
* If pPhysicalDeviceGroups is not null, then pCount physical device groups are copied into the array.
* If the number of available physical device groups is less than pCount, the value of pCount is
* updated to indicate the number of physical device groups actually returned in the array.
*
* Returns VK_SUCCESS if successful. Returns VK_INCOMPLETE if the number of physical
* device groups available in this instance is larger than the specified pCount. Returns other
* values if an error occurs.
*/
VkResult getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps);
/** Returns the driver layer. */
MVKLayer* getDriverLayer() { return getLayerManager()->getDriverLayer(); }
MVKSurface* createSurface(const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
MVKSurface* createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
void destroySurface(MVKSurface* mvkSrfc,
const VkAllocationCallbacks* pAllocator);
MVKDebugReportCallback* createDebugReportCallback(const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
void destroyDebugReportCallback(MVKDebugReportCallback* mvkDRCB,
const VkAllocationCallbacks* pAllocator);
void debugReportMessage(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
size_t location,
int32_t messageCode,
const char* pLayerPrefix,
const char* pMessage);
MVKDebugUtilsMessenger* createDebugUtilsMessenger(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
void destroyDebugUtilsMessenger(MVKDebugUtilsMessenger* mvkDUM,
const VkAllocationCallbacks* pAllocator);
void debugUtilsMessage(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData);
void debugReportMessage(MVKVulkanAPIObject* mvkAPIObj, int aslLvl, const char* pMessage);
/** Returns whether debug callbacks are being used. */
bool hasDebugCallbacks() { return _hasDebugReportCallbacks || _hasDebugUtilsMessengers; }
/** The list of Vulkan extensions, indicating whether each has been enabled by the app. */
const MVKExtensionList _enabledExtensions;
#pragma mark Object Creation
/** Constructs an instance from the specified instance config. */
MVKInstance(const VkInstanceCreateInfo* pCreateInfo);
~MVKInstance() override;
/**
* Returns a reference to this object suitable for use as a Vulkan API handle.
* This is the compliment of the getMVKInstance() method.
*/
inline VkInstance getVkInstance() { return (VkInstance)getVkHandle(); }
/**
* Retrieves the MVKInstance instance referenced by the VkInstance handle.
* This is the compliment of the getVkInstance() method.
*/
static inline MVKInstance* getMVKInstance(VkInstance vkInstance) {
return (MVKInstance*)getDispatchableObject(vkInstance);
}
protected:
friend MVKDevice;
void propagateDebugName() override {}
void initProcAddrs();
void initDebugCallbacks(const VkInstanceCreateInfo* pCreateInfo);
NSArray<id<MTLDevice>>* getAvailableMTLDevicesArray();
VkDebugReportFlagsEXT getVkDebugReportFlagsFromASLLevel(int aslLvl);
VkDebugUtilsMessageSeverityFlagBitsEXT getVkDebugUtilsMessageSeverityFlagBitsFromASLLevel(int aslLvl);
MVKEntryPoint* getEntryPoint(const char* pName);
void logVersions();
VkResult verifyLayers(uint32_t count, const char* const* names);
VkApplicationInfo _appInfo;
MVKSmallVector<MVKPhysicalDevice*, 2> _physicalDevices;
MVKSmallVector<MVKDebugReportCallback*> _debugReportCallbacks;
MVKSmallVector<MVKDebugUtilsMessenger*> _debugUtilMessengers;
std::unordered_map<std::string, MVKEntryPoint> _entryPoints;
std::mutex _dcbLock;
bool _hasDebugReportCallbacks;
bool _hasDebugUtilsMessengers;
bool _useCreationCallbacks;
const char* _debugReportCallbackLayerPrefix;
};
#pragma mark -
#pragma mark MVKDebugReportCallback
/** Represents a Vulkan Debug Report callback. */
class MVKDebugReportCallback : public MVKVulkanAPIObject {
public:
/** Returns the Vulkan type of this object. */
VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT; }
/** Returns the debug report object type of this object. */
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT; }
/** Returns a pointer to the Vulkan instance. */
MVKInstance* getInstance() override { return _mvkInstance; }
MVKDebugReportCallback(MVKInstance* mvkInstance,
const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
bool isCreationCallback) :
_mvkInstance(mvkInstance),
_info(*pCreateInfo),
_isCreationCallback(isCreationCallback) {
_info.pNext = nullptr;
}
protected:
friend MVKInstance;
void propagateDebugName() override {}
MVKInstance* _mvkInstance;
VkDebugReportCallbackCreateInfoEXT _info;
bool _isCreationCallback;
};
#pragma mark -
#pragma mark MVKDebugUtilsMessenger
/** Represents a Vulkan Debug Utils callback. */
class MVKDebugUtilsMessenger : public MVKVulkanAPIObject {
public:
/** Returns the Vulkan type of this object. */
VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT; }
/** Returns the debug report object type of this object. */
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; }
/** Returns a pointer to the Vulkan instance. */
MVKInstance* getInstance() override { return _mvkInstance; }
MVKDebugUtilsMessenger(MVKInstance* mvkInstance,
const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
bool isCreationCallback) :
_mvkInstance(mvkInstance),
_info(*pCreateInfo),
_isCreationCallback(isCreationCallback) {
_info.pNext = nullptr;
}
protected:
friend MVKInstance;
void propagateDebugName() override {}
MVKInstance* _mvkInstance;
VkDebugUtilsMessengerCreateInfoEXT _info;
bool _isCreationCallback;
};