Merge pull request #654 from billhollings/master

Support VK_EXT_metal_surface extension.
This commit is contained in:
Bill Hollings 2019-07-03 23:53:41 -04:00 committed by GitHub
commit 46bea62230
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 101 additions and 77 deletions

View File

@ -32,7 +32,7 @@ static UIView* sampleView; // Global variable to pass UIView to LunarG sample c
* Initialize sample from view, and resize view in accordance with the sample.
*/
void init_window(struct sample_info &info) {
info.window = sampleView;
info.window = sampleView.layer;
sampleView.bounds = CGRectMake(0, 0, info.width, info.height);
}

View File

@ -33,7 +33,7 @@ static NSView* sampleView; // Global variable to pass NSView to LunarG sample c
* Initialize sample from view, and resize view in accordance with the sample.
*/
void init_window(struct sample_info &info) {
info.window = sampleView;
info.window = sampleView.layer;
sampleView.bounds = CGRectMake(0, 0, info.width, info.height);
}

View File

@ -43,7 +43,7 @@
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
const char* arg = "cube";
demo_main(&demo, self.view, 1, &arg);
demo_main(&demo, self.view.layer, 1, &arg);
demo_draw(&demo);
uint32_t fps = 60;

View File

@ -43,7 +43,7 @@
self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method.
const char* arg = "cube";
demo_main(&demo, self.view, 1, &arg);
demo_main(&demo, self.view.layer, 1, &arg);
CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, &demo);

View File

@ -48,12 +48,7 @@ ShellMVK::ShellMVK(Game& game) : Shell(game)
_profile_start_time = _current_time;
_profile_present_count = 0;
#ifdef VK_USE_PLATFORM_IOS_MVK
instance_extensions_.push_back(VK_MVK_IOS_SURFACE_EXTENSION_NAME);
#endif
#ifdef VK_USE_PLATFORM_MACOS_MVK
instance_extensions_.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
#endif
instance_extensions_.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
init_vk();
}
@ -78,22 +73,12 @@ VkSurfaceKHR ShellMVK::create_surface(VkInstance instance) {
VkSurfaceKHR surface;
VkResult err;
#ifdef VK_USE_PLATFORM_IOS_MVK
VkIOSSurfaceCreateInfoMVK surface_info;
surface_info.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
VkMetalSurfaceCreateInfoEXT surface_info;
surface_info.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
surface_info.pNext = NULL;
surface_info.flags = 0;
surface_info.pView = _view;
err = vkCreateIOSSurfaceMVK(instance, &surface_info, NULL, &surface);
#endif
#ifdef VK_USE_PLATFORM_MACOS_MVK
VkMacOSSurfaceCreateInfoMVK surface_info;
surface_info.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
surface_info.pNext = NULL;
surface_info.flags = 0;
surface_info.pView = _view;
err = vkCreateMacOSSurfaceMVK(instance, &surface_info, NULL, &surface);
#endif
surface_info.pLayer = _caMetalLayer;
err = vkCreateMetalSurfaceEXT(instance, &surface_info, NULL, &surface);
assert(!err);
return surface;
@ -124,8 +109,8 @@ void ShellMVK::update_and_draw() {
}
}
void ShellMVK::run(void* view) {
_view = view; // not retained
void ShellMVK::run(void* caMetalLayer) {
_caMetalLayer = caMetalLayer; // not retained
create_context();
resize_swapchain(settings_.initial_width, settings_.initial_height);
}

View File

@ -49,7 +49,7 @@ public:
void quit() { }
protected:
void* _view;
void* _caMetalLayer;
PosixTimer _timer;
double _current_time;
double _profile_start_time;

View File

@ -45,12 +45,12 @@
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
std::vector<std::string> args;
args.push_back("-p"); // Use push constants
args.push_back("-p"); // Use push constants
// args.push_back("-s"); // Use a single thread
_game = new Hologram(args);
_shell = new ShellMVK(*_game);
_shell->run(self.view);
_shell->run(self.view.layer);
uint32_t fps = 60;
_displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderLoop)];

View File

@ -46,12 +46,12 @@
self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method.
std::vector<std::string> args;
// args.push_back("-p"); // Uncomment to use push constants
args.push_back("-p"); // Uncomment to use push constants
// args.push_back("-s"); // Uncomment to use a single thread
_game = new Hologram(args);
_shell = new ShellMVK(*_game);
_shell->run(self.view);
_shell->run(self.view.layer);
CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, _shell);

View File

@ -253,36 +253,23 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
- `VK_EXT_debug_utils`
- `VK_EXT_host_query_reset`
- `VK_EXT_memory_budget`
- `VK_EXT_metal_surface`
- `VK_EXT_shader_viewport_index_layer`
- `VK_EXT_vertex_attribute_divisor`
- `VK_EXTX_portability_subset`
- `VK_MVK_ios_surface` (iOS)
- `VK_MVK_macos_surface` (macOS)
- `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
- `VK_MVK_macos_surface` *(macOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
- `VK_MVK_moltenvk`
- `VK_AMD_gpu_shader_half_float`
- `VK_AMD_negative_viewport_height`
- `VK_IMG_format_pvrtc` (iOS)
- `VK_IMG_format_pvrtc` *(iOS)*
- `VK_NV_glsl_shader`
In order to visibly display your content on *iOS* or *macOS*, you must enable the `VK_MVK_ios_surface`
or `VK_MVK_macos_surface` extension, respectively, and use the functions defined for that extension
to create a *Vulkan* rendering surface.
You can enable each of these extensions by defining the `VK_USE_PLATFORM_IOS_MVK` or
`VK_USE_PLATFORM_MACOS_MVK` guard macro in your compiler build settings. See the description
of the `mvk_vulkan.h` file below for a convenient way to enable these extensions automatically.
When using the `VK_MVK_macos_surface ` extension, the `pView` member of the `VkMacOSSurfaceCreateInfoMVK`
structure passed in the `vkCreateMacOSSurfaceMVK` function can be either an `NSView` whose layer is a
`CAMetalLayer`, or the `CAMetalLayer` itself. Passing the `CAMetalLayer` itself is recommended when
calling the `vkCreateMacOSSurfaceMVK` function from outside the main application thread, as `NSView`
should only be accessed from the main application thread.
When using the `VK_MVK_ios_surface ` extension, the `pView` member of the `VkIOSSurfaceCreateInfoMVK`
structure passed in the `vkCreateIOSSurfaceMVK` function can be either a `UIView` whose layer is a
`CAMetalLayer`, or the `CAMetalLayer` itself. Passing the `CAMetalLayer` itself is recommended when
calling the `vkCreateIOSSurfaceMVK ` function from outside the main application thread, as `UIView`
should only be accessed from the main application thread.
In order to visibly display your content on *iOS* or *macOS*, you must enable the `VK_EXT_metal_surface`
extension, and use the function defined in that extension to create a *Vulkan* rendering surface.
You can enable the `VK_EXT_metal_surface` extension by defining the `VK_USE_PLATFORM_METAL_EXT`
guard macro in your compiler build settings. See the description of the `mvk_vulkan.h` file below for
a convenient way to enable this extension automatically.
<a name="moltenvk_extension"></a>
@ -308,10 +295,8 @@ where `HEADER_FILE` is one of the following:
enabled for *iOS* or *macOS*. Use this header file in place of the `vulkan.h` header file,
where access to a **MoltenVK** platform surface extension is required.
- When building for *iOS*, the `mvk_vulkan.h` header file automatically enables the
`VK_USE_PLATFORM_IOS_MVK` build setting and `VK_MVK_ios_surface` *Vulkan* extension.
- When building for *macOS*, the `mvk_vulkan.h` header file automatically enables the
`VK_USE_PLATFORM_MACOS_MVK` build setting and `VK_MVK_macos_surface` *Vulkan* extension.
The `mvk_vulkan.h` header file automatically enables the `VK_USE_PLATFORM_METAL_EXT`
build setting and `VK_EXT_metal_surface` *Vulkan* extension.
- `mvk_datatypes.h` - Contains helpful functions for converting between *Vulkan* and *Metal* data types.
You do not need to use this functionality to use **MoltenVK**, as **MoltenVK** converts between

View File

@ -18,6 +18,8 @@ MoltenVK 1.0.36
Released TBD
- Add support for extensions:
- `VK_EXT_metal_surface`
- For shaders created directly from MSL, set function name from
`VkPipelineShaderStageCreateInfo::pName`.
- On iOS GPU family 2 and earlier, support immutable depth-compare samplers

View File

@ -18,11 +18,13 @@
/**
* This is a convenience header file that loads vulkan.h with the appropriate MoltenVK
* Vulkan platform extensions automatically enabled for iOS or macOS.
* This is a convenience header file that loads vulkan.h with the appropriate Vulkan platform extensions.
*
* When building for iOS, this header automatically enables the VK_MVK_ios_surface Vulkan extension.
* When building for macOS, this header automatically enables the VK_MVK_macos_surface Vulkan extension.
* This header automatically enables the VK_EXT_metal_surface Vulkan extension.
*
* When building for iOS, this header also automatically enables the obsolete VK_MVK_ios_surface Vulkan extension.
* When building for macOS, this header also automatically enables the obsolete VK_MVK_macos_surface Vulkan extension.
* Both of these extensions are obsolete. Consider using the portable VK_EXT_metal_surface extension instead.
*/
#ifndef __mvk_vulkan_h_
@ -31,6 +33,8 @@
#include <Availability.h>
#define VK_USE_PLATFORM_METAL_EXT 1
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
# define VK_USE_PLATFORM_IOS_MVK 1
#endif

View File

@ -88,6 +88,9 @@ public:
/** Returns the driver layer. */
MVKLayer* getDriverLayer() { return MVKLayerManager::globalManager()->getDriverLayer(); }
MVKSurface* createSurface(const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
MVKSurface* createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator);

View File

@ -70,6 +70,11 @@ VkResult MVKInstance::getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPh
return result;
}
MVKSurface* MVKInstance::createSurface(const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator) {
return new MVKSurface(this, pCreateInfo, pAllocator);
}
MVKSurface* MVKInstance::createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator) {
return new MVKSurface(this, pCreateInfo, pAllocator);
@ -540,6 +545,7 @@ void MVKInstance::initProcAddrs() {
ADD_INST_EXT_ENTRY_POINT(vkCreateDebugUtilsMessengerEXT, EXT_DEBUG_UTILS);
ADD_INST_EXT_ENTRY_POINT(vkDestroyDebugUtilsMessengerEXT, EXT_DEBUG_UTILS);
ADD_INST_EXT_ENTRY_POINT(vkSubmitDebugUtilsMessageEXT, EXT_DEBUG_UTILS);
ADD_INST_EXT_ENTRY_POINT(vkCreateMetalSurfaceEXT, EXT_METAL_SURFACE);
#ifdef VK_USE_PLATFORM_IOS_MVK
ADD_INST_EXT_ENTRY_POINT(vkCreateIOSSurfaceMVK, MVK_IOS_SURFACE);

View File

@ -65,6 +65,10 @@ public:
#pragma mark Construction
MVKSurface(MVKInstance* mvkInstance,
const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
MVKSurface(MVKInstance* mvkInstance,
const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
@ -73,6 +77,7 @@ public:
protected:
void propogateDebugName() override {}
void initLayerObserver();
MVKInstance* _mvkInstance;
CAMetalLayer* _mtlCAMetalLayer;

View File

@ -23,16 +23,28 @@
#include "MVKOSExtensions.h"
#import "MVKBlockObserver.h"
#define STR(NAME) #NAME
// We need to double-dereference the name to first convert to the platform symbol, then to a string.
#define STR_PLATFORM(NAME) #NAME
#define STR(NAME) STR_PLATFORM(NAME)
#pragma mark MVKSurface
MVKSurface::MVKSurface(MVKInstance* mvkInstance,
const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator) : _mvkInstance(mvkInstance) {
_mtlCAMetalLayer = (CAMetalLayer*)[pCreateInfo->pLayer retain];
initLayerObserver();
}
// pCreateInfo->pView can be either a CAMetalLayer or a view (NSView/UIView).
MVKSurface::MVKSurface(MVKInstance* mvkInstance,
const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator) : _mvkInstance(mvkInstance) {
MVKLogInfo("%s(): This function is obsolete. Consider using the vkCreateMetalSurfaceEXT() function from the VK_EXT_metal_surface extension instead.", STR(vkCreate_PLATFORM_SurfaceMVK));
// Get the platform object contained in pView
id<NSObject> obj = (id<NSObject>)pCreateInfo->pView;
@ -45,30 +57,34 @@ MVKSurface::MVKSurface(MVKInstance* mvkInstance,
obj = ((PLATFORM_VIEW_CLASS*)obj).layer;
}
_layerObserver = nil;
// Confirm that we were provided with a CAMetalLayer
if ([obj isKindOfClass: [CAMetalLayer class]]) {
_mtlCAMetalLayer = (CAMetalLayer*)[obj retain]; // retained
if ([_mtlCAMetalLayer.delegate isKindOfClass: [PLATFORM_VIEW_CLASS class]]) {
// Sometimes, the owning view can replace its CAMetalLayer. In that case, the client
// needs to recreate the surface.
_layerObserver = [MVKBlockObserver observerWithBlock: ^(NSString* path, id, NSDictionary*, void*) {
if ( ![path isEqualToString: @"layer"] ) { return; }
std::lock_guard<std::mutex> lock(this->_lock);
[this->_mtlCAMetalLayer release];
this->_mtlCAMetalLayer = nil;
this->setConfigurationResult(VK_ERROR_SURFACE_LOST_KHR);
[this->_layerObserver release];
this->_layerObserver = nil;
} forObject: _mtlCAMetalLayer.delegate atKeyPath: @"layer"];
}
} else {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
"%s(): On-screen rendering requires a layer of type CAMetalLayer.",
STR(vkCreate_PLATFORM_SurfaceMVK)));
_mtlCAMetalLayer = nil;
}
initLayerObserver();
}
// Sometimes, the owning view can replace its CAMetalLayer. In that case, the client needs to recreate the surface.
void MVKSurface::initLayerObserver() {
_layerObserver = nil;
if ( ![_mtlCAMetalLayer.delegate isKindOfClass: [PLATFORM_VIEW_CLASS class]] ) { return; }
_layerObserver = [MVKBlockObserver observerWithBlock: ^(NSString* path, id, NSDictionary*, void*) {
if ( ![path isEqualToString: @"layer"] ) { return; }
std::lock_guard<std::mutex> lock(this->_lock);
[this->_mtlCAMetalLayer release];
this->_mtlCAMetalLayer = nil;
this->setConfigurationResult(VK_ERROR_SURFACE_LOST_KHR);
[this->_layerObserver release];
this->_layerObserver = nil;
} forObject: _mtlCAMetalLayer.delegate atKeyPath: @"layer"];
}
MVKSurface::~MVKSurface() {

View File

@ -57,6 +57,7 @@ MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT)
MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS)
MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET)
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE)
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET)

View File

@ -2608,6 +2608,23 @@ MVK_PUBLIC_SYMBOL void vkSubmitDebugUtilsMessageEXT(
MVKTraceVulkanCallEnd();
}
#pragma mark -
#pragma mark VK_EXT_metal_surface extension
MVK_PUBLIC_SYMBOL VkResult vkCreateMetalSurfaceEXT(
VkInstance instance,
const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface) {
MVKTraceVulkanCallStart();
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
MVKSurface* mvkSrfc = mvkInst->createSurface(pCreateInfo, pAllocator);
*pSurface = (VkSurfaceKHR)mvkSrfc;
VkResult rslt = mvkSrfc->getConfigurationResult();
MVKTraceVulkanCallEnd();
return rslt;
}
#pragma mark -
#pragma mark iOS & macOS surface extensions