blob: 2b514ad5a8d9ed5e202dadde021ddc78a0ec712a [file] [log] [blame]
/*
* MVKLayers.mm
*
* Copyright (c) 2014-2018 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.
*/
#include "MVKLayers.h"
#include "MVKEnvironment.h"
#include "vk_mvk_moltenvk.h"
#include <mutex>
using namespace std;
#pragma mark MVKLayer
const char* MVKLayer::getName() { return (const char*)&_layerProperties.layerName; }
VkLayerProperties* const MVKLayer::getLayerProperties() { return &_layerProperties; }
VkResult MVKLayer::getExtensionProperties(uint32_t* pCount, VkExtensionProperties* pProperties) {
// If properties aren't actually being requested yet, simply update the returned count
if ( !pProperties ) {
*pCount = (uint32_t)_extensions.size();
return VK_SUCCESS;
}
// Othewise, determine how many extensions we'll return, and return that count
uint32_t extCnt = (uint32_t)_extensions.size();
VkResult result = (*pCount <= extCnt) ? VK_SUCCESS : VK_INCOMPLETE;
*pCount = min(extCnt, *pCount);
// Now populate the layer properties
for (uint32_t extIdx = 0; extIdx < *pCount; extIdx++) {
pProperties[extIdx] = _extensions[extIdx];
}
return result;
}
bool MVKLayer::hasExtensionNamed(const char* extnName) {
for (auto& extn : _extensions) {
if ( strcmp(extn.extensionName, extnName) == 0 ) { return true; }
}
return false;
}
#pragma mark Object Creation
MVKLayer::MVKLayer() {
// The core driver layer
strcpy(_layerProperties.layerName, "MoltenVK");
strcpy(_layerProperties.description, "MoltenVK driver layer");
_layerProperties.specVersion = MVK_VULKAN_API_VERSION;
_layerProperties.implementationVersion = MVK_VERSION;
// Extensions
VkExtensionProperties extTmplt;
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_MVK_MOLTENVK_EXTENSION_NAME);
extTmplt.specVersion = VK_MVK_MOLTENVK_SPEC_VERSION;
_extensions.push_back(extTmplt);
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
extTmplt.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
_extensions.push_back(extTmplt);
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_KHR_SURFACE_EXTENSION_NAME);
extTmplt.specVersion = VK_KHR_SURFACE_SPEC_VERSION;
_extensions.push_back(extTmplt);
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME);
extTmplt.specVersion = VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION;
_extensions.push_back(extTmplt);
#if MVK_IOS
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_MVK_IOS_SURFACE_EXTENSION_NAME);
extTmplt.specVersion = VK_MVK_IOS_SURFACE_SPEC_VERSION;
_extensions.push_back(extTmplt);
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_IMG_FORMAT_PVRTC_EXTENSION_NAME);
extTmplt.specVersion = VK_IMG_FORMAT_PVRTC_SPEC_VERSION;
_extensions.push_back(extTmplt);
#endif
#if MVK_MACOS
memset(extTmplt.extensionName, 0, sizeof(extTmplt.extensionName));
strcpy(extTmplt.extensionName, VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
extTmplt.specVersion = VK_MVK_MACOS_SURFACE_SPEC_VERSION;
_extensions.push_back(extTmplt);
#endif
}
#pragma mark MVKLayerManager
MVKLayer* MVKLayerManager::getDriverLayer() { return &(_layers[0]); }
MVKLayer* MVKLayerManager::getLayerNamed(const char* pLayerName) {
// If name is null, return the driver layer
if ( !pLayerName ) { return getDriverLayer(); }
// Otherwise look for a layer with the specified name
uint32_t layCnt = (uint32_t)_layers.size();
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
MVKLayer* pLayer = &_layers[layIdx];
if ( strcmp(pLayer->getName(), pLayerName) == 0 ) { return pLayer; }
}
return VK_NULL_HANDLE;
}
VkResult MVKLayerManager::getLayerProperties(uint32_t* pCount, VkLayerProperties* pProperties) {
// If properties aren't actually being requested yet, simply update the returned count
if ( !pProperties ) {
*pCount = (uint32_t)_layers.size();
return VK_SUCCESS;
}
// Othewise, determine how many layers we'll return, and return that count
uint32_t layerCnt = (uint32_t)_layers.size();
VkResult result = (*pCount <= layerCnt) ? VK_SUCCESS : VK_INCOMPLETE;
*pCount = min(layerCnt, *pCount);
// Now populate the layer properties
for (uint32_t layIdx = 0; layIdx < *pCount; layIdx++) {
pProperties[layIdx] = *(&_layers[layIdx])->getLayerProperties();
}
return result;
}
#pragma mark Object Creation
// Populate the layers
MVKLayerManager::MVKLayerManager() {
_layers.push_back(MVKLayer());
}
static mutex _lock;
static MVKLayerManager* _globalManager = VK_NULL_HANDLE;
MVKLayerManager* MVKLayerManager::globalManager() {
lock_guard<mutex> lock(_lock);
if ( !_globalManager ) { _globalManager = new MVKLayerManager(); }
return _globalManager;
}